All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] NAT for unreplied connections
@ 2002-06-04  8:43 Philip Craig
  2002-06-04 13:01 ` Henrik Nordstrom
  0 siblings, 1 reply; 4+ messages in thread
From: Philip Craig @ 2002-06-04  8:43 UTC (permalink / raw)
  To: netfilter-devel

Hi,

The nat table is only used for the first packet in each
connection.  This poses a problem if the events such as the
following occur:

1. TCP SYN packet sent, but no reply received.

2. iptables rules change or routing table changes such that
the TCP SYN packet should be NATed differently.

3. TCP SYN packet resent, but is NATed using the conntrack
created by the initial conntrack, and so it never reaches its
destination, or the reply is never received.

Currently, the only solution for this is to create a new
connection, often requiring the application to be killed and
restarted.  This can happen for UDP connections and pings
too.

I searched in the list archives and found one other person
has noticed this problem too, but there were no replies:

http://lists.samba.org/pipermail/netfilter-devel/2002-January/003166.html

I've included a patch which changes the IP conntracking such
that the conntrack is recreated if a packet is sent in the
original direction before any replies are seen.

This solves my current problems, but my testing is fairly
minimal so far.  Can anyone see any problems with this patch,
or have a better solution?

One problem may be that since the new conntrack may not have
the same source port as the original, UDP protocols that
don't require replies immediately after the first packet may
fail.

Regards,
Phil


--- linux-2.4.x/net/ipv4/netfilter/ip_conntrack_core.c	2 Oct 2001 09:36:12 -0000	1.1.1.2
+++ linux-2.4.x/net/ipv4/netfilter/ip_conntrack_core.c	4 Jun 2002 07:52:40 -0000	1.3
@@ -584,6 +584,16 @@

  	/* look for tuple match */
  	h = ip_conntrack_find_get(&tuple, NULL);
+ 
if (h && !(h->ctrack->status & IPS_SEEN_REPLY)
+ 
		&& DIRECTION(h) == IP_CT_DIR_ORIGINAL) {
+ 
	/* No reply yet, so recreate the conntrack in case the
+ 
	   NAT rules have changed. */
+ 
	if (del_timer(&h->ctrack->timeout)) {
+ 
		death_by_timeout((unsigned long)h->ctrack);
+ 
		ip_conntrack_put(h->ctrack);
+ 
		h = NULL;
+ 
	}
+ 
}
  	if (!h) {
  		h = init_conntrack(&tuple, proto, skb);
  		if (!h)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] NAT for unreplied connections
  2002-06-04  8:43 [PATCH] NAT for unreplied connections Philip Craig
@ 2002-06-04 13:01 ` Henrik Nordstrom
  2002-06-05  1:23   ` Philip Craig
  0 siblings, 1 reply; 4+ messages in thread
From: Henrik Nordstrom @ 2002-06-04 13:01 UTC (permalink / raw)
  To: Philip Craig, netfilter-devel

The MASQUERADE target comes to mind here.. it is approaching the same problem 
from a different angle, and in my opinion a better one.. MASQUERADE kills all 
relevant conntrack entries when the interface changes, to deal cleanly with 
the situation of dynamic IP assignment where the IP may change while the 
netfilter kernel is running and actively tracking packets..

The main problem with your approach is retransmitted packets. As you tear down 
the conntrack entry on each retransmission until the connection has been 
reassured, the retransmitted packets may well have a different NAT tuple 
selected than the original one. If then the first packet reaches the origin 
server then you will be in trouble. This may well happen even without any 
rule change in NAT, simply as an effect of traffic pattern or a complex 
ruleset intentionally varying the NAT selection. Not very good. You need to 
have some other criteria to determine when it is safe to forget the NAT 
state.

Regards
Henrik

Philip Craig wrote:
> Hi,
>
> The nat table is only used for the first packet in each
> connection.  This poses a problem if the events such as the
> following occur:
>
> 1. TCP SYN packet sent, but no reply received.
>
> 2. iptables rules change or routing table changes such that
> the TCP SYN packet should be NATed differently.
>
> 3. TCP SYN packet resent, but is NATed using the conntrack
> created by the initial conntrack, and so it never reaches its
> destination, or the reply is never received.
>
> Currently, the only solution for this is to create a new
> connection, often requiring the application to be killed and
> restarted.  This can happen for UDP connections and pings
> too.
>
> I searched in the list archives and found one other person
> has noticed this problem too, but there were no replies:
>
> http://lists.samba.org/pipermail/netfilter-devel/2002-January/003166.html
>
> I've included a patch which changes the IP conntracking such
> that the conntrack is recreated if a packet is sent in the
> original direction before any replies are seen.
>
> This solves my current problems, but my testing is fairly
> minimal so far.  Can anyone see any problems with this patch,
> or have a better solution?
>
> One problem may be that since the new conntrack may not have
> the same source port as the original, UDP protocols that
> don't require replies immediately after the first packet may
> fail.
>
> Regards,
> Phil
>
>
> --- linux-2.4.x/net/ipv4/netfilter/ip_conntrack_core.c	2 Oct 2001 09:36:12
> -0000	1.1.1.2 +++ linux-2.4.x/net/ipv4/netfilter/ip_conntrack_core.c	4 Jun
> 2002 07:52:40 -0000	1.3 @@ -584,6 +584,16 @@
>
>   	/* look for tuple match */
>   	h = ip_conntrack_find_get(&tuple, NULL);
> +
> if (h && !(h->ctrack->status & IPS_SEEN_REPLY)
> +
> 		&& DIRECTION(h) == IP_CT_DIR_ORIGINAL) {
> +
> 	/* No reply yet, so recreate the conntrack in case the
> +
> 	   NAT rules have changed. */
> +
> 	if (del_timer(&h->ctrack->timeout)) {
> +
> 		death_by_timeout((unsigned long)h->ctrack);
> +
> 		ip_conntrack_put(h->ctrack);
> +
> 		h = NULL;
> +
> 	}
> +
> }
>   	if (!h) {
>   		h = init_conntrack(&tuple, proto, skb);
>   		if (!h)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] NAT for unreplied connections
  2002-06-04 13:01 ` Henrik Nordstrom
