Re: [RFC] TCPOPTSTRIP target

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Patrick McHardy <kaber@xxxxxxxxx> writes:

> Jan Engelhardt wrote:
>> Since I had nothing better to do, I did a cleanup :)
>
> Great :) My main question is what the use case of this is.

Main intention for writing this module was to strip of TCP Options from
the SYN packets sent by some Hosts - for example Hosts that are
announcing that they can do window scaling, but in fact some broken
implementation/routers inbetween are preventing this. Simply stripping
of these Option allows communicating with such device, without the need
to disable window scaling kernel-wide.

The first version was only stripping the Windows scaling option, but it
may be useful for other cases - so i decided to make the stripped option
configurable.

>
>> @@ -0,0 +1,155 @@
>> +/*
>> + * A module for stripping a specific TCP option from TCP packets.
>> + *
>> + * Copyright (C) 2007 Sven Schnelle <svens@xxxxxxxxxxxx>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/skbuff.h>
>> +#include <linux/ip.h>
>> +#include <linux/ipv6.h>
>> +#include <linux/tcp.h>
>> +#include <net/ipv6.h>
>> +#include <net/tcp.h>
>> +#include <linux/netfilter/x_tables.h>
>> +#include <linux/netfilter/xt_tcpudp.h>
>
> tcpudp.h? Shouldn't be needed.
>
>> +#include <linux/netfilter/xt_TCPOPTSTRIP.h>
>> +
>> +static void fast_csum(__sum16 *csum, const u_int8_t *optr,
>> +                      const u_int8_t *nptr, const int offset)
>> +{
>> +	u_int8_t s[4];
>> +
>> +	if (offset & 1) {
>> +		s[0] = s[2] = 0;
>> +		s[1] = ~*optr;
>> +		s[3] = *nptr;
>> +	} else {
>> +		s[1] = s[3] = 0;
>> +		s[0] = ~*optr;
>> +		s[2] = *nptr;
>> +	}
>> +
>> +	*csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
>> +}
>
>
> Please use the generic checksumming helpers.

something like this?:

+       if (opt[i] == tinfo->tcpoption) {
+           for(j = 0; j < optl; j++) {
+                   o = opt[i+j];
+                   n = TCPOPT_NOP;
+                   if ((i + j) % 2 == 0) {
+                       o <<= 8;
+                       n <<= 8;
+                   }
+                   nf_proto_csum_replace2(&tcph->check, *pskb,
+                                          htons(o), htons(n), 0);
+           }
+           memset(opt+i, TCPOPT_NOP, optl);
+        }

As i'm currently travelling, i can't test the code above - will do the
end of next week, and resubmit.

>> +
>> +static unsigned int
>> +tcpoptstrip_mangle_packet(struct sk_buff **pskb,
>> +                          const struct xt_tcpoptstrip_info *info,
>> +                          unsigned int tcphoff, unsigned int minlen)
>> +{
>> +	const u_int8_t newopt = TCPOPT_NOP;
>> +	unsigned int optl, tcplen, i, j;
>> +	struct tcphdr *tcph;
>> +	u_int8_t *opt;
>> +
>> +	if (!skb_make_writable(pskb, (*pskb)->len))
>> +		return NF_DROP;
>> +
>> +	tcplen = (*pskb)->len - tcphoff;
>> +	tcph   = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
>> +
>> +	if (tcplen != 4 * tcph->doff)
>> +		return NF_DROP;
>
>
> Seems to be copied from TCPMSS - but I don't see why you shouldn't allow
> stripping options from packets with data.

Indeed, i've used xt_TCPMSS.c as some kind of template. Could be removed
of course.

>> +
>> +	opt = (u_int8_t *)tcph;
>> +
>> +	for (i = sizeof(struct tcphdr); i < 4 * tcph->doff; i += optl) {
>> +		optl = optlen(opt, i);
>> +
>> +		if (optl + i > tcph->doff*4)
>> +			break;
>> +
>> +		if (opt[i] == info->tcpoption) {
>> +			for (j = 0; j < optl; j++)
>> +				fast_csum(&tcph->check, opt + i + j,
>> +				          &newopt, i + j);
>> +			if (optl & 1)
>> +				fast_csum(&tcph->check, &newopt,
>> +				          &newopt, i + j);
>> +			memset(opt+i, newopt, optl);
>
>
> For TCPOPTSTRIP I would expect either real stripping or replacement
> by TCPOPT_NOP. In which cases does replacement by something else
> make sense?

It does replacement by TCPOPT_NOP - the newopt is a const
TCPOPT_NOP. But i've changed this with the checksum code above.
Of course we can choose another name which describes the task of this
target better - didn't care much about it the name in the first case.

I think replacing the TCP Option by nop is cheaper than moving all
remaining options.
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux