Hi,
On Fri, 25 Nov 2005, Jozsef Kadlecsik wrote:
> On Thu, 24 Nov 2005, Olaf Kirch wrote:
>
> > On Thu, Nov 24, 2005 at 03:08:27PM +0100, Harald Welte wrote:
> > > Jozsef Kadlecsik doesn't recall those patches/changes (even though he's
> > > our "Mr. TCP state tracking" and is indicated as the author of one of
> > > the two patches.
> > >
> > > I also don't recall having seen any of those patches before. But that
> > > doesn't mean all too much, my brain is like a sieve some times.
> >
> > Those patches came out of a discussion on netfilter-devel. Sorry,
> > I don't know exactly when but looking at our CVS log it was Dec 2004.
>
> Yes, it was about a year ago - finally I could dig out the patches from my
> mail archives. I'll prepare an updated version on the weekend and send it
> out to netfilter-devel for reviewing.
Attached is the updated patch. Unfortunately nfsim currently is broken so
I could not test it against the testsuite, but actually it's identical
with the original, not applied patches. The patch takes care both
ip_conntrack and nf_conntrack.
Best regards,
Jozsef
-
E-mail : [EMAIL PROTECTED], [EMAIL PROTECTED]
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
H-1525 Budapest 114, POB. 49, Hungary
Mounting NFS file systems after a (warm) reboot could take a long time if
firewalling and connection tracking was enabled.
The reason is that the NFS clients tends to use the same ports (800 and
counting down). Now on reboot, the server would still have a TCB for an
existing TCP connection client:800 -> server:2049. The client sends a
SYN from port 800 to server:2049, which elicits an ACK from the server.
The firewall on the client drops the ACK because (from its point of
view) the connection is still in half-open state, and it expects to see
a SYNACK.
The client will eventually time out after several minutes.
The following patch corrects this, by accepting ACKs on half open connections
as well.
Signed-off-by: Jozsef Kadlecsik <[EMAIL PROTECTED]>
diff -urN --exclude-from=/usr/src/diff.exclude
linux-2.6.15-rc2-orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
linux-2.6.15-rc2-tcp-win/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- linux-2.6.15-rc2-orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
2005-11-20 04:25:03.000000000 +0100
+++ linux-2.6.15-rc2-tcp-win/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
2005-11-29 11:01:25.000000000 +0100
@@ -272,9 +272,9 @@
* sCL -> sCL
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
-/*ack*/ { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
/*
- * sSS -> sIV Might be a half-open connection.
+ * sSS -> sIG Might be a half-open connection.
* sSR -> sSR Might answer late resent SYN.
* sES -> sES :-)
* sFW -> sCW Normal close request answered by ACK.
@@ -917,8 +917,12 @@
switch (new_state) {
case TCP_CONNTRACK_IGNORE:
- /* Either SYN in ORIGINAL
- * or SYN/ACK in REPLY. */
+ /* Ignored packets:
+ *
+ * a) SYN in ORIGINAL
+ * b) SYN/ACK in REPLY
+ * c) ACK in reply direction after initial SYN in original.
+ */
if (index == TCP_SYNACK_SET
&& conntrack->proto.tcp.last_index == TCP_SYN_SET
&& conntrack->proto.tcp.last_dir != dir
@@ -985,13 +989,20 @@
}
case TCP_CONNTRACK_CLOSE:
if (index == TCP_RST_SET
- && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
- && conntrack->proto.tcp.last_index == TCP_SYN_SET
+ && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+ && conntrack->proto.tcp.last_index == TCP_SYN_SET)
+ || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
+ && conntrack->proto.tcp.last_index == TCP_ACK_SET))
&& ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
- /* RST sent to invalid SYN we had let trough
- * SYN was in window then, tear down connection.
+ /* RST sent to invalid SYN or ACK we had let trough
+ * at a) and c) above:
+ *
+ * a) SYN was in window then
+ * c) we hold a half-open connection.
+ *
+ * Delete our connection entry.
* We skip window checking, because packet might ACK
- * segments we ignored in the SYN. */
+ * segments we ignored. */
goto in_window;
}
/* Just fall trough */
diff -urN --exclude-from=/usr/src/diff.exclude
linux-2.6.15-rc2-orig/net/netfilter/nf_conntrack_proto_tcp.c
linux-2.6.15-rc2-tcp-win/net/netfilter/nf_conntrack_proto_tcp.c
--- linux-2.6.15-rc2-orig/net/netfilter/nf_conntrack_proto_tcp.c
2005-11-20 04:25:03.000000000 +0100
+++ linux-2.6.15-rc2-tcp-win/net/netfilter/nf_conntrack_proto_tcp.c
2005-11-29 11:19:00.000000000 +0100
@@ -280,9 +280,9 @@
* sCL -> sCL
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
-/*ack*/ { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
/*
- * sSS -> sIV Might be a half-open connection.
+ * sSS -> sIG Might be a half-open connection.
* sSR -> sSR Might answer late resent SYN.
* sES -> sES :-)
* sFW -> sCW Normal close request answered by ACK.
@@ -912,8 +912,12 @@
switch (new_state) {
case TCP_CONNTRACK_IGNORE:
- /* Either SYN in ORIGINAL
- * or SYN/ACK in REPLY. */
+ /* Ignored packets:
+ *
+ * a) SYN in ORIGINAL
+ * b) SYN/ACK in REPLY
+ * c) ACK in reply direction after initial SYN in original.
+ */
if (index == TCP_SYNACK_SET
&& conntrack->proto.tcp.last_index == TCP_SYN_SET
&& conntrack->proto.tcp.last_dir != dir
@@ -979,13 +983,20 @@
}
case TCP_CONNTRACK_CLOSE:
if (index == TCP_RST_SET
- && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
- && conntrack->proto.tcp.last_index == TCP_SYN_SET
+ && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+ && conntrack->proto.tcp.last_index == TCP_SYN_SET)
+ || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
+ && conntrack->proto.tcp.last_index == TCP_ACK_SET))
&& ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
- /* RST sent to invalid SYN we had let trough
- * SYN was in window then, tear down connection.
+ /* RST sent to invalid SYN or ACK we had let trough
+ * at a) and c) above:
+ *
+ * a) SYN was in window then
+ * c) we hold a half-open connection.
+ *
+ * Delete our connection entry.
* We skip window checking, because packet might ACK
- * segments we ignored in the SYN. */
+ * segments we ignored. */
goto in_window;
}
/* Just fall trough */