Firewall rule : How to drop TCP connection lasting more than 3 hours

Hello

In order to limit my IPTV download to 3 hours, I would like to set up a rule in the firewall that router-marks it as “dropped” if the TCP connection has lasted for more than 3 hours.

Anyone can please write me the rule ?

Thanks

I think you can do that under connections tab in firewall tracking, just set TCP Established Timeout to 3hrs.

Thanks, I see that.

However my intention is to only mark as dropped the TCP packets that have a specific IP address source/destination port.

Is your intention to cut live connections or zombie connections which remain open but do not transport any data?

The point is that the connection properties only contain the connection’s remaining lifetime which gets reset to the globally set one for that protocol (i.e. 24 hours in case of default setting for TCP) with each packet passing, including the keepalive ones. So not only that there is no readily available match condition to create the rule you want, but even using scripting you cannot just filter connections which exist for longer than 3h and remove them (causing the session to fail). So it would only be possible for connections in which the last packet was seen 3h ago, and that doesn’t help you much.

So you need to periodcially spawn a “Victor the cleaner” script which will (roughly) identify any new connection established to the IPTV server since its last run, save a reference to it with the timestamp of the first detection, and remove any of the existing connections of this type if more than 3h have elapsed from its detection.

Worse than that, it is a nightmare to calculate “now+3h” using RouterOS scripting, so it is much simpler to have the array of references to the connections organized as a circular buffer, and use the index to that array as an IP address which you put to an /ip firewall address-list with a timeout of 3 hours and remove the connection once that address disappears from the list. The fact that it needs to be a global array, so that the individual reincarnations of the script could write to it, makes it even more complex.

Don’t you have an easier task :slight_smile: ?

Thanks for your insight. I feared it was more difficult that first thought.

My IPTV application on AppleTV does not check for timeout, which means that if I leave the channel viewing on for hours (for example by falling asleep), the streaming will continue non stop and use unwanted bandwidth. During all the viewing process, the same TCP connection remains active. There is only a new TCP connection when changing TV channel.

Hence my intention to limit the streaming to X hours by time-limiting any single TCP connection from the IPTV servers.

I guess I will have to go via the script route, unless someone has a better idea.

Thanks for helping !

Well, put this way it sounds to me much simpler - just kill all IPTV connections (identified by the IP addresses of the servers) three hours after the last press of the programmable button :slight_smile:

More seriously, you’ve actually simplified the task a lot. As you say there is actually only one such connection at a time, you can leave out the array part and simply count the time elapsed from establishment of any such connection, which is ways simpler because you don’t need to refer to a particular connection (identified by apair of sockets) and it is enough to use the server address alone. This simpler task can be solved without srcipting.

The idea would be the following then:

  • you would add the IP address of the particular IPTV server to an /ip firewall address-list list=IPTV-timer each time the client would send a SYN packet to it (i.e. establishing a new connection), with a timeout of 3 hours
  • you would insert a rule between the usual “fastrrack established,related ; accept established,related” ones in chain=forward which would send all packets from any of the IPTV servers to a custom chain
  • in the custom chain you would have a rule with action=reject reject-with=tcp-reset src-address-list=!IPTV-timer

The point is that even if a connection is fasttracked, some of its packets in both directions intentionally take the standard path in order to refresh the connection state. That’s why the “accept” rule must follow the “fasttrack” one. And to break the connection, it is sufficient to send a RST to the server, although sending a RST also to the client would be even better.

How do you identify the IPTV servers? Do you have a domain name for them or a fixed list of addresses you know to never ever change?

Yes, the IPTV stream comes from the same subnet.

But I think I have found a workaround.

There is a possibility of mangling packets based on the size of the Connection Bytes.

I could estimate the total connection bytes of a 3 hours streaming TV, and then mark the route and route it to junk…

You don’t need to mangle it, you can use the connection-bytes matcher directly in the filter, so you can put a rule sending the TCP RST if the byte count exceeds some magic number to the place I’ve indicated before and you’re good.
I don’t know how reliable is the conversion of connection bytes to time because I don’t know whether all channels use the same bitrate, that’s why I haven’t suggested you this way.
Also, the maximum count of bytes it can match is 4 Gbytes, so I don’t know whether that’s sufficient for 3 hours of HD video.

Thanks, however on Mikrotik Wiki, I see no limitation for count of byte match. Will have a deeper look as it might indeed be a bit short for HD IPTV 3 hours of viewing.

(update) Oh yes, anything above 4000M is forbidden…

If you can identify the traffic by IP or port then you could use two addresslist. The first set the IP to be blocked for 24 hours. The second one allows for three hours.

On set:

Put IP destination address in three hour list if not in the 24 hour list
Put IP destination address in in 24 hour list if it is in the three hour list

If the end time is constantly updated in the 24 hour list then set the timeout to 21 hours.

Filter the traffic:

Accept if destination address is still in the allow list (for 3 hours)
Drop if destination address is still in the deny list (for 24 hours)

you mean that filter action should be “add src to address list” ?

If you add the source then it could be working for several tv/set-topbox/tablet/phone independent but I don’t think that will be doable.

Using destination you can control access to the destination the IPTV is transmitted from, this if it is one source.

Update: have made an first setup and 10.20.20.0/24 is by example the IPTV network:

/ip firewall mangle
add action=accept chain=prerouting dst-address-list=3hour connection-state=established,related
add action=add-dst-to-address-list address-list=3hour address-list-timeout=3h chain=prerouting connection-state=new dst-address=10.20.20.0/24 dst-address-list=!24hour log=yes log-prefix="Begin IPTV grace period"
add action=add-dst-to-address-list address-list=24hour address-list-timeout=1d chain=prerouting connection-state=new dst-address=10.20.20.0/24 dst-address-list=!24hour log=yes log-prefix="Begin IPTV free time"
/ip firewall filter
add action=accept protocol=tcp chain=forward connection-state=established,related dst-address-list=3hour
add action=reject reject-with=tcp-reset protocol=tcp chain=forward connection-state=established,related dst-address=10.20.20.0/24
add action=reject chain=forward connection-state=established,related disabled=yes dst-address=10.20.20.0/24 protocol=udp reject-with=icmp-host-unreachable

To me you have also end the UDP stream otherwise that will be pushed to your address and I hope this is the correct way to kill UDP from the IPTV server.

If you have a fixed IP for a device you can use src-address fot only apply this setup to that device. Other devices can still use the IPTV and will experience a disturbance when the three hours are up for that other device.