I have a GL.iNet AR-300M running the latest OpenWRT 18.06.2 stable release. I'm using it basically as a USB-ethernet bridge between my USB-tethered Android phone and my primary router (a pfSense box) sitting upstream. In order to minimize unnecessary layers of NAT I've set up a bridge in OpenWRT (br-lan) that consists of one of the ethernet ports (eth0) and the USB tether interface, usb0.
Because my cell carrier imposes tethering restrictions (enforced by checking the outgoing TTL of packets from the phone) I've configured iptables to modify the TTL as follows:
However, this doesn't seem to work. The firewall rule shows up in Status -> Firewall but the packet counters remain at 0, indicating that this mangle rule isn't been applied (confirmed with packet sniffing on the phone).
If I tweak OpenWRT to use a standard routed NAT setup, the mangling works with the following iptables rule:
However, this isn't ideal as this creates three layers of NAT before traffic leaves the phone (pfSense router, OpenWRT router, Android tether).
Anyone have any ideas as to why mangling doesn't seem to work with a bridged interface? I've already checked that the appropriate packages are installed (iptables-mod-physdev, iptables-mod-ipopt).
Well, I'll be darned. I did a reset to stock settings and redid the configuration from scratch. It's working now! Not sure what was going wrong - perhaps the br_netfilter kernel module wasn't loaded.
Yep, that's how I originally added the rule in the first place
I did some more testing. The bridge + physdev method seems to be quite flaky with regard to the USB device being hotplugged. On the other hand, the routed NAT + -o usb0 method is a lot more robust - it just starts working when the USB device is plugged in. I think I'll have to stick with the latter method (and just accept some excessive NATting) for now - this seems like it might be more of a Linux kernel / iptables issue than OpenWRT.
I found this page, which suggests that you can do a script on ifup. The question is, do ifup events fire for individual interfaces that are part of a bridge?
I finally figured it out and now have this setup working reliably in bridge mode. The problem was actually in the sysctl settings for br_netfilter not being applied at startup (see http://ebtables.netfilter.org/documentation/bridge-nf.html). I just needed to put
I also created a simple script /etc/hotplug.d/net/99-usb-mangle-ttl that will automatically apply and remove the iptables rule when usb0 is connected/disconnected from the system:
#!/bin/sh
if [ "$INTERFACE" = "usb0" ]; then
if [ "$ACTION" = "add" ]; then
iptables -t mangle -I FORWARD -m physdev --physdev-is-bridged --physdev-in eth1 --physdev-out usb0 -j TTL --ttl-set 65
elif [ "$ACTION" = "remove" ]; then
iptables -t mangle -D FORWARD -m physdev --physdev-is-bridged --physdev-in eth1 --physdev-out usb0 -j TTL --ttl-set 65
fi
fi
It's not possible to use the higher-level iface hotplug system since it seems ifup/ifdown events are filtered for interfaces that are part of a bridge. In any case, it's probably not necessary to have a script in the first place since you should be able to stick it in the custom firewall rules section in the web GUI, but I think this is a more elegant approach.
Hopefully this saves some headaches for anyone else trying to do a similar setup.