aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-08-24 17:22:08 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2018-09-10 19:29:24 -0400
commitf94e63801ab2791ed64c409d0f751f6a0c953ead (patch)
treefc083aac1dde0e5f89e969d14c7ae2adee4b2191
parent7acfda539c0b9636a58bfee56abfb3aeee806d96 (diff)
netfilter: conntrack: reset tcp maxwin on re-register
Doug Smythies says: Sometimes it is desirable to temporarily disable, or clear, the iptables rule set on a computer being controlled via a secure shell session (SSH). While unwise on an internet facing computer, I also do it often on non-internet accessible computers while testing. Recently, this has become problematic, with the SSH session being dropped upon re-load of the rule set. The problem is that when all rules are deleted, conntrack hooks get unregistered. In case the rules are re-added later, its possible that tcp window has moved far enough so that all packets are considered invalid (out of window) until entry expires (which can take forever, default established timeout is 5 days). Fix this by clearing maxwin of existing tcp connections on register. v2: don't touch entries on hook removal. v3: remove obsolete expiry check. Reported-by: Doug Smythies <dsmythies@telus.net> Fixes: 4d3a57f23dec59 ("netfilter: conntrack: do not enable connection tracking unless needed") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/nf_conntrack_proto.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 9f14b0df6960..51c5d7eec0a3 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -776,9 +776,26 @@ static const struct nf_hook_ops ipv6_conntrack_ops[] = {
776}; 776};
777#endif 777#endif
778 778
779static int nf_ct_tcp_fixup(struct nf_conn *ct, void *_nfproto)
780{
781 u8 nfproto = (unsigned long)_nfproto;
782
783 if (nf_ct_l3num(ct) != nfproto)
784 return 0;
785
786 if (nf_ct_protonum(ct) == IPPROTO_TCP &&
787 ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) {
788 ct->proto.tcp.seen[0].td_maxwin = 0;
789 ct->proto.tcp.seen[1].td_maxwin = 0;
790 }
791
792 return 0;
793}
794
779static int nf_ct_netns_do_get(struct net *net, u8 nfproto) 795static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
780{ 796{
781 struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id); 797 struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
798 bool fixup_needed = false;
782 int err = 0; 799 int err = 0;
783 800
784 mutex_lock(&nf_ct_proto_mutex); 801 mutex_lock(&nf_ct_proto_mutex);
@@ -798,6 +815,8 @@ static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
798 ARRAY_SIZE(ipv4_conntrack_ops)); 815 ARRAY_SIZE(ipv4_conntrack_ops));
799 if (err) 816 if (err)
800 cnet->users4 = 0; 817 cnet->users4 = 0;
818 else
819 fixup_needed = true;
801 break; 820 break;
802#if IS_ENABLED(CONFIG_IPV6) 821#if IS_ENABLED(CONFIG_IPV6)
803 case NFPROTO_IPV6: 822 case NFPROTO_IPV6:
@@ -814,6 +833,8 @@ static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
814 ARRAY_SIZE(ipv6_conntrack_ops)); 833 ARRAY_SIZE(ipv6_conntrack_ops));
815 if (err) 834 if (err)
816 cnet->users6 = 0; 835 cnet->users6 = 0;
836 else
837 fixup_needed = true;
817 break; 838 break;
818#endif 839#endif
819 default: 840 default:
@@ -822,6 +843,11 @@ static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
822 } 843 }
823 out_unlock: 844 out_unlock:
824 mutex_unlock(&nf_ct_proto_mutex); 845 mutex_unlock(&nf_ct_proto_mutex);
846
847 if (fixup_needed)
848 nf_ct_iterate_cleanup_net(net, nf_ct_tcp_fixup,
849 (void *)(unsigned long)nfproto, 0, 0);
850
825 return err; 851 return err;
826} 852}
827 853