Currently DNS resolvers that send both A and AAAA queries from same source port can trigger stream mode prematurely, which results in non-early-evictable conntrack entry for three minutes, even though DNS requests are done in a few milliseconds. Add a two second grace period where we continue to use the ordinary 30-second default timeout. Its enough for DNS request/response traffic, even if two request/reply packets are involved. ASSURED is still set, else conntrack (and thus a possible NAT mapping ...) gets zapped too in case conntrack table runs full.
Unified · Split
| @@ -27,12 +27,17 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include <net/netfilter/nf_conntrack_tuple.h> | 28 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 29 | 29 | ||
| 30 | struct nf_ct_udp { | ||
| 31 | unsigned long stream_ts; | ||
| 32 | }; | ||
| 33 | |||
| 30 | /* per conntrack: protocol private data */ | 34 | /* per conntrack: protocol private data */ |
| 31 | union nf_conntrack_proto { | 35 | union nf_conntrack_proto { |
| 32 | /* insert conntrack proto private data here */ | 36 | /* insert conntrack proto private data here */ |
| 33 | struct nf_ct_dccp dccp; | 37 | struct nf_ct_dccp dccp; |
| 34 | struct ip_ct_sctp sctp; | 38 | struct ip_ct_sctp sctp; |
| 35 | struct ip_ct_tcp tcp; | 39 | struct ip_ct_tcp tcp; |
| 40 | struct nf_ct_udp udp; | ||
| 36 | struct nf_ct_gre gre; | 41 | struct nf_ct_gre gre; |
| 37 | unsigned int tmpl_padto; | 42 | unsigned int tmpl_padto; |
| 38 | }; | 43 | }; |
| @@ -100,11 +100,21 @@ static int udp_packet(struct nf_conn *ct, · 99 unmodified lines | |||
| 100 | if (!timeouts) | 100 | if (!timeouts) |
| 101 | timeouts = udp_get_timeouts(nf_ct_net(ct)); | 101 | timeouts = udp_get_timeouts(nf_ct_net(ct)); |
| 102 | 102 | ||
| 103 | if (!nf_ct_is_confirmed(ct)) | ||
| 104 | ct->proto.udp.stream_ts = 2 * HZ + jiffies; | ||
| 105 | |||
| 103 | /* If we've seen traffic both ways, this is some kind of UDP | 106 | /* If we've seen traffic both ways, this is some kind of UDP |
| 104 | stream. Extend timeout. */ | 107 | * stream. Set Assured. |
| 108 | */ | ||
| 105 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { | 109 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
| 106 | nf_ct_refresh_acct(ct, ctinfo, skb, | 110 | unsigned long extra = timeouts[UDP_CT_UNREPLIED]; |
| 107 | timeouts[UDP_CT_REPLIED]); | 111 | |
| 112 | /* Still active after two seconds? Extend timeout. */ | ||
| 113 | if (time_after(jiffies, ct->proto.udp.stream_ts)) | ||
| 114 | extra = timeouts[UDP_CT_REPLIED]; | ||
| 115 | |||
| 116 | nf_ct_refresh_acct(ct, ctinfo, skb, extra); | ||
| 117 | |||
| 108 | /* Also, more likely to be important, and not a probe */ | 118 | /* Also, more likely to be important, and not a probe */ |
| 109 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) | 119 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) |
| 110 | nf_conntrack_event_cache(IPCT_ASSURED, ct); | 120 | nf_conntrack_event_cache(IPCT_ASSURED, ct); |