3 min read

TTL modification for outgoing traffic with OpenWRT

For OpenWRT 22.03 and above using firewall4, please refer to the following updated article.

TTL modification for outgoing traffic with OpenWRT 22.03 and firewall4
This is an admittedly belated post given the fact that the first stable build of OpenWRT 22.03 was released in September 2022, but I’m sure it will come in handy for users who primarily use OpenWRT to facilitate 4G/LTE/5G mobile tethering using their smartphone. As users of

Introduction

Do you often find yourself in the position of having to access the internet by tethering your 4G/LTE smartphone? I sure do, because my local cable ISP sucks ass. Unfortunately, however, cellular carriers have a number of tricks up their sleeve to detect (and potentially block you from) tethering. While more advanced techniques such as user agent sniffing and OS TCP/IP stack fingerprinting are harder to circumvent, TTL detection seems to be in much wider use and is also much easier to work around. In this article, we'll go over how to set up TTL modification on an OpenWRT-powered router.

Basic Theory

All IP packets contain an initial time-to-live (TTL) value that is decremented by one for every hop, or router it travels through, until it reaches the destination. By definition, packets are dropped when their TTL reaches zero in order to prevent infinite routing loops. When tethering is enabled on an Android or Apple smartphone, the additional layer of NAT, and therefore routing, decrements the TTL of outgoing packets through the tether interface by 1. Since the default TTL on Android and iOS is 64, it is trivial for phone carriers to distinguish between true on-phone traffic and tethered traffic by checking the value of the TTL and whether or not it equals 64. On Windows, for example, the default TTL is 128 (and therefore 127 after being routed through the tether NAT) - a far cry from 64 and a dead giveaway that tethering is occurring. Therefore, in order to mask tethered traffic, we need to set the TTL of all outgoing tethered packets to a uniform value. Taking into account the extra hop added by the tether interface and the default TTL 64 of most phones, this value is 64 + 1 = 65.

Prerequisites

The instructions below are developed and tested on a GL.iNet AR-300M16 running OpenWRT 18.06.2.

Case 1: Standard routed setup

Scenario: Standard routed setup with separate LAN and WAN (tether) interfaces

  1. Using the OpenWRT package manager via LuCI or opkg CLI, install the iptables-mod-ipopt package.
  2. Navigate to Network → Firewall → Custom Rules.
  3. Add the following line: iptables -t mangle -I POSTROUTING -o usb0 -j TTL --ttl-set 65
  4. Click Restart Firewall to save

If necessary, change usb0 to wlan0 (or whichever interface name corresponds to your tether interface.)

Case 2: Bridged setup

Scenario: Tether WAN interface is bridged to LAN interface, i.e. OpenWRT acting as a transparent USB-to-ethernet bridge for a pre-existing router and network

  1. Using the OpenWRT package manager via LuCI or opkg CLI, install the iptables-mod-ipopt and iptables-mod-physdev packages.
  2. Navigate to Network → Firewall → Custom Rules.
  3. Add the following line: iptables -t mangle -I POSTROUTING -m physdev --physdev-out usb0 -j TTL --ttl-set 65
  4. SSH into the OpenWRT device
  5. In /etc/sysctl.conf, add the following lines:
net.bridge.bridge-nf-call-arptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
  1. Click Restart Firewall to save

If necessary, change usb0 to wlan0 (or whichever interface name corresponds to your tether interface.)

If everything was configured properly, you should be able to see the traffic counters slowly incrementing for your new iptables rule in Status → Firewall.