@ 2002-06-05  1:23   ` Philip Craig
  2002-06-05  6:26     ` Henrik Nordstrom
  0 siblings, 1 reply; 4+ messages in thread
From: Philip Craig @ 2002-06-05  1:23 UTC (permalink / raw)
  To: Henrik Nordstrom, netfilter-devel

Henrik Nordstrom wrote:
> The MASQUERADE target comes to mind here.. it is approaching the same problem 
> from a different angle, and in my opinion a better one.. MASQUERADE kills all 
> relevant conntrack entries when the interface changes, to deal cleanly with 
> the situation of dynamic IP assignment where the IP may change while the 
> netfilter kernel is running and actively tracking packets..

Yes, the MASQUERADE target helps a lot, but it doesn't quite do everything
I need.  One of the places the problem is occuring is for dial on demand PPP.
This uses a slip interface to trigger the dial.  When the ppp interface comes
up, any packets for connections that initially went through the slip interface
will be transmitted unNATed (including the packets from the slip interface
that diald buffered).

A solution might be to add a MASQUERADE rule for the slip interface, and bring
the slip down once I know the ppp is up.  So in general I need to ensure that
there is always MASQUERADE rule for the current route that an outgoing packet
will take, and to bring the old interface down if there is a route change.
This is still kind of a workaround for the problem, but if it works then I
think that's good enough.


> The main problem with your approach is retransmitted packets. As you tear down 
> the conntrack entry on each retransmission until the connection has been 
> reassured, the retransmitted packets may well have a different NAT tuple 
> selected than the original one. If then the first packet reaches the origin 
> server then you will be in trouble. This may well happen even without any 
> rule change in NAT, simply as an effect of traffic pattern or a complex 
> ruleset intentionally varying the NAT selection. Not very good. You need to 
> have some other criteria to determine when it is safe to forget the NAT 
> state.

I'd thought at first that this wouldn't be too much of a problem for
TCP... it would just look to the server like two separate connections were
being initiated, and the first one would never be established.  I agree
that it's not very good behaviour though.

Regards,
Phil

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] NAT for unreplied connections
  2002-06-05  1:23   ` Philip Craig
@ 2002-06-05  6:26     ` Henrik Nordstrom
  0 siblings, 0 replies; 4+ messages in thread
From: Henrik Nordstrom @ 2002-06-05  6:26 UTC (permalink / raw)
  To: Philip Craig, netfilter-devel

On Wednesday 05 June 2002 03:23, Philip Craig wrote:

> A solution might be to add a MASQUERADE rule for the slip
> interface, and bring the slip down once I know the ppp is up.  So
> in general I need to ensure that there is always MASQUERADE rule
> for the current route that an outgoing packet will take, and to
> bring the old interface down if there is a route change. This is
> still kind of a workaround for the problem, but if it works then I
> think that's good enough.

It should be sufficient to just have some MASQUERADE rule anywhere I 
think. MASQUERADE does not seem to care what rules you have installed 
when reacting on interface changes.. It will simply react on any 
interface being brought down or ip address deleteions.

What you need to make sure to make it work is that the SLIP interface 
is brought down or at least that there is an ip address deleted from 
the interface SLIP interface... i.e. the following should do in the 
ppp-up script even if you like to keep the slip interface around:

  ip addr add 1.1.1.1/32 dev slip0
  ip addr del 1.1.1.1/32 dev slip0

> I'd thought at first that this wouldn't be too much of a problem
> for TCP... it would just look to the server like two separate
> connections were being initiated, and the first one would never be
> established.  I agree that it's not very good behavior though.

The problem is that your approach may cause this kind of problem at 
any time if there is more than one computer involved (including the 
NAT gateway itself), not only when there is interface changes.

  Computer A is in contact server X on port 80, using port 1234 as 
source port.
  Computer B tries to contact server X on port 80, also using port 
1234 as source port.
  Server X is slow in responding, causing retransmissions

  B sends SYN, NAT assigns it port 5678 as 1234 is occupied.
  B retransmits, NAT reassigns B to port 4325 as 1234 is still 
occupied and there has been other changes in current port usage 
between the two SYN packets from B..

And this is only one case. There is more.

Regards
Henrik

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-06-05  6:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-06-04  8:43 [PATCH] NAT for unreplied connections Philip Craig
2002-06-04 13:01 ` Henrik Nordstrom
2002-06-05  1:23   ` Philip Craig
2002-06-05  6:26     ` Henrik Nordstrom

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.