Turns out that it was indeed the TTL that was causing the issue! Here's an FAQ-style answer, hopefully more broadly useful for other people.
Why does my connection only work via direct cable, but not via a router? Is my router not working properly?
If your situation is like mine, the router was (and is) working just fine. The issue is that my ISP just implemented TTL throttling.
What is TTL throttling?
TTL throttling consists in setting the TTL (time-to-live) of IP packets to 1, in order to prevent the use of routers: all packets from the WAN (Internet) are dropped before reaching the PC (because their TTL becomes 0).
How can I detect TTL throttling?
When connected using direct cable (which should work normally), try pinging any server, preferably by IP to avoid DNS issues. Google's public DNS server is easy to remember, so I often do:
ping 8.8.8.8
The result will contain a field ttl
(or TTL
on Windows):
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=1 time=12.3 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=1 time=3.52 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=1 time=21.1 ms
In this example, the TTL is exactly 1. The chances of this happening in practice, without TTL throttling, are nearly zero. ttl=1
is the indicator that your TTL is being throttled.
How to circumvent TTL throttling?
You need to configure your router so that it will modify the TTL of the incoming packets, increasing it to a higher value (say, 64) so that packets will not be dropped before arriving at the devices connected to your router.
Unfortunately, specific details will depend on each router/firmware. I had DD-WRT installed in my router, so I used iptables
rules to configure it.
After various attempts, I ended up succeeding in defining a rule that worked for me, but every firmware version may be different! You may have to try several combinations before finding one that works.
General tips about configuring DD-WRT iptables to cancel TTL throttling
- If you can, use the SSH command line to connect to the router. It's faster and it gives you feedback about incorrect commands;
- You probably will have to understand the iptables syntax in order to fix the command so that it'll work for you;
- I still don't understand it enough, and I was tired of trying, so I just stuck with the first one that worked, although it most probably is not the best one.
Here are the commands that I added to my DD-WRT startup script:
iptables -v -t mangle -A OUTPUT -j TTL --ttl-set 60
iptables -v -t mangle -A PREROUTING -j TTL --ttl-set 63
They are almost surely wrong at some level, but the important parts are:
- always use
-v
to obtain verbose output; incorrect commmands will be indicated;
- avoid using
-n
(for numerical, i.e. IP output); despite being mentioned in DD-WRT's Iptables page, this option does not seem to exist in my DD-WRT version, resulting in a silent error. I only noticed it by echoing $?
after the command, which resulted in 255 instead of 0. Removing this option allowed me to see the error messages;
- for quick testing without a working Internet connection on the PC, you can let a
ping
command running on the PC on a console, while you try the iptables
commands on another console. By default, my router was replying with ttl=64
, but when I got a rule that worked, I could instantly see ping returning with the new value (hence why I did not use 64 in my example) when using the OUTPUT
chain (otherwise, it is not necessary for the actual Internet connection);
- some people mention chain
PREROUTING
, others mention INPUT
. I'm not sure of the difference, but the PREROUTING
seems to have worked better for me.
Unfortunately, this is still not ideal: every hour or so, my connection seems to get reset, so I have to manually update the iptables rule.
Note: I barely know anything about iptables
, so any suggestions for better rules are welcome (I will test and update them accordingly).
Windows/Mac Internet sharing
If you are using a Windows/Mac computer as router (e.g. using your PC/laptop to share your Internet connection with other devices), software such as Connectify (since its version 7.1, according to their website) also enables bypassing TTL throttling.
Connectify calls this setting avoid Hotel/NAT restrictions. It is active by default, which would explain why there are not so many people complaining about TTL throttling on the Internet: Windows users end up mostly using Connectify, without asking why it works. This would however explain why Windows' standard Internet connection sharing might not work out of the box.
And on a final note...
Should I feel bad about avoiding TTL throttling?
Probably not, especially if your ISP, like mine, (1) already does bandwidth throttling, (2) introduces TTL throttling without ever announcing it, and (3) is clearly only interested in cheating its users, instead of improving the service. Removing a standard feature artificially and by "cheating" (faking TTL is cheating), only to charge twice as much to put it back, is a very scummy move.
NAT/QoS
tab only lists port forwarding settings. After installing DD-WRT, I don't think I've ever had to change the default settings, so I believe there's no NAT configured, or maybe everything is already NATted by my router. If I should activate NAT, should I choose One-to-one or One-to-many?