From: Yasuyuki KOZAKAI <yasuyuki.kozakai@xxxxxxxxxxxxx> Date: Sat, 07 Jul 2007 15:27:06 +0900 (JST) > Hi, Jordan, > > I'll sort out observations from your report and try to explain my idea in > other mail after finishing some tests. OK, I try to explain what the current netfilter does in Jordan's situation. I also attach the patch to fix this problem. Jordan, can you try it ? Patrick, please consider to apply it. Even if following my idea is not correct, clearly it fixes a bug. I'm wondering why I missed '!' when I copied & pasted ip_conntrack_proto_icmp.c... - This situation occurred on 2.6.20.12 and 2.6.21.5 at least. - your rules are following *nat :PREROUTING ACCEPT [32:2910] :POSTROUTING ACCEPT [29:2330] :OUTPUT ACCEPT [2:152] -A PREROUTING -i eth1 -p tcp -m tcp --dport 25000 -j DNAT --to-destination 192.168.0.133 -A PREROUTING -i eth1 -p udp -m udp --dport 25000 -j DNAT --to-destination 192.168.0.133 -A POSTROUTING -o eth1 -j MASQUERADE COMMIT *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT DROP [0:0] -A INPUT -i lo -j ACCEPT -A INPUT -i eth0 -j ACCEPT -A INPUT -i eth1 -m state --state ESTABLISHED -j ACCEPT -A INPUT -i eth1 -j REJECT --reject-with icmp-port-unreachable -A INPUT -j DROP -A FORWARD -j ACCEPT -A OUTPUT -o lo -j ACCEPT -A OUTPUT -d 192.168.0.0/255.255.255.0 -o eth0 -j ACCEPT -A OUTPUT -d 192.168.0.0/255.255.255.0 -j LOG --log-prefix "[packet out wrong interface] " -A OUTPUT -o eth1 -j ACCEPT -A OUTPUT -j DROP COMMIT - ICMP error is generated by this router but destination address of it is strange. Jul 4 14:54:33 webby kernel: [packet out wrong interface] IN= OUT=eth1 SRC=123.23.23.23 DST=192.168.0.133 LEN=68 TOS=0x00 PREC=0xC0 TTL=64 ID=39698 PROTO=ICMP TYPE=3 CODE=3 [SRC=192.168.0.133 DST=123.23.23.23 LEN=40 TOS=0x00 PREC=0x20 TTL=239 ID=39262 PROTO=TCP SPT=25000 DPT=25000 WINDOW=64172 RES=0x00 RST URGP=0 ] - original TCP reset is following 14:54:33.931831 IP (tos 0x20, ttl 239, id 39262, offset 0, flags [none], proto: TCP (6), length: 40) 70.243.226.250.1703 > 123.23.23.23.25000: R, cksum 0xacb6 (correct), 4070626809:4070626809(0) win 64172 - no error message is printed by nf_ct_tcp, no 'table is full' error. My idea is following. - This TCP reset is not initial packet of TCP connection. If it is initial packet, no address in ICMP packet should be mangled. Jordan, if you see /proc/net/netfilter/nf_conntrack, you will find the entry matched the TCP packet. - TCP packet was marked as error packet. Because '--state ESTABLISHED' didn't match the packet. No conntrack entry wasn't assigned to the packet. Usually, error log by nf_conntrack_tcp should be generated in such case, but no message is generated in some cases. I don't know why this TCP reset was handled as error. - Then ICMP error generated at this router was not assigned to any conntrack entry. - nf_conntarck_icmp.c assigns the ICMP error to the conntrack which matches the TCP reset. But IP_CT_IS_REPLY didn't set to *ctinfo. This is bug. h = nf_conntrack_find_get(&innertuple, NULL); if (!h) { /* Locally generated ICMPs will match inverted if they haven't been SNAT'ed yet */ /* FIXME: NAT code has to handle half-done double NAT --RR */ if (hooknum == NF_IP_LOCAL_OUT) h = nf_conntrack_find_get(&origtuple, NULL); if (!h) { DEBUGP("icmp_error_message: no match\n"); return -NF_ACCEPT; } /* Reverse direction from that found */ if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) *ctinfo += IP_CT_IS_REPLY; } else { if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) *ctinfo += IP_CT_IS_REPLY; - As a result, nf_nat_packet mistook the address in ICMP packet which should be mangled.
>From e36c67a5f57a0bd45f6666627ad3d60d42ee4497 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai <yasuyuki.kozakai@xxxxxxxxxxxxx> Date: Sat, 7 Jul 2007 20:29:39 +0900 Subject: [PATCH 1/1] [NETFILTER]: nf_conntrack: Fixes direction of locally generated ICMP error The conntrack assigned to locally generated ICMP error is usually the one assigned to the original packet which has caused the error. But if the original packet is handled as invalid by nf_conntrack, no conntrack is assigned to the original packet. Then nf_ct_attach() cannot assign any conntrack to the ICMP error packet. In that case nf_conntrack_icmp tries to assign appropriate conntrack to it. But the current code mistakes the direction of the packet. As a result, NAT code mistakes the address in the packet to mangle. Spotted by Jordan Russell. Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@xxxxxxxxxxxxx> --- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index f4fc657..5973b58 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -201,7 +201,7 @@ icmp_error_message(struct sk_buff *skb, } /* Reverse direction from that found */ - if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) + if (NF_CT_DIRECTION(h) != IP_CT_DIR_REPLY) *ctinfo += IP_CT_IS_REPLY; } else { if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) -- 1.5.2.2