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 | 28 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 29 | 29 | |
| 30 | +struct nf_ct_udp { | |
| 31 | + unsigned long stream_ts; | |
| 32 | +}; | |
| 33 | + | |
| 30 | 34 | /* per conntrack: protocol private data */ |
| 31 | 35 | union nf_conntrack_proto { |
| 32 | 36 | /* insert conntrack proto private data here */ |
| 33 | 37 | struct nf_ct_dccp dccp; |
| 34 | 38 | struct ip_ct_sctp sctp; |
| 35 | 39 | struct ip_ct_tcp tcp; |
| 40 | + struct nf_ct_udp udp; | |
| 36 | 41 | struct nf_ct_gre gre; |
| 37 | 42 | unsigned int tmpl_padto; |
| 38 | 43 | }; |
| @@ -100,11 +100,21 @@ static int udp_packet(struct nf_conn *ct, · 99 unmodified lines | ||
| 100 | 100 | if (!timeouts) |
| 101 | 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 | 106 | /* If we've seen traffic both ways, this is some kind of UDP |
| 104 | − stream. Extend timeout. */ | |
| 107 | + * stream. Set Assured. | |
| 108 | + */ | |
| 105 | 109 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
| 106 | − nf_ct_refresh_acct(ct, ctinfo, skb, | |
| 107 | − timeouts[UDP_CT_REPLIED]); | |
| 110 | + unsigned long extra = timeouts[UDP_CT_UNREPLIED]; | |
| 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 | 118 | /* Also, more likely to be important, and not a probe */ |
| 109 | 119 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) |
| 110 | 120 | nf_conntrack_event_cache(IPCT_ASSURED, ct); |