Per-conntrack timeout target v3
Subsystems (2)
RFC PATCH 1/1 Per-conntrack timeout target v3
Some further updates/optimizations to my original posting. This version handles all protocols now. Anyone besides me think this is useful?
***
I use a fairly short 2 hour established timeout on firewalls I operate, which works fine for most purposes. Occasionally, however, it would be nice to have a longer timeout for *certain* types of traffic such as SSH or telnet sessions.
So, below find a TIMEOUT target to enable such per-conntrack timeouts. Syntax for SSH would be something like:
iptables -A foo -p tcp --dport 22 -j TIMEOUT --timeout 123456
iptables -A foo -p tcp --dport 22 -j ACCEPTIt could of course also be used to lower the timeouts on some traffic, such as HTTP.
Phil
include/linux/netfilter/nf_conntrack_common.h +4 -0
@@ -73,6 +73,10 @@/* Connection has fixed timeout. */ IPS_FIXED_TIMEOUT_BIT =10 ,IPS_FIXED_TIMEOUT = (1 <<IPS_FIXED_TIMEOUT_BIT ), + +/* Connection has a manually configured timeout. */ +IPS_MANUAL_TIMEOUT_BIT =11 , + IPS_MANUAL_TIMEOUT = (1 << IPS_MANUAL_TIMEOUT_BIT), };/* Connection tracking event bits */
include/linux/netfilter/xt_TIMEOUT.h +17 -0
@@ -0,0 +1,17 @@ +#ifndef _XT_TIMEOUT_H +#define _XT_TIMEOUT_H + +struct nf_conn_timeout { +u_int32_t timeout; +}; + +#ifdef __KERNEL__ +#include <net/netfilter/nf_conntrack_extend.h> + +static inline struct nf_conn_timeout *nfct_timeout (const struct nf_conn *ct) +{ +return nf_ct_ext_find (ct,NF_CT_EXT_TIMEOUT ); +} +#endif + +#endif /*_XT_TIMEOUT_H*/
include/net/netfilter/nf_conntrack_extend.h +2 -0
@@ -7,11 +7,13 @@ {NF_CT_EXT_HELPER ,NF_CT_EXT_NAT , +NF_CT_EXT_TIMEOUT , NF_CT_EXT_NUM, };#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat +#define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout/* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext {
net/netfilter/Kconfig +11 -0
@@ -365,6 +365,17 @@ If you want to compile it as a module, say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. +config NETFILTER_XT_TARGET_TIMEOUT + tristate '"TIMEOUT" target support' + depends on NETFILTER_XTABLES + depends on NF_CONNTRACK + help + The TIMEOUT target allows you to alter the timeout of specific + sessions in the conntrack/NAT subsystem. Specific conntracks can + be given longer or shorter timeouts than the global defaults. + + If unsure, say `N'. + config NETFILTER_XT_TARGET_SECMARK tristate '"SECMARK" target support' depends on NETFILTER_XTABLES && NETWORK_SECMARK
net/netfilter/Makefile +1 -0
@@ -48,6 +48,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o +obj-$(CONFIG_NETFILTER_XT_TARGET_TIMEOUT) += xt_TIMEOUT.o obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o # matches
net/netfilter/nf_conntrack_proto_generic.c +9 -1
@@ -11,6 +11,7 @@#include <linux/timer.h> #include <linux/netfilter.h> #include <net/netfilter/nf_conntrack_l4proto.h> +#include <linux/netfilter/xt_TIMEOUT.h> static unsigned int nf_ct_generic_timeout__read_mostly =600 *HZ ;
@@ -55,7 +56,14 @@ int pf, unsigned int hooknum) { -nf_ct_refresh_acct (conntrack ,ctinfo ,skb ,nf_ct_generic_timeout ); +unsigned int timeout; + +if (test_bit (IPS_MANUAL_TIMEOUT_BIT , &conntrack->status)) + timeout =nfct_timeout (conntrack)->timeout; +else + timeout = nf_ct_generic_timeout; + +nf_ct_refresh_acct (conntrack, ctinfo, skb, timeout);return NF_ACCEPT ; }
net/netfilter/nf_conntrack_proto_gre.c +8 -2
@@ -36,6 +36,7 @@#include <net/netfilter/nf_conntrack_core.h> #include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_pptp.h> +#include <linux/netfilter/xt_TIMEOUT.h> #define GRE_TIMEOUT (30 * HZ)#define GRE_STREAM_TIMEOUT (180 * HZ)
@@ -217,11 +218,16 @@ int pf, unsigned int hooknum) { +unsigned int timeout; +/* If we've seen traffic both ways, this is a GRE connection. * Extend timeout. */ if (ct->status &IPS_SEEN_REPLY ) { -nf_ct_refresh_acct (ct, ctinfo, skb, - ct->proto.gre.stream_timeout); +if (test_bit (IPS_MANUAL_TIMEOUT_BIT , &ct->status)) + timeout =nfct_timeout (ct)->timeout; +else + timeout = ct->proto.gre.stream_timeout; +nf_ct_refresh_acct (ct, ctinfo, skb, timeout);/* Also, more likely to be important, and not a probe. */ set_bit (IPS_ASSURED_BIT , &ct->status);nf_conntrack_event_cache (IPCT_STATUS , skb);
net/netfilter/nf_conntrack_proto_sctp.c +9 -1
@@ -24,6 +24,7 @@#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h> +#include <linux/netfilter/xt_TIMEOUT.h> /* Protects conntrack->proto.sctp */ static DEFINE_RWLOCK (sctp_lock);
@@ -298,6 +299,7 @@sctp_chunkhdr_t _sch, *sch;u_int32_t offset, count;char map[256 /sizeof (char )] = {0 }; +unsigned int timeout; sh =skb_header_pointer (skb, dataoff,sizeof (_sctph), &_sctph);if (sh ==NULL )
@@ -387,7 +389,13 @@write_unlock_bh (&sctp_lock); } -nf_ct_refresh_acct (conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]); +if (test_bit (IPS_MANUAL_TIMEOUT_BIT , &conntrack->status) + && newconntrack ==SCTP_CONNTRACK_ESTABLISHED ) + timeout =nfct_timeout (conntrack)->timeout; +else + timeout = *sctp_timeouts[newconntrack]; + +nf_ct_refresh_acct (conntrack, ctinfo, skb, timeout);if (oldsctpstate ==SCTP_CONNTRACK_COOKIE_ECHOED && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
net/netfilter/nf_conntrack_proto_tcp.c +8 -3
@@ -24,6 +24,7 @@#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h> +#include <linux/netfilter/xt_TIMEOUT.h> /* Protects conntrack->proto.tcp */ static DEFINE_RWLOCK (tcp_lock);
@@ -941,9 +942,13 @@ && (new_state ==TCP_CONNTRACK_FIN_WAIT || new_state == TCP_CONNTRACK_CLOSE)) conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; - timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans - && *tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans - ? nf_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state]; +if (test_bit (IPS_MANUAL_TIMEOUT_BIT , &conntrack->status) + && new_state ==TCP_CONNTRACK_ESTABLISHED ) + timeout =nfct_timeout (conntrack)->timeout; +else + timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans + && *tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans + ? nf_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];write_unlock_bh (&tcp_lock);nf_conntrack_event_cache (IPCT_PROTOINFO_VOLATILE , skb);
net/netfilter/nf_conntrack_proto_udp.c +8 -2
@@ -21,6 +21,7 @@#include <linux/netfilter_ipv6.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h> +#include <linux/netfilter/xt_TIMEOUT.h> static unsigned int nf_ct_udp_timeout__read_mostly =30 *HZ ;static unsigned int nf_ct_udp_timeout_stream__read_mostly =180 *HZ ;
@@ -74,11 +75,16 @@ int pf, unsigned int hooknum) { +unsigned long timeout; +/* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ if (test_bit (IPS_SEEN_REPLY_BIT , &conntrack->status)) { -nf_ct_refresh_acct (conntrack, ctinfo, skb, - nf_ct_udp_timeout_stream); +if (test_bit (IPS_MANUAL_TIMEOUT_BIT , &conntrack->status)) + timeout =nfct_timeout (conntrack)->timeout; +else + timeout = nf_ct_udp_timeout_stream; +nf_ct_refresh_acct (conntrack, ctinfo, skb, timeout);/* Also, more likely to be important, and not a probe */ if (!test_and_set_bit (IPS_ASSURED_BIT , &conntrack->status))nf_conntrack_event_cache (IPCT_STATUS , skb);
net/netfilter/nf_conntrack_proto_udplite.c +8 -2
@@ -22,6 +22,7 @@#include <linux/netfilter_ipv6.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h> +#include <linux/netfilter/xt_TIMEOUT.h> static unsigned int nf_ct_udplite_timeout__read_mostly =30 *HZ ;static unsigned int nf_ct_udplite_timeout_stream__read_mostly =180 *HZ ;
@@ -73,11 +74,16 @@ int pf, unsigned int hooknum) { +unsigned long timeout; +/* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ if (test_bit (IPS_SEEN_REPLY_BIT , &conntrack->status)) { -nf_ct_refresh_acct (conntrack, ctinfo, skb, - nf_ct_udplite_timeout_stream); +if (test_bit (IPS_MANUAL_TIMEOUT_BIT , &conntrack->status)) + timeout =nfct_timeout (conntrack)->timeout; +else + timeout = nf_ct_udplite_timeout_stream; +nf_ct_refresh_acct (conntrack, ctinfo, skb, timeout);/* Also, more likely to be important, and not a probe */ if (!test_and_set_bit (IPS_ASSURED_BIT , &conntrack->status))nf_conntrack_event_cache (IPCT_STATUS , skb);
net/netfilter/xt_TIMEOUT.c +121 -0
121 lines not on this page · raw message
extensions/libxt_TIMEOUT.c +111 -0
111 lines not on this page · raw message
extensions/Makefile +1 -1
@@ -7,7 +7,7 @@ # PF_EXT_SLIB:=ah addrtype conntrack ecn icmp iprange owner policy realm recent tos ttl unclean CLUSTERIP DNAT ECN LOG MASQUERADE MIRROR NETMAP REDIRECT REJECT SAME SNAT TOS TTL ULOG PF6_EXT_SLIB:=ah dst eui64 frag hbh hl icmp6 ipv6header mh owner policy rt HL LOG REJECT -PFX_EXT_SLIB:=connbytes connmark connlimit comment dccp dscp esp hashlimit helper length limit mac mark multiport physdev pkttype quota sctp state statistic standard string tcp tcpmss time u32 udp CLASSIFY CONNMARK DSCP MARK NFLOG NFQUEUE NOTRACK TCPMSS TRACE +PFX_EXT_SLIB:=connbytes connmark connlimit comment dccp dscp esp hashlimit helper length limit mac mark multiport physdev pkttype quota sctp state statistic standard string tcp tcpmss time u32 udp CLASSIFY CONNMARK DSCP MARK NFLOG NFQUEUE NOTRACK TCPMSS TRACE TIMEOUT PF_EXT_SELINUX_SLIB:= PF6_EXT_SELINUX_SLIB:=
include/linux/netfilter/xt_TIMEOUT.h +17 -0
@@ -0,0 +1,17 @@ +#ifndef _XT_TIMEOUT_H +#define _XT_TIMEOUT_H + +struct nf_conn_timeout { +u_int32_t timeout; +}; + +#ifdef __KERNEL__ +#include <net/netfilter/nf_conntrack_extend.h> + +static inline struct nf_conn_timeout *nfct_timeout (const struct nf_conn *ct) +{ +return nf_ct_ext_find (ct,NF_CT_EXT_TIMEOUT ); +} +#endif + +#endif /*_XT_TIMEOUT_H*/
Quoted 6 lines · Phil Oester
I use a fairly short 2 hour established timeout on firewalls I operate, which works fine for most purposes. Occasionally, however, it would be nice to have a longer timeout for *certain* types of traffic such as SSH or telnet sessions.
Quoted 9 lines
So, below find a TIMEOUT target to enable such per-conntrack timeouts. Syntax for SSH would be something like:
iptables -A foo -p tcp --dport 22 -j TIMEOUT --timeout 123456 iptables -A foo -p tcp --dport 22 -j ACCEPTIt could of course also be used to lower the timeouts on some traffic, such as HTTP.
Considering TCP only...
If my firewall allows 'NEW' connections (-m conntrack --ctstate NEW) on non-SYN packets, what good will xt_TIMEOUT do? If the ct entry times out, a new one will be created once the next packet flows.
Quoted 5 lines · Jan Engelhardt
Considering TCP only...
If my firewall allows 'NEW' connections (-m conntrack --ctstate NEW) on non-SYN packets, what good will
xt_TIMEOUTdo? If the ct entry times out, a new one will be created once the next packet flows.
Correct - in this case, it will not help at all. But many rulesets require (--state NEW) to be --syn, where this would help.
Phil
Quoted 10 lines · Phil Oester
Some further updates/optimizations to my original posting. This version handles all protocols now. Anyone besides me think this is useful?
***
I use a fairly short 2 hour established timeout on firewalls I operate, which works fine for most purposes. Occasionally, however, it would be nice to have a longer timeout for *certain* types of traffic such as SSH or telnet sessions.
Quoted 8 lines
So, below find a TIMEOUT target to enable such per-conntrack timeouts. Syntax for SSH would be something like:
iptables -A foo -p tcp --dport 22 -j TIMEOUT --timeout 123456 iptables -A foo -p tcp --dport 22 -j ACCEPTIt could of course also be used to lower the timeouts on some traffic, such as HTTP.
I think the patch is useful, but I wonder how long it will take until people want to override timeouts for other connection states. I'm also looking for a way to pass parameters for new connections to helpers (most of the things that are currently module parameters), so maybe we could generalize this to a conntrack parameter target?
Quoted 5 lines · Patrick McHardy
I think the patch is useful, but I wonder how long it will take until people want to override timeouts for other connection states. I'm also looking for a way to pass parameters for new connections to helpers (most of the things that are currently module parameters), so maybe we could generalize this to a conntrack parameter target?
In thinking about this, it seems like a HELPER target would be useful, for instance if some random FTP server ran on a non-standard port and we wanted the FTP helper to be used. Something like:
-s X -p 210 -j HELPER --helper ftp
Or did you have something else in mind, such as being able to change the _global_ ports in use by the FTP helper? (or both?)
I suppose we could allow adjustment of other timeouts by having multiple arguments to -j TIMEOUT, such as --syn_sent, --syn_recv, etc. though the check() becomes more complicated between the various protos.
Phil
Quoted 7 lines · Phil Oester
Quoted 5 lines · Patrick McHardy
I think the patch is useful, but I wonder how long it will take until people want to override timeouts for other connection states. I'm also looking for a way to pass parameters for new connections to helpers (most of the things that are currently module parameters), so maybe we could generalize this to a conntrack parameter target?
Quoted 5 lines
In thinking about this, it seems like a HELPER target would be useful, for instance if some random FTP server ran on a non-standard port and we wanted the FTP helper to be used. Something like:
-s X -p 210 -j HELPER --helper ftp
BTW, the helper code is said to already do that (man iptables):
--helper ftp-2121
Quoted 9 lines · Jan Engelhardt
Quoted 5 lines
In thinking about this, it seems like a HELPER target would be useful, for instance if some random FTP server ran on a non-standard port and we wanted the FTP helper to be used. Something like:
-s X -p 210 -j HELPER --helper ftpBTW, the helper code is said to already do that (man iptables):
--helper ftp-2121
Actually that's for the helper _match_, so you could for instance match packets which are part of a helper configured on a non-standard port via module parameter. So this is different, in that it would allow you to specify non-standard ports at runtime.
Phil
Quoted 11 lines · Phil Oester
Quoted 5 lines · Patrick McHardy
I think the patch is useful, but I wonder how long it will take until people want to override timeouts for other connection states. I'm also looking for a way to pass parameters for new connections to helpers (most of the things that are currently module parameters), so maybe we could generalize this to a conntrack parameter target?
In thinking about this, it seems like a HELPER target would be useful, for instance if some random FTP server ran on a non-standard port and we wanted the FTP helper to be used. Something like:
Quoted 8 lines
-s X -p 210 -j HELPER --helper ftpOr did you have something else in mind, such as being able to change the _global_ ports in use by the FTP helper? (or both?)
I suppose we could allow adjustment of other timeouts by having multiple arguments to -j TIMEOUT, such as --syn_sent, --syn_recv, etc. though the
check()becomes more complicated between the various protos.
Long delay due to Christmas, sorry ..
Yes, manually attaching helpers would also be useful, but I was mainly thinking of helper-specific parameters, like in the case of FTP, "loose", for SIP the timeouts, etc.
Ideally such a target should support both.
Quoted 6 lines · Phil Oester
Quoted 5 lines · Jan Engelhardt
Quoted 5 lines
In thinking about this, it seems like a HELPER target would be useful, for instance if some random FTP server ran on a non-standard port and we wanted the FTP helper to be used. Something like:
-s X -p 210 -j HELPER --helper ftp
Quoted 8 lines
Quoted 3 lines
BTW, the helper code is said to already do that (man iptables):
--helper ftp-2121Actually that's for the helper _match_, so you could for instance match packets which are part of a helper configured on a non-standard port via module parameter. So this is different, in that it would allow you to specify non-standard ports at runtime.
One of the really nice things about this is that it makes helpers explicit. I never liked the automatic tracking very much since helpers effectively change your ruleset, and there isn't even a way to disable them selectively besides blocking connections completely.