Skip to contentSkip to conversation

new 'tcpack' match

PATCH In review Jonas Berlin 5 participants 17 messages Mar 27, 2005 – Apr 19, 2005 netfilter

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 new 'tcpack' match

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Matches TCP packets that has no payload, i.e. contains only ACKs.

~ iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10

Or match non-ack packets:

~ iptables -A INPUT -p tcp -m tcpack ! --tcpack -j CLASSIFY 1:12

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCRkWWxyF48ZTvn+4RAoPhAJwLrvINY2VnZ5yqwvovQ8Ao1hv+7wCgzBLG s8lz2LADN8KTr+r38X/oL4s=
=Y+Gd
-----END PGP SIGNATURE-----

tcpack/linux-2.6/include/linux/netfilter_ipv6/ip6t_tcpack.h +8 -0
Index: pom-all/tcpack/linux-2.6/include/linux/netfilter_ipv6/ip6t_tcpack.h
===================================================================
@@ -0,0 +1,8 @@
+#ifndef _IP6T_TCPACK_H
+#define _IP6T_TCPACK_H
+
+struct ip6t_tcpack_info {
+      u_int8_t invert;
+};
+
+#endif /*_IP6T_TCPACK_H*/
tcpack/linux-2.6/include/linux/netfilter_ipv4/ipt_tcpack.h +8 -0
Index: pom-all/tcpack/linux-2.6/include/linux/netfilter_ipv4/ipt_tcpack.h
===================================================================
@@ -0,0 +1,8 @@
+#ifndef _IPT_TCPACK_H
+#define _IPT_TCPACK_H
+
+struct ipt_tcpack_info {
+      u_int8_t invert;
+};
+
+#endif /*_IPT_TCPACK_H*/
tcpack/linux-2.6/net/ipv4/netfilter/Makefile.ladd +2 -0
Index: pom-all/tcpack/linux-2.6/net/ipv4/netfilter/Makefile.ladd
===================================================================
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
+obj-$(CONFIG_IP_NF_MATCH_TCPACK) += ipt_tcpack.o
tcpack/linux-2.6/net/ipv4/netfilter/ipt_tcpack.c +72 -0

72 lines not on this page · raw message

