mmorciegov / android-wifi-tether

Automatically exported from code.google.com/p/android-wifi-tether
7 stars 3 forks source link

Patch: Clamp MSS to fix broken fragmentation #816

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
This patch adds a netfilter rule to allow tethering with ISPs that don't 
support fragmented packets, but do advertise an appropraite path MTU.  It's 
logically equivalent to the clamp_mss patch for wired-tether [1].

From the wired-tether issue page:

"Background: some ISPs don't support IP fragmentation, either because they're 
afraid of IP fragmentation attacks, or their routers are braindead.  Usually 
this isn't an issue for connecting clients because their DHCP responses include 
an interface MTU equal to the path MTU.  In response, the client ensures during 
TCP handshakes that connections use an MSS that results in TCP/IP packets never 
being fragmented.

However, problems occur when the connecting "client" is a NAT router (such as a 
tethering phone).  Often the phone-tethered host interface (e.g., USB RNDIS, 
802.11, etc.) uses a preset MTU (usually 1500) that exceeds the path MTU 
advertised by the ISP.  The host will open TCP connections with too-large of an 
MSS, and inevitably large packets will become fragmented and lost.  The fix is 
to have the router (phone) mangle TCP handshakes to clamp the MSS such that 
generated TCP/IP packets never exceed the path MTU.  This patch implements such 
a fix as described in the iptables(8) man page.

Now, I've not-yet witnessed this problem in practice when tethering--either 
because my ISP does support fragmentation, or because the path MTU (1400 or 
1492) isn't low enough to cause fragmentation in practice.  That said, I have 
encoutered this problem with wired-broadband ISPs.  Since the fix is trivial, 
it's probably a good idea to implement as I'm sure someone, somewhere, gets 
this wrong."

This (wireless-tether) patch basically does the same thing as the wired-tether 
one, it ignores "iptables -t mangle" errors if it returns value 3, making the 
MSS clamp optional.  It will work for phones that have mangle table support, 
and it's ignored on phones that don't.

To implement this, the patch alters the "run_program" edify function to take an 
optional second argument: an "OK status", which along with 0, is considered a 
successful (non-error) result from the invoked program.  All "iptables -t 
mangle" commands are called with "OK status" 3.

Like the wired-tether version, there's two outstanding issues:

The iptables binary needs to be updated to support the "--clamp-mss-to-pmtu" 
option, which it does in the Eclair & Froyo AOSP trees.  I'm guessing it 
doesn't in Donut and earlier.

When I test new builds of wireless-tether, I see that the binaries are not 
automatically updated on a program update (although I keep the same version 
code), and I have to uninstall/reinstall completely to get them to update.  If 
this is the case in update of the official version, then it will error for 
everyone until they do a reinstall/binary update.  So if it doesn't exist, a 
mechanism to update the iptables binary on program update would be needed to 
make this smooth.

Thanks!

[1] http://code.google.com/p/android-wired-tether/issues/detail?id=31

Original issue reported on code.google.com by mkas...@gmail.com on 18 Jan 2011 at 8:48

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by harald....@gmail.com on 19 Jan 2011 at 10:16

GoogleCodeExporter commented 9 years ago
A short update: I'm currently working on version 3 of the app (complete rewrite 
of some main-functions) and I will integrate exactly this as a selectable 
option in settings. Thanks again for the patch!

Original comment by harald....@gmail.com on 25 Jan 2011 at 12:34

GoogleCodeExporter commented 9 years ago
Cool, thanks!

Original comment by mkas...@gmail.com on 26 Jan 2011 at 5:50

GoogleCodeExporter commented 9 years ago
Mmmh ... I've implemented that now ... but I get errors when enabling mss 
clamping.

iptables -t mangle -I FORWARD -s 192.168.2.0/24 -p tcp --tcp-flags SYN,RST SYN 
-j TCPMSS --clamp-mss-to-pmtu]
getsockopt for multiport failed strangely: No such file or directory
getsockopt for multiport failed strangely: No such file or directory
FIX ME! implement getprotobyname() bionic/libc/bionic/stubs.c:378
iptables v1.3.7: Unknown arg `--clamp-mss-to-pmtu'
Try `iptables -h' or 'iptables --help' for more information.

That's on a nexus one running cyanogenmod and I've tried various versions of 
the iptables-binary (from froyo-aosp).

Oh ... wait ... CONFIG_NETFILTER_XT_MATCH_TCPMSS is not enabled in the 
cyanogenmod-kernel.

Original comment by harald....@gmail.com on 10 Feb 2011 at 10:21

