--- Begin Message ---
- To: <submit@bugs.debian.org>
- Subject: ipsec changes ip headers; fails to say about this to conntrack
- From: Aidas Kasparas <kaspar@gmc.lt>
- Date: Wed, 15 Oct 2003 20:29:50 +0300 (EEST)
- Message-id: <Pine.LNX.4.33.0310151900280.27338-200000@enter.lifosa.com>
Package: kernel-source-2.4.22
Version: 3
***SETUP***
where this miscommunication shows weird results:
[BoxA]-----[GwA]======[GwB]-----[BoxB]
Interfaces:
BoxA- eth0 192.168.0.2/24
GwA- eth0 192.168.0.254/24
GwA= eth1 Some public address, say PubA
GwB- eth0 192.168.1.254/24
GwB= eth1 Some public address, say PubB
BoxB- eth0 192.168.1.2/24
Tunnel between GwA and GwB -
192.168.0.0/24 192.168.1.0/24 -P out ipsec esp/tunnel/PubA-PubB/unique
and in other direction vice versa.
iptables @GwA empty +
-t nat -A POSTROUTING -o eth1 -j MASQUERADE
BoxA tries to telnet to BoxB:80. tcpdump @BoxA shows
BoxA.1025 -> BoxB.80 SYN
BoxB.1 -> BoxA.1025 ACK
BoxA.1025 -> BoxB.1 RST
tcpdump @GwB- shows normal answer of BoxB:
BoxB.80 -> BoxA.1025 ACK
ping between BoxA and BoxB is working fine.
If iptables rule with MASQUERADE is removed or rule like
POSTROUTING -o eth1 -p esp -j ACCEPT
is inserted before MASQ rule - communications between BoxA and BoxB
returns to normal.
Changing MASQUERADE to DNAT makes no difference.
OK. I agree, initialial configuration of iptables could be better. But I'm
ready to bet money, that I'm not the last one who will make configuration
like this. And I'm ready to bet big money that at least some of those who
will configure like I did, will have no idea what is causing that port-1
maddness and where to start trying to fix it [for me it took 5 days].
It is clear, that ipsec and masquerading do not play well together. I
failed to trace exact place in code which is responsible for storing 1
into source port's position. But I found that ipsec code changes packets
(and headers of them) in place and do not follow Rusty's
instructions
(http://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-6.html)
that such modules should release skb->nfct when they
encapsulate/decapsulate packets.
I tried to add missing code for first of Rusty's requirement. Not sure
that code added at right/best place. But at least kernel with these
additions works on my test box. And port-1 madness is gone on that box no
matter how I play with MASQUERADE rules.
Code is added only to IPv4 part. Can try to add to ipv6 part also, given
my modifications to ipv4 part are ok.
Second of Rusty's requirements - encapsulated packets should go through
LOCAL_OUT hook. I did not managed to come up with code which does this.
I also checked kernel v2.6 code. Other tunnel drivers (ip_gre.c ipip.c)
still contain code for skb->nfct release and ipsec drivers do not.
Therefore I think it is very likely that 2.6 kernel version suffers from
this problem also.
--- net/ipv4/xfrm4_input.c.R 2003-10-15 11:50:06.000000000 +0300
+++ net/ipv4/xfrm4_input.c 2003-10-15 11:53:06.000000000 +0300
@@ -106,8 +106,16 @@
goto drop_put;
} while (!err);
- /* Allocate new secpath or COW existing one. */
+ /* Now, ip header is changed, so let conntrack know about this. */
+#ifdef CONFIG_NETFILTER
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+#endif
+ /* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
struct sec_path *sp;
sp = secpath_dup(skb->sp);
--- net/ipv4/esp4.c.R 2003-08-24 04:33:10.000000000 +0300
+++ net/ipv4/esp4.c 2003-10-15 12:23:48.000000000 +0300
@@ -199,6 +199,16 @@
err = -EHOSTUNREACH;
goto error_nolock;
}
+
+ /* Now, ip headers are changed, so let conntrack know this. */
+#ifdef CONFIG_NETFILTER
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+#endif
+
return NET_XMIT_BYPASS;
error:
--- net/ipv4/ipcomp.c.R 2003-10-15 12:48:44.000000000 +0300
+++ net/ipv4/ipcomp.c 2003-10-15 13:00:52.000000000 +0300
@@ -227,6 +227,14 @@
ip_send_check(iph);
skb->nh.raw = skb->data;
+#ifdef CONFIG_NETFILTER
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+#endif
+
out_ok:
x->curlft.bytes += skb->len;
x->curlft.packets++;
--- net/ipv4/ah4.c.R 2003-10-15 12:47:55.000000000 +0300
+++ net/ipv4/ah4.c 2003-10-15 12:48:32.000000000 +0300
@@ -150,6 +150,15 @@
err = -EHOSTUNREACH;
goto error_nolock;
}
+
+#ifdef CONFIG_NETFILTER
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+#endif
+
return NET_XMIT_BYPASS;
error:
--- End Message ---