tcpack/linux-2.6/net/ipv4/netfilter/Kconfig.ladd +9 -0
Index: pom-all/tcpack/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
===================================================================
@@ -0,0 +1,9 @@
+config IP_NF_MATCH_TCPACK
+	tristate  'TCP ACK match support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a `tcpack' match, which allow you to match
+	  TCP packets containg no actual data, just ACKs.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
tcpack/linux-2.6/net/ipv6/netfilter/Makefile.ladd +2 -0
Index: pom-all/tcpack/linux-2.6/net/ipv6/netfilter/Makefile.ladd
===================================================================
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
+obj-$(CONFIG_IP6_NF_MATCH_TCPACK) += ip6t_tcpack.o
tcpack/linux-2.6/net/ipv6/netfilter/Kconfig.ladd +9 -0
Index: pom-all/tcpack/linux-2.6/net/ipv6/netfilter/Kconfig.ladd
===================================================================
@@ -0,0 +1,9 @@
+config IP6_NF_MATCH_TCPACK
+	tristate  'TCP ACK match support'
+	depends on IP6_NF_IPTABLES
+	help
+	  This option adds a `tcpack' match, which allow you to match
+	  TCP packets containg no actual data, just ACKs.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
tcpack/linux-2.6/net/ipv6/netfilter/ip6t_tcpack.c +70 -0

70 lines not on this page · raw message

tcpack/iptables/extensions/libip6t_tcpack.c +88 -0

88 lines not on this page · raw message

tcpack/iptables/extensions/.tcpack-test +2 -0
Index: pom-all/tcpack/iptables/extensions/.tcpack-test
===================================================================
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_tcpack.h ] && echo tcpack

Property changes on: pom-all/tcpack/iptables/extensions/.tcpack-test
___________________________________________________________________
Name: svn:executable
+ *

tcpack/iptables/extensions/libipt_tcpack.man +7 -0
Index: pom-all/tcpack/iptables/extensions/libipt_tcpack.man
===================================================================
@@ -0,0 +1,7 @@
+Matches TCP packets that has no payload, i.e. contains only ACKs.
+.IP
+iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10
+.P
+Or match non-ack packets:
+.IP
+iptables -A INPUT -p tcp -m tcpack ! --tcpack -j CLASSIFY 1:12
tcpack/iptables/extensions/.tcpack-test6 +2 -0
Index: pom-all/tcpack/iptables/extensions/.tcpack-test6
===================================================================
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_tcpack.h ] && echo tcpack

Property changes on: pom-all/tcpack/iptables/extensions/.tcpack-test6
___________________________________________________________________
Name: svn:executable
+ *

tcpack/iptables/extensions/libip6t_tcpack.man +10 -0
Index: pom-all/tcpack/iptables/extensions/libip6t_tcpack.man
===================================================================
@@ -0,0 +1,10 @@
+Matches TCP packets that has no payload, i.e. contains only ACKs.
+.IP
+ip6tables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10
+.P
+Or match non-ack packets:
+.IP
+ip6tables -A INPUT -p tcp -m tcpack ! --tcpack -j CLASSIFY 1:12
+
+
+
tcpack/iptables/extensions/libipt_tcpack.c +88 -0

88 lines not on this page · raw message

tcpack/help +7 -0
Index: pom-all/tcpack/help
===================================================================
@@ -0,0 +1,7 @@
+Matches TCP packets that has no payload, i.e. contains only ACKs.
+
+  iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10
+
+Or match non-ack packets:
+
+  iptables -A INPUT -p tcp -m tcpack ! --tcpack -j CLASSIFY 1:12
tcpack/info +4 -0
Index: pom-all/tcpack/info
===================================================================
@@ -0,0 +1,4 @@
+Title: Add support for matching TCP packets with only ACKs (no payload)
+Author: Jonas Berlin <[email protected]>
+Status: testing
+Repository: extra
#1 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jonas Berlin wrote:

| Matches TCP packets that has no payload, i.e. contains only ACKs.
|
|   iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10
|
| Or match non-ack packets:
|
|   iptables -A INPUT -p tcp -m tcpack ! --tcpack -j CLASSIFY 1:12

Actually after thinking about it, the "ack" reference is quite bogus.. it matches packets that simply has no data bytes in them.. regardless of the possible flags SYN ACK FIN RST.

I think I'll rename it and rewrite the documentation a bit so it's clearer and also add some more usage examples and ideas.

So if possible, please hold merging this patch into pom-ng :)

Sorry for my over-enthusiasm, this was my first self-written pom-ng module I publicly announced :)

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCSA92xyF48ZTvn+4RAj45AJ9wjU6CsSq88PB4NxKI54h0fKzIHgCggZ7p I5Uha/RhbnLdYi7Eu2Fk4ZU=
=WwNx
-----END PGP SIGNATURE-----

#2 lore raw
In reply to Jonas Berlin
Quoted 10 lines · Jonas Berlin

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Matches TCP packets that has no payload, i.e. contains only ACKs.

~ iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10

Or match non-ack packets:

~ iptables -A INPUT -p tcp -m tcpack ! --tcpack -j CLASSIFY 1:12

I can see that it would be useful, given all the half-working ACK matching rules for shaping floating around, but we already a tcp match, so it should be done in there, and, if possible, kept a little bit more generic. Perhaps a data-len match option.

Regards
Patrick

#3 lore raw
Quoted 4 lines

I can see that it would be useful, given all the half-working ACK matching rules for shaping floating around, but we already a tcp match, so it should be done in there, and, if possible, kept a little bit more generic. Perhaps a data-len match option.

Hmm. I'm no guru, but isn't it possible to do that using the u32 filter with tc? Which propably is faster than doing it in iptables anyway.

--
Maciej

#4 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Maciej Soltysiak wrote:

|>I can see that it would be useful, given all the half-working ACK
|>matching rules for shaping floating around, but we already a tcp
|>match, so it should be done in there, and, if possible, kept a little
|>bit more generic. Perhaps a data-len match option.
|
| Hmm. I'm no guru, but isn't it possible to do that using the u32 filter
| with tc? Which propably is faster than doing it in iptables anyway.

Yeah it's possible, but no one seems to be doing it right..

What needs to be done is to compare the tcp header length with the total packet length to ensure there are no data bytes. However, tc can only match specific data bytes, and since there are at least 8 different tcp header lengths that can occur during normal traffic in an established connection, it means at least 8 filter rules to match the ack packets..

I've mostly seen solutions where the test is to see if the total length is less than 64 bytes, and if, it means it's a packet that should be prioritized. Unfortunately, since linux likes both the timestamp and the sack options of tcp, the tcp header tends to expand beyond 63 bytes every now and then. When this happens, the packets exceeding 63 bytes will probably go off to another qdisc, which might keep them on a queue for a bit too long, possibly resulting in the data transfer getting stalled temporarily, and possibly unnecessary resends.

I aim to fix this all with one simple netfilter match which can give an answer with simple arithmetics in one go instead of matching against a preconfigured list of possible values one by one.

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCUISKxyF48ZTvn+4RAjSlAKDWorgIpKW8vDf0q+lk2hDsP/uhCwCdGrkl Er4Rr5Hgw68jZEqeqeH2FtY=
=QPJY
-----END PGP SIGNATURE-----

#5 lore raw
Quoted 4 lines

| Hmm. I'm no guru, but isn't it possible to do that using the u32 filter | with tc? Which propably is faster than doing it in iptables anyway.

Yeah it's possible, but no one seems to be doing it right..

Ah, okay, I get it.

Quoted 3 lines

I aim to fix this all with one simple netfilter match which can give an answer with simple arithmetics in one go instead of matching against a preconfigured list of possible values one by one.

Right.

I agree the best way to go would be to extend the tcp match with the proposed semantics:

    --datalen [!] A[,B:C[,D]]

It also might be useful to match the sole header length.
--headerlen [!] A[,B:C[,D]]

And the lenght of tcp+data

--len

Possibly the similar for udp:
--datalen, --headerlen, --len

And ICMP:
--datalen, --len (icmp headers have fixed size)

Signature · 2 lines
Regards,
Maciej Soltysiak
#6 lore raw
Quoted 16 lines · Maciej Soltysiak
Quoted 3 lines

I aim to fix this all with one simple netfilter match which can give an answer with simple arithmetics in one go instead of matching against a preconfigured list of possible values one by one.

Right.

I agree the best way to go would be to extend the tcp match with the proposed semantics:

    --datalen [!] A[,B:C[,D]]

It also might be useful to match the sole header length.
--headerlen [!] A[,B:C[,D]]

And the lenght of tcp+data

Quoted 7 lines
   --len

Possibly the similar for udp:

   --datalen, --headerlen, --len

And ICMP:
--datalen, --len (icmp headers have fixed size)

Could we do this in a generic way? I'm currently rewriting the iptables ACCOUNT target and it could benefit from that as well.

I'd need:
- length of whole IP packet
- length of layer 2 frame

Perhaps a generic prefix for all "length" options is appropriate?

--len-header-ip
--len-data-ip
--len-full-ip
--len-header-tcp
--len-data-tcp
--len-full-tcp
--len-header-ether
--len-data-ether
--len-full-ether
etc.

I realize that some of the options above don't make that much sense, but you get the idea.

Regards,
Carl-Daniel

Signature · 1 line
http://www.hailfinger.org/
#7 lore raw
In reply to Maciej Soltysiak

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoting Maciej Soltysiak on 2005-04-04 13:30 UTC:

~ > I agree the best way to go would be to extend the tcp match with | the proposed semantics:
| --datalen [!] A[,B:C[,D]]

I think [!] A[:B] should suffice :)

| It also might be useful to match the sole header length.
| --headerlen [!] A[,B:C[,D]]

Maybe [!] A[:B] here also..

Patric McHardy, what do you think, should I implement --headerlen also?

| And the lenght of tcp+data
| --len

This should be done with the "length" match IMO. -m length
- --layer2-length maybe ? I could implement this too while at it..

| Possibly the similar for udp:
| --datalen, --headerlen, --len

The udp header length is fixed (8 bytes), and thus --headerlen is unneeded and --datalen N[:M] could maybe implemented as -m length
- --layer2-length N+8[:M+8] ? I do agree that it would be a bit unaesthetic :)

| And ICMP:
| --datalen, --len (icmp headers have fixed size)

Same situation as udp, except maybe if the timestamps of the Timestamp message would be considered a part of the header, in which case the header size would no longer be fixed.. Anyway I guess --layer2-length should suffice for icmp..

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCWl7dxyF48ZTvn+4RAiKlAJ9ngZw5WUOvn14AFl5sthU6tUHWHQCfUR/z yxHXlrMHAI+eHryfG1RSuT4=
=nJX2
-----END PGP SIGNATURE-----

#8 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoting Jonas Berlin on 2005-04-11 11:26 UTC:

Quoted 2 lines

This should be done with the "length" match IMO. -m length --layer2-length maybe ? I could implement this too while at it..

Actually, that should probably have been layer 3 instead of 2..

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCWnbzxyF48ZTvn+4RAkS6AJ9QsGbuvsd0r4NS47tldVZIQtkTDwCgkEmu b4+EZEqkUI4DlUwGIHviaWs=
=kotj
-----END PGP SIGNATURE-----

#9 lore raw
In reply to Jonas Berlin
Quoted 29 lines · Jonas Berlin

Quoting Maciej Soltysiak on 2005-04-04 13:30 UTC:

~ > I agree the best way to go would be to extend the tcp match with | the proposed semantics:
| --datalen [!] A[,B:C[,D]]

I think [!] A[:B] should suffice :)

| It also might be useful to match the sole header length.
| --headerlen [!] A[,B:C[,D]]

Maybe [!] A[:B] here also..

Patric McHardy, what do you think, should I implement --headerlen also?

| And the lenght of tcp+data
| --len

This should be done with the "length" match IMO. -m length --layer2-length maybe ? I could implement this too while at it..

| Possibly the similar for udp:
| --datalen, --headerlen, --len

The udp header length is fixed (8 bytes), and thus --headerlen is unneeded and --datalen N[:M] could maybe implemented as -m length --layer2-length N+8[:M+8] ? I do agree that it would be a bit unaesthetic :)

Quoted 7 lines

| And ICMP:
| --datalen, --len (icmp headers have fixed size)

Same situation as udp, except maybe if the timestamps of the Timestamp message would be considered a part of the header, in which case the header size would no longer be fixed.. Anyway I guess --layer2-length should suffice for icmp..

Perhaps a generic prefix for all "length" options is appropriate?

--len-header-ip
--len-data-ip
--len-full-ip
--len-header-tcp
--len-data-tcp
--len-full-tcp
--len-header-ether
--len-data-ether
--len-full-ether
etc.

Regards,
Carl-Daniel

Signature · 1 line
http://www.hailfinger.org/
#10 lore raw
In reply to Patrick McHardy

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Patrick McHardy wrote:

|> Matches TCP packets that has no payload, i.e. contains only ACKs.
|
| I can see that it would be useful, given all the half-working ACK
| matching rules for shaping floating around, but we already a tcp
| match, so it should be done in there, and, if possible, kept a little

I was thinking of this, but my mind tricked me into believing that it was a too bold thing to do..

Speaking of tcp match.. would you happen to know when the "h" union of sk_buff is instantiated?

~   a) first time someone does -p something
~   b) somewhere before the filter table
~   c) in a seemingly unpredictable fashion
~   d) ?

I kindof recall sometimes using it and oopsing the kernel because it was not yet initialized.. The patch I posted currently starts from nh and calculates the tcp header start itself.. :)

| bit more generic. Perhaps a data-len match option.

I was thinking of this too but couldn't think of much use for more specific length-matching, so I thought I'd save a few cycles.. but ok if you think it's the way to go, I go. :)

Any parameter name suggestions? "[!] --has-payload" ?

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCUH32xyF48ZTvn+4RAk4DAJ9cnX1IXU6Qn0HuWoBoZvZPakpBAACeK/lY PsmEkZ6Bk0G9cpixt0FaJic=
=j2oo
-----END PGP SIGNATURE-----

#11 lore raw
Quoted 7 lines · Jonas Berlin

| bit more generic. Perhaps a data-len match option.

I was thinking of this too but couldn't think of much use for more specific length-matching, so I thought I'd save a few cycles.. but ok if you think it's the way to go, I go. :)

Any parameter name suggestions? "[!] --has-payload" ?

How bout just a '--datalen [!] X', where X can be any number, including 0?

Phil

#12 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Phil Oester wrote:

|>Any parameter name suggestions? "[!] --has-payload" ?
|
| How bout just a '--datalen [!] X', where X can be any number, including 0?

Oops getting sleepy..

Yeah, datalen perhaps.. but should it maybe also match a range instead of just one exact length?

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCUIUkxyF48ZTvn+4RAh72AJoCTo+gkpYRYcwcA4srpkKYTaal5QCfe1S/ /YN5r6+OjwrZDQrSmHOI6gI=
=XW4e
-----END PGP SIGNATURE-----

#13 lore raw
Quoted 2 lines · Jonas Berlin

Yeah, datalen perhaps.. but should it maybe also match a range instead of just one exact length?

Sure, and maybe both ranges and multiple lengths, similar to how revision 1 of the multiport match handles ports. So:

	--datalen [!] A[,B:C[,D]]

Phil

#14 lore raw
In reply to Jonas Berlin
Quoted 6 lines · Jonas Berlin

Speaking of tcp match.. would you happen to know when the "h" union of sk_buff is instantiated?

~   a) first time someone does -p something
~   b) somewhere before the filter table
~   c) in a seemingly unpredictable fashion
~   d) ?

It is used by the upper layer protocols, you can't use it in netfilter because it is unset for forwarded packets.

Quoted 7 lines

| bit more generic. Perhaps a data-len match option.

I was thinking of this too but couldn't think of much use for more specific length-matching, so I thought I'd save a few cycles.. but ok if you think it's the way to go, I go. :)

Any parameter name suggestions? "[!] --has-payload" ?

--datalen?

Regards
Patrick

#15 lore raw
In reply to Patrick McHardy

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoting Patrick McHardy on 2005-04-03 18:15 UTC:

|> ~  iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10
|
| I can see that it would be useful, given all the half-working ACK
| matching rules for shaping floating around, but we already a tcp
| match, so it should be done in there, and, if possible, kept a little
| bit more generic. Perhaps a data-len match option.

Should I make a new revision of the tcp match in order not to break binary compatibility?

- --
- - xkr47
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFCWmmNxyF48ZTvn+4RAps7AKC2Bii7ZaWYecGwYgPQ8xJxmgLWqgCfRucE PajDstxPkhhzN3q17+hXzfA=
=Gsrz
-----END PGP SIGNATURE-----

#16 lore raw
Quoted 12 lines · Jonas Berlin

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoting Patrick McHardy on 2005-04-03 18:15 UTC:

|> ~  iptables -A INPUT -p tcp -m tcpack --tcpack -j CLASSIFY 1:10
|
| I can see that it would be useful, given all the half-working ACK
| matching rules for shaping floating around, but we already a tcp
| match, so it should be done in there, and, if possible, kept a little
| bit more generic. Perhaps a data-len match option.
Quoted 2 lines

Should I make a new revision of the tcp match in order not to break binary compatibility?

Yes.

Regards
Patrick