5

Is it possible to limit the maximum duration of a TCP connection with iptables?

With iptables I can limit the number of concurrent TCP connections per IP address, by using -m connlimit, and I can also limit the number of new connections per IP address per time interval, by using -m hashlimit. I'm currently using these rules to get the desired effect:

iptables -A INPUT -m tcp -p tcp --syn --dport 80 -m connlimit --connlimit-above 10 -j DROP
iptables -A INPUT -m tcp -p tcp --dport 80 -m state --state NEW -m hashlimit --hashlimit-above 15/min --hashlimit-burst 10 --hashlimit-mode srcip --hashlimit-name rtlimit -j DROP

However, is there a way to ensure that an "established" TCP connection will be closed after at most n seconds, in order to prevent "long-standing" connections? (regardless of still "active" or not)

I see people suggest:

iptables -A INPUT -p tcp --dport 80 -m state --state RELATED,ESTABLISHED -m limit --limit 1/minute -j DROP

However, I don't think this really does what I want. To my understanding, above rule would drop all packets that are belonging to an "established" connection and that are coming in at a rate "faster" than one packet per minute. It doesn't close a connection after 1 minute elapsed, or does it?

Is there any way to actually accomplish this with iptables?

2
  • Is it a requirement that the iptables command itself to be used to set the limit? Or is it enough if the limit applies to connections managed by iptables, but the limit itself is set with another command?
    – DericS
    Jan 15, 2022 at 20:11
  • It would be okay, I think.
    – Pygoscelis
    Jan 20, 2022 at 19:23

2 Answers 2

3

UPDATE: There are two issues with my answer. 1) I did not address the part of the question that states 'regardless of still "active" or not'; and 2) The question is about closing the socket at the endpoint(s) of the connection and not about removing the connection from the tracking of iptables (netfilter). END UPDATE.

I see two options here:

Option 1 - global

Limit the idle timeout value of an established connection, for all connections by modifying the appropriate global netfilter variable.

Verify the current default value with:

cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established

Modify the default value (for example, to 600 seconds) with:

echo 600 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established

Option 2 - granular

Limit the idle timeout value of an established connection, for specific connections, by setting up a timeout policy and using that policy with the iptables command.

Setup a timeout policy with:

nfct add timeout nam1 inet tcp established 600

Apply that policy to iptables rules:

iptables -I PREROUTING -t raw -p tcp -j CT --timeout nam1
iptables -I OUTPUT -t raw -p tcp -j CT --timeout nam1

You might need to install the nfct tool, which on debian / ubuntu, comes from the package with the same name (nfct).

Additional info

man iptables-extensions shows some information on the CT target.

man nfct shows an example which is close to the information you requested. (You may have issues using the timeout policy with a name of more than four characters in length.)

The conntrack tool can be useful for following what's going on at different events of the connection (e.g. conntrack -E -p tcp).

2
  • Thanks! This seemed like a great solution, but turns out to not work. After setting up a 30 seconds timeout, using the method outlined in the nfct manpage, I was able to actually observe a [DESTROY] message after 30 seconds in the output of conntrack -E -p tcp on "my" connection – only that this did not close the connection at all! With ss I can see the connection (socket) is still there (EASTAB). Indeed, the connection (LDAP session in this case) was still up and working as if nothing had happened. Any ideas? With ss --kill I can close the connection, and that does work.
    – Pygoscelis
    Jan 20, 2022 at 19:26
  • Ah, I think I better understand your question now. I've provided a way to lower a timeout for the iptables connection entries. You're concern is not with iptables itself. You want to have the socket connections into/out of your system have a limited lifetime. We may be able to use iptables to make your socket connections stop working after the timeout (by adding a few more rules to what's already in this answer). I'm not sure we'll be able to cleanly close those socket connections after the timeout.
    – DericS
    Jan 21, 2022 at 3:17
2

I have now come up with a different "solution":

I wrote a small script that runs as a cronjob (once per minute) and that dumps all "established" connections into a file, by using the ss command and a bit of grep magic. I also keep the "old" file from the previous run. This way I can identify the connections that have "persisted" since the previous run, by concatenating the two files and then using sort plus uniq -d. These connections will then explicitly be closed, by using the ss --kill command. Seems to work for me.

(yes, this isn't an exact timeout, but probably "good enough" for my purpose)


List currently "established" connections:

ss -o state established

Get only "duplicate" lines:

cat file1.txt file2.txt | sort | uniq -d

Close connection, for example:

s --kill -o state established "( dst ${ip} and dport = ${port} )"
3
  • 1
    Please don't provide vague answers that make people guess how the solution could look like; instead provide a working answer that people can understand and comment on.
    – U. Windl
    Jan 22, 2022 at 23:56
  • How is that answer vague? Using ss to "manually" investigate the established connections and using ss --kill to destroy "persistent" connections is the best "solution" that I have managed to come up with. If you know for a better way to accomplish this, e.g. with iptables rules, then please feel free to share it. Until then I think that sharing "my" solution should be fine...
    – Pygoscelis
    Jan 23, 2022 at 13:09
  • 1
    Some more details on how I call ss command has been added.
    – Pygoscelis
    Jan 23, 2022 at 14:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .