Transparent access to .onion websites

This is a very basic setup but I’m sharing mine in hopes of saving someone a bunch of googling.

<insert the usual drill about TOR and anonymity and why it’s important>

So my goal was not to anonymize my every move, but rather to be able to key in an *.onion website into the URL bar of any device on the local network and have that delivered transparently. I happen to own a fancy Asus router with AsusWRT-Merlin on board, but the approach should work on pretty much any Linux box that can route traffic.

Step 1: Get TOR installed. Use the package manager available for your router/Linux box. Here’s my config from the router:

SocksPort 9050
Log notice file /tmp/torlog
VirtualAddrNetwork 10.192.0.0/10
AutomapHostsOnResolve 1
TransPort 9040
TransListenAddress 192.168.1.1
DNSPort 9053
DNSListenAddress 192.168.1.1
RunAsDaemon 1
DataDirectory /tmp/.tordb
AvoidDiskWrites 1

A client must first request the domain to be resolved through TOR’s DNS (which in our case will be available at 192.168.1.1:9053). TOR will respond with an address from the 10.192.0.0/10 subnet. The browser will then attempt to connect to said IP address, which our router should intercept and redirect to 192.168.1.1:9040.

Step 2: Figure out DNS resolution. We want to resolve *.onion domains through TOR and resolve everything else through our regular DNS server. My router uses dnsmasq, so adding this line to the config file should do the trick:

server=/.onion/192.168.1.1#9053

Kill and restart dnsmasq for this to take effect.

Step 3: Intercept and redirect. Easy:

iptables -t nat -A PREROUTING -d 10.192.0.0/10 -i br0 -p tcp -m tcp -j REDIRECT --to-ports 9040

At this point you should be able to open an *.onion website in your browser and see it just work!

Step 4: Making the changes persistent. This one will depend on how your router firmware handles that. For mine, I created two new files in the persistent partition (a.k.a. JFFS).
/jffs/configs/dnsmasq.conf.add:

server=/.onion/192.168.11.1#9053

/jffs/scripts/nat-start:

#!/bin/sh
iptables -t nat -A PREROUTING -d 10.192.0.0/10 -i br0 -p tcp -m tcp -j REDIRECT --to-ports 9040

And finally:

chmod a+rx /jffs/scripts/*

That’s it. Read more on user scripts in AsusWRT-Merlin here if you feel like it.