GoogleCodeExporter commented 9 years ago
OK, I see what's going on.

The "Unknown arg `--clamp-mss-to-pmtu'" error means that Froyo iptables doesn't 
have TCPMSS support either.  Turns out it does (and probably previous versions 
as well), it's just not compiled by default.

Attached is a patch for external/iptables/Android.mk to enable building of 
TCPMSS support in iptables.  It's against android-2.2.2_r1, but the version 
shouldn't matter.

You can test an iptables binary for support with "strings iptables | grep 
clamp-mss-to-pmtu".  If you see a few strings in the result, the binary should 
be good.

Now, for the command to actually take effect you'll need support for both 
CONFIG_NETFILTER_XT_TARGET_TCPMSS and CONFIG_IP_NF_MANGLE in the kernel.  
They're enabled in stock Samsung kernels, but not HTC, and maybe not 
CyanogenMod either.

CONFIG_NETFILTER_XT_MATCH_TCPMSS is something else entirely and shouldn't be 
necessary.

Original comment by mkas...@gmail.com on 13 Feb 2011 at 4:55

Attachments:

GoogleCodeExporter commented 9 years ago
Ok. Here we go ...
http://android-wifi-tether.googlecode.com/files/wifi_tether_v3_0-pre5.apk

There is now an option in "settings" to enable mss clamping.
(You only see this option if CONFIG_NETFILTER_XT_TARGET_TCPMSS is enabled in 
kernel and /proc/config.gz exists.)

I don't know what device you have (v3 doesn't support the same range of 
different devices like the old 2.0-tree) ... 

Thanks again for the patch and all your help.

Original comment by harald....@gmail.com on 14 Feb 2011 at 9:42

GoogleCodeExporter commented 9 years ago
Cool, it works!  The only caveat is that I had to compile a new kernel since 
the stock Epic (which is the phone I have) Eclair kernel doesn't have IKCONFIG 
(/proc/config.gz) support.

So I checked the stock kernel sources for a number of other Samsung Android 
devices (I9000, Captivate, Vibrant, & Fascinate) since I suspect these are the 
ones that would largely support MSS clamping out-of-the-box.  Like the Epic, 
the Eclair sources have TCPMSS support but not IKCONFIG.  One option would be 
to whitelist these devices, but it's probably not the best idea for the reason 
below.

I also checked out the Froyo kernel sources for the Samsung devices that have 
an official Froyo release (I9000 & Vibrant).  Again, they don't have IKCONFIG 
enabled, but even more strangely is that TCPMSS support is compiled as a 
module.  It's strange since very few in tree drivers are compiled as modules.  
What's worse, is that the module (xt_TCPMSS.ko) is found in neither the 
initramfs nor /system in the stock firmware images.  This appears to be the 
case in the leaked Epic Froyo firmware as well.  Lame.

Since Eclair is going away on Samsung devices, whitelisting probably doesn't 
make sense when TCPMSS doesn't work in Froyo out-of-the-box.  I suppose the 
right thing to do would be to look for "CONFIG_NETFILTER_XT_TARGET_TCPMSS=y" in 
/proc/config.gz as you already do--this covers custom kernels with TCPMSS 
support compiled in--and also to check for "xt_TCPMSS" in /proc/modules, which, 
if it exists, means the kernel has the appropriate module loaded.

I suppose loading the xt_TCPMSS.ko module is best left to the user as there's 
no uniform place where it would exist.

Original comment by mkas...@gmail.com on 17 Feb 2011 at 3:59

GoogleCodeExporter commented 9 years ago
ahm. you have an epic 4g?

Original comment by harald....@gmail.com on 17 Feb 2011 at 5:16

GoogleCodeExporter commented 9 years ago
Yes, Sprint Epic 4G running DI18, latest official (Eclair) release with a few 
kernel patches.

Original comment by mkas...@gmail.com on 17 Feb 2011 at 8:56

GoogleCodeExporter commented 9 years ago
Does it (version 3.0-preX) work in infrastructure/master-mode for you or ad-hoc 
(peer-to-peer)?

Original comment by harald....@gmail.com on 17 Feb 2011 at 10:06

GoogleCodeExporter commented 9 years ago
3.0-pre9 works in ad-hoc mode, but does not work in infrastructure with default 
settings (i.e., encryption off).  Fails on the steps:

Loading WiFi firmware
Configuring softap
Starting softap
Activating WiFi interface

But passes the others.

Is there a way to get verbose output from the "tether" script?

Original comment by mkas...@gmail.com on 18 Feb 2011 at 12:18