aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorGao Feng <fgao@ikuai8.com>2016-09-22 02:53:53 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-09-25 08:54:01 -0400
commit8d11350f5f33378efc5f905bee325f3e76d6bcca (patch)
tree4065e58f4f95f606ce26341a5b1135ab66e673d7 /net/netfilter
parente3b37f11e6e4e6b6f02cc762f182ce233d2c1c9d (diff)
netfilter: seqadj: Fix the wrong ack adjust for the RST packet without ack
It is valid that the TCP RST packet which does not set ack flag, and bytes of ack number are zero. But current seqadj codes would adjust the "0" ack to invalid ack number. Actually seqadj need to check the ack flag before adjust it for these RST packets. The following is my test case client is 10.26.98.245, and add one iptable rule: iptables -I INPUT -p tcp --sport 12345 -m connbytes --connbytes 2: --connbytes-dir reply --connbytes-mode packets -j REJECT --reject-with tcp-reset This iptables rule could generate on TCP RST without ack flag. server:10.172.135.55 Enable the synproxy with seqadjust by the following iptables rules iptables -t raw -A PREROUTING -i eth0 -p tcp -d 10.172.135.55 --dport 12345 -m tcp --syn -j CT --notrack iptables -A INPUT -i eth0 -p tcp -d 10.172.135.55 --dport 12345 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460 iptables -A OUTPUT -o eth0 -p tcp -s 10.172.135.55 --sport 12345 -m conntrack --ctstate INVALID,UNTRACKED -m tcp --tcp-flags SYN,RST,ACK SYN,ACK -j ACCEPT The following is my test result. 1. packet trace on client root@routers:/tmp# tcpdump -i eth0 tcp port 12345 -n tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes IP 10.26.98.245.45154 > 10.172.135.55.12345: Flags [S], seq 3695959829, win 29200, options [mss 1460,sackOK,TS val 452367884 ecr 0,nop,wscale 7], length 0 IP 10.172.135.55.12345 > 10.26.98.245.45154: Flags [S.], seq 546723266, ack 3695959830, win 0, options [mss 1460,sackOK,TS val 15643479 ecr 452367884, nop,wscale 7], length 0 IP 10.26.98.245.45154 > 10.172.135.55.12345: Flags [.], ack 1, win 229, options [nop,nop,TS val 452367885 ecr 15643479], length 0 IP 10.172.135.55.12345 > 10.26.98.245.45154: Flags [.], ack 1, win 226, options [nop,nop,TS val 15643479 ecr 452367885], length 0 IP 10.26.98.245.45154 > 10.172.135.55.12345: Flags [R], seq 3695959830, win 0, length 0 2. seqadj log on server [62873.867319] Adjusting sequence number from 602341895->546723267, ack from 3695959830->3695959830 [62873.867644] Adjusting sequence number from 602341895->546723267, ack from 3695959830->3695959830 [62873.869040] Adjusting sequence number from 3695959830->3695959830, ack from 0->55618628 To summarize, it is clear that the seqadj codes adjust the 0 ack when receive one TCP RST packet without ack. Signed-off-by: Gao Feng <fgao@ikuai8.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_conntrack_seqadj.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/net/netfilter/nf_conntrack_seqadj.c b/net/netfilter/nf_conntrack_seqadj.c
index dff0f0cc59e4..ef7063eced7c 100644
--- a/net/netfilter/nf_conntrack_seqadj.c
+++ b/net/netfilter/nf_conntrack_seqadj.c
@@ -169,7 +169,7 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
169 s32 seqoff, ackoff; 169 s32 seqoff, ackoff;
170 struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); 170 struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
171 struct nf_ct_seqadj *this_way, *other_way; 171 struct nf_ct_seqadj *this_way, *other_way;
172 int res; 172 int res = 1;
173 173
174 this_way = &seqadj->seq[dir]; 174 this_way = &seqadj->seq[dir];
175 other_way = &seqadj->seq[!dir]; 175 other_way = &seqadj->seq[!dir];
@@ -184,27 +184,31 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
184 else 184 else
185 seqoff = this_way->offset_before; 185 seqoff = this_way->offset_before;
186 186
187 newseq = htonl(ntohl(tcph->seq) + seqoff);
188 inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, false);
189 pr_debug("Adjusting sequence number from %u->%u\n",
190 ntohl(tcph->seq), ntohl(newseq));
191 tcph->seq = newseq;
192
193 if (!tcph->ack)
194 goto out;
195
187 if (after(ntohl(tcph->ack_seq) - other_way->offset_before, 196 if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
188 other_way->correction_pos)) 197 other_way->correction_pos))
189 ackoff = other_way->offset_after; 198 ackoff = other_way->offset_after;
190 else 199 else
191 ackoff = other_way->offset_before; 200 ackoff = other_way->offset_before;
192 201
193 newseq = htonl(ntohl(tcph->seq) + seqoff);
194 newack = htonl(ntohl(tcph->ack_seq) - ackoff); 202 newack = htonl(ntohl(tcph->ack_seq) - ackoff);
195
196 inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, false);
197 inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 203 inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack,
198 false); 204 false);
199 205 pr_debug("Adjusting ack number from %u->%u, ack from %u->%u\n",
200 pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
201 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), 206 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
202 ntohl(newack)); 207 ntohl(newack));
203
204 tcph->seq = newseq;
205 tcph->ack_seq = newack; 208 tcph->ack_seq = newack;
206 209
207 res = nf_ct_sack_adjust(skb, protoff, tcph, ct, ctinfo); 210 res = nf_ct_sack_adjust(skb, protoff, tcph, ct, ctinfo);
211out:
208 spin_unlock_bh(&ct->lock); 212 spin_unlock_bh(&ct->lock);
209 213
210 return res; 214 return res;