Apr 4 2018

Giving every Tor Hidden Service a IPv6 address

Tor has a neat feature called Onion Services (A) that allow you to host and access a TCP port with anonymity, the only thing being required is access to the Tor network.

This is a handy feature for many reasons. It allows people to access facebook (facebookcorewwwi.onion) in countries where it is blocked, it allows people to leak documents to the press in a safer way (nyttips4bmquxfzw.onion)

One of the bigger things to note is that it’s only requirement to both host and access onion services is a connection to the Tor network. This means you can host things behind NAT or other firewalls when you normally could not, making it handy for remote access.

Because this makes Tor a nice NAT/firewall evader it would be nice if a Tor client was not needed to access a onion service. For HTTP/HTTPS services there are already services that do this, tor2web being one of them (amusingly facebook detects this and advices users not to log in via a proxy)

However tor2web has the downside in that it will only work for HTTP/HTTPS, even though onion services can be wrapped with any TCP port service!

To get around this, we can use IPv6 and its very large amount of IP addresses that are standard with a IPv6 deployment.

A Tor onion address is a 8 byte base32 encoded string (80 bits). Conveniently the minimum routable IPv6 block size is a /48 (80 bits of address space) meaning we can have a 1-1 mapping of .onion addresses to IPv6 addresses in a /48!

In this case you can fit it into a IP address that looks like this:

2a07:1500:fed5:2804:40b9:ca13:a24b:5ac8

First we need to write a DNS server that can take these onion addresses and serve back these IPv6 addresses.

I wrote a small DNS server (100 lines) to automatically translate these DNS entries to their IPv6 addresses using the very useful miekg/dns libary

ben@eshwil:~$ dig -p 553 @127.0.0.1 facebookcorewwwi.tor6.flm.me.uk. ; <<>> DiG 9.10.3-P4-Ubuntu <<>> -p 553 @127.0.0.1 facebookcorewwwi.tor6.flm.me.uk. ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10108 ;; flags: qr ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;facebookcorewwwi.tor6.flm.me.uk. IN A ;; ANSWER SECTION: facebookcorewwwi.tor6.flm.me.uk. 2147483646 IN AAAA 2a07:1500:fed5:2804:40b9:ca13:a24b:5ac8 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#553(127.0.0.1) ;; WHEN: Tue Apr 03 09:01:57 EDT 2018 ;; MSG SIZE rcvd: 119

Now we have the address translation in place, we can build the proxy. This is a slightly abnormal task for a proxy, as it has to listen on all ports on 1,208,925,819,614,629,174,706,176 addresses. This means that we are not able to use conventional ways to accept connections.

Using iptables to listen on ports

iptables is commonly thought of as only a firewall. However beyond it’s ability to filter is the ability to setup NAT, run bytecode programs and blink LEDs. In our case, we want to send all TCP traffic from a IP range to a single program.

The REDIRECT target is generally used to catch outbound traffic and put it into a proxy (for example, corporate/educational filtering proxies) however you can also use it in the opposite direction and use it for traffic coming inbound to the system.

In our case we have:

ip6tables -t nat -A PREROUTING -d 2a07:1500:fed5::/48 -i eth0 -p tcp -j REDIRECT --to-ports 1337

This takes matches the any TCP connection coming into 2a07:1500:fed5::/48 (even if we are not binding on it) and it redirects it locally to a program listening on port 1337.

Or, better explained:

However there is a catch, when the connection is redirected, the final destination is lost as it has been changed to be the local application. However there is a syscall you can use to request the original address.

From that point onwards it is a case of reversing the dns encoding of the onion address, then proxying the connection to Tor!

After a bit of fiddling, I had a proof of concept that worked! (minus facebook not being able to handle the Host: header I requested with)

The issue with running this as a service

Tor onion services are great because they are live inside a censorship resilient network, however those exact same protections mean that some very unfavorable content can sometimes live inside tor onion services.

To try and avoid any issues such content may cause, I have decided to not accept connections from any port that a browser can make connections on.

You can still use the following ports:

port original protocol use 1 tcpmux 7 echo 9 discard 11 systat 13 daytime 15 netstat 17 qotd 19 chargen 20 ftp data 21 ftp access 22 ssh 23 telnet 25 smtp 37 time 42 name 43 nicname 53 domain 77 priv-rjs 79 finger 87 ttylink 95 supdup 101 hostriame 102 iso-tsap 103 gppitnp 104 acr-nema 109 pop2 110 pop3 111 sunrpc 113 auth 115 sftp 117 uucp-path 119 nntp 123 NTP 135 loc-srv /epmap 139 netbios 143 imap2 179 BGP 389 ldap 465 smtp+ssl 512 print / exec 513 login 514 shell 515 printer 526 tempo 530 courier 531 chat 532 netnews 540 uucp 556 remotefs 563 nntp+ssl 587 stmp 601 n/a 636 ldap+ssl 993 ldap+ssl 995 pop3+ssl 2049 nfs 3659 apple-sasl 4045 lockd 6000 X11 6665 IRC 6666 IRC 6667 IRC 6668 IRC 6669 IRC

Example usage

Let’s say you wanted to always have access to a raspberry pi, even if you don’t have ports forwarded.

root@shelf-pi:~# apt install tor Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: libevent-2.0-5 logrotate tor-geoipdb torsocks Suggested packages: mixmaster xul-ext-torbutton socat tor-arm polipo privoxy apparmor-utils obfsproxy The following NEW packages will be installed: libevent-2.0-5 logrotate tor tor-geoipdb torsocks 0 upgraded, 5 newly installed, 0 to remove and 68 not upgraded. Need to get 107 kB/2,355 kB of archives. After this operation, 9,842 kB of additional disk space will be used. Do you want to continue? [Y/n] … # setup a hidden (aka onion) service and point it to SSH root@shelf-pi:~# echo "HiddenServiceDir /var/lib/tor/ssh_hidden_service/" >> /etc/tor/torrc root@shelf-pi:~# echo "HiddenServicePort 22 127.0.0.1:22" >> /etc/tor/torrc # restart tor to apply the change root@shelf-pi:~# systemctl restart tor # confirm the service was provisioned, obtain the onion domain root@shelf-pi:~# ls /var/lib/tor/ssh_hidden_service/ hostname private_key root@shelf-pi:~# cat /var/lib/tor/ssh_hidden_service/hostname s7wgpiadcsilb3dd.onion

At this point, You can now SSH from the clear internet to this onion service!

ben@eshwil:~$ ssh root@s7wgpiadcsilb3dd.tor6.flm.me.uk The authenticity of host 's7wgpiadcsilb3dd.tor6.flm.me.uk (2a07:1500:fed5:97ec:67a0:314:90b0:ec63)' can't be established. ECDSA key fingerprint is SHA256:sB2143z+Ls85q4QOs6hAPrP0A50WhelrAy2Xo8Th5ig. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 's7wgpiadcsilb3dd.tor6.flm.me.uk,2a07:1500:fed5:97ec:67a0:314:90b0:ec63' (ECDSA) to the list of known hosts. The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Apr 3 20:40:48 2018 from root@shelf-pi:~#

Or! You can CNAME directly to this domain!

Then use it as a subdomain:

ben@eshwil:~$ ssh root@shelf-pi.benjojo.co.uk The authenticity of host 'shelf-pi.benjojo.co.uk (2a07:1500:fed5:97ec:67a0:314:90b0:ec63)' can't be established. ECDSA key fingerprint is SHA256:sB2143z+Ls85q4QOs6hAPrP0A50WhelrAy2Xo8Th5ig. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'shelf-pi.benjojo.co.uk' (ECDSA) to the list of known hosts. The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Apr 3 21:12:44 2018 from localhost root@shelf-pi:~#

Closing

As always, you can find the source code to this here: https://github.com/benjojo/six-onions

If you liked this, I’m currently at the Recurse Center and spending the next 12 weeks working on things like this and writing them up, so follow me on twitter or RSS to know when the next one of these come out!