Friday, January 18, 2013

TOR relay and transparent routing

I assume you already know about TOR, The Onion Router for anonymity to protect your privacy.

TOR is a network so it can only work if there are nodes (relays). If you have a server, you can run one so consider it. Afraid of legal issues? You do not need to run an exit node, a relay is just fine: everything is encrypted.

This post will show you how easy it is to set up a TOR relay on Debian, how to nicely monitor it and how to use it as a transparent router.


Setup

Simple: a NAT router and behind a LAN with a server and a workstation.
           ________                ________
 internet |        |      LAN     |        |
----------| (NAT)  |--------------| server | 192.168.0.1
 1.2.3.4  | router |---------.    |________|
          |________|         |
                       ______|______
                      |             |
                      | workstation | 192.168.0.2
                      |_____________|
 

Install

If you are not root, use sudo -i or su to get a root shell then:
# echo 'deb http://deb.torproject.org/torproject.org squeeze main' \
  >> /etc/apt/sources.list
# gpg --recv 74A941BA219EC810
# gpg --export --armor 74A941BA219EC810 | apt-key add -
# apt-get update
# apt-get install tor

Prepare a control password

You will need a password to remotely control your TOR server:
$ tor --hash-password test
[...]
16:A908451A24E6A06D604B4D30592A14A177FD276103658D4F10D9C4B12F

Configuration

Open /etc/tor/torrc with your favourite editor and configure a few things:
# TOR SOCKS port
SocksPort 0.0.0.0:9050

# Control port
ControlPort 0.0.0.0:9051
HashedControlPassword 16:A908451(...the hash above...)10D9C4B12F

# TOR relay port
ORPort 9001

# Throttle traffic to 100KB/s (800Kbps) but allow bursts up to 200KB/s (1600Kbps)
RelayBandwidthRate 100 KB
RelayBandwidthBurst 200 KB

# No exits allowed, just be a relay node
ExitPolicy reject *:*

# Transparent router
VirtualAddrNetwork 10.192.0.0/10
AutomapHostsOnResolve 1
TransPort 0.0.0.0:9040
DNSPort 0.0.0.0:53
Apply:
# invoke-rc.d tor reload

Firewall

I like iptables with ferm, for easy rule making. Edit /etc/ferm/ferm.conf:
domain ip {
  table filter {
    chain INPUT {
      proto tcp dport 9001 ACCEPT; # ORPort
      saddr 192.168.0.0/24 {
        proto udp dport 53 ACCEPT;   # DNSPort
        proto tcp dport 9040 ACCEPT; # TransPort
        proto tcp dport 9050 ACCEPT; # SocksPort
        proto tcp dport 9051 ACCEPT; # ControlPort
      }
    }
  }
  table nat {
    chain PREROUTING {
      interface eth0 saddr 192.168.0.0/24 {
        # Do not redirect RFC1918, except VirtualAddrNetwork (10.192.0.0/10)
        daddr (10.0.0.0/9 10.128.0.0/10 172.16.0.0/12 192.168.0.0/16) ACCEPT;
        proto tcp syn REDIRECT to-ports 9040; # TransPort
      }
    }
  }
  # Make sure NOT to forward traffic (e.g. udp which does not go via TOR)
  table FORWARD policy DROP;
}
Apply:
# invoke-rc.d ferm reload

Port forwarding

The only port you need to forward from your router to your TOR server is 9001.
If your router is also a Linux server, you can do this with ferm again. Edit /etc/ferm/ferm.conf:
domain ip {
  table nat {
    chain PREROUTING {
      daddr 1.2.3.4 {
        proto tcp dport 9001 DNAT to 192.168.0.1; # ORPort
      }
    }
  }
}
Apply:
# invoke-rc.d ferm reload

Monitoring

I like ARM, the Anonymizing Relay Monitor in console:

Arm bandwidth graph and log

Install:
# apt-get install tor-arm
And start it:
# arm
You can also run arm remotely, by connecting on the ControlPort (9051) and using the control password.

Use TOR on the workstation

Instead of using TOR for the whole system, let's add a tor user that will pass through TOR, while other users still use the normal connection:
# adduser tor
And now it is policy routing on user.

Edit /etc/ferm/ferm.conf to apply specific rules to tor user:
  1. mark packets for later specific routing
  2. redirect DNS requests to TOR resolver instead of your DNS resolver to avoid DNS leak
@def $RESOLVERS = `awk '$1=="nameserver"{print $2}' /etc/resolv.conf`;

domain ip {
  table mangle {
    chain OUTPUT {
      mod owner uid-owner tor MARK set-mark 0x1;
    }
  }
  table nat {
    chain OUTPUT {
      mod owner uid-owner tor daddr $RESOLVERS
        proto (tcp udp) dport 53 DNAT to 192.168.0.1;
    }
  }
}
Apply:
# invoke-rc.d ferm reload
And route packets differently based on the mark:
# ip rule add fwmark 0x1 table 100
# ip route add default via 192.168.0.1 table 100
# ip route flush cache
To persist after reboot, edit /etc/network/interfaces and add 3 post-up to your network interface:
auto eth0
iface eth0 inet static
  address 192.168.0.2
  netmask 255.255.255.0
  gateway 192.168.0.254

  post-up ip rule add fwmark 0x1 table 100
  post-up ip route add default via 192.168.0.1 table 100
  post-up ip route flush cache
Now try:
tor$ curl ifconfig.me
[not your IP but a TOR exit node]

8 comments:

  1. This is great, but it depends entirely on iptables, which is unfortunately Linux specific. Do you know if there is a similar setup for running a tor relay on FreeBSD.

    ReplyDelete
  2. It must be possible on FreeBSD too but I don't know the details.

    ReplyDelete
  3. What is the real sense of Tor when your net speed decrease of around 50-60%?
    Maybe just to get some INFO
    Nice INFO indeed
    Ciao

    ReplyDelete
  4. Great post d: what about adding Privoxy to the mix.. I just installed this into a VPS not a pretty picture, I also want to add torsocks, I love to hear your take on this.

    ReplyDelete
  5. @Feb 7th comment: yes TOR will be slower than your regular connection, but it gives you privacy and security. See https://www.torproject.org/about/overview.html.en for more information. Also, adding more relays on fast connections will help TOR network to be faster!

    @Feb 8th comment: yes if you need an HTTP proxy in addition to TOR's socks proxy, privoxy will do that for you.
    And yes torsocks is great, enables you to use TOR transparently: "usewithtor curl ifconfig.me" (replacing connect calls).

    ReplyDelete
  6. Thank you for sharing, works perfect!
    I have same network configuration as you, except one thing: on router i have lighthttpd and torrent server deluged, what can i do to send their traffic trough tor too?
    Sorry for my English, i am not native speaker.

    ReplyDelete
  7. You can do it on router itself with policy routing: create user, run programs under that user, mark packets from that user in netfilter and route them separately. You can inspire from part 2 of http://blog.stalkr.net/2012/04/pptp-vpn-and-policy-routing-on-user.html
    Good luck!

    ReplyDelete
  8. THIS is how it should be done.. :D

    root@tor:/etc# cat /etc/tor/torrc|grep -v ^#|grep -v ^$
    Log notice file /var/log/notices.log
    AutomapHostsSuffixes .onion,.exit
    AutomapHostsOnResolve 1
    ExitPolicy reject *:* # no exits allowed
    CircuitBuildTimeout 5
    KeepalivePeriod 60
    NewCircuitPeriod 15
    AvoidDiskWrites 1
    ExcludeNodes {??},{gb},{us},{fr}
    ExcludeSingleHopRelays 1
    AllowSingleHopCircuits 0
    ClientOnly 1
    ConstrainedSockets 1
    ReachableDirAddresses *:80
    ReachableORAddresses *:443
    SocksPort 9050
    SocksListenAddress 127.0.0.1
    DNSPort 53
    DNSListenAddress 10.42.0.1
    TransPort 9040
    TransListenAddress 10.42.0.1
    root@tor:/etc# cat iptables-rules
    #----------------------------------------------------------------
    *filter
    #----------------------------------------------------------------
    :INPUT DROP [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT DROP [0:0]
    #----------------------------------------------------------------
    # INDPUT
    #----------------------------------------------------------------
    -A INPUT -i lo -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -i lo -j DROP
    -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -i eth0 -j DROP
    -A INPUT -i wlan0 --src 10.42.0.0/24 --dst 10.42.0.1 -p udp -m udp --dport 53 -j ACCEPT
    -A INPUT -i wlan0 --src 10.42.0.0/24 -p tcp -m tcp --dport 9040 -j ACCEPT
    -A INPUT -i wlan0 --src 10.42.0.0/24 -p tcp -m tcp --dport 60000 -j ACCEPT
    -A INPUT -i wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -i wlan0 -j DROP
    -A INPUT -m state --state INVALID -j DROP
    #----------------------------------------------------------------
    # OUTPUT
    #----------------------------------------------------------------
    -A OUTPUT -o lo -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A OUTPUT -o eth0 -m owner --uid-owner debian-tor -p udp -m udp --dport 53 -j ACCEPT
    -A OUTPUT -o eth0 -m owner --uid-owner debian-tor -p tcp -m tcp --dport 80 -j ACCEPT
    -A OUTPUT -o eth0 -m owner --uid-owner debian-tor -p tcp -m tcp --dport 443 -j ACCEPT
    -A OUTPUT -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A OUTPUT -o eth0 -j DROP
    -A OUTPUT -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A OUTPUT -m state --state INVALID -j DROP
    -A FORWARD -m state --state INVALID -j DROP
    #----------------------------------------------------------------
    COMMIT
    #----------------------------------------------------------------
    *nat
    #----------------------------------------------------------------
    :PREROUTING ACCEPT [32:4626]
    :INPUT ACCEPT [195:15210]
    :OUTPUT ACCEPT [3:216]
    :POSTROUTING ACCEPT [4:292]
    -A PREROUTING -i wlan0 --src 10.42.0.0/24 -p tcp -m tcp --dport 22 -j REDIRECT --to-ports 60000
    -A PREROUTING -i wlan0 --src 10.42.0.0/24 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9040
    -A PREROUTING -i wlan0 --src 10.42.0.0/24 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 9040
    -A PREROUTING -i wlan0 --src 10.42.0.0/24 -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports 9040
    #----------------------------------------------------------------
    COMMIT
    #----------------------------------------------------------------
    root@tor:/etc# cat network/interfaces
    #---------------------------------
    # LOOPBACK - lo0
    #---------------------------------
    auto lo
    iface lo inet loopback
    #---------------------------------
    # ETH - eth0
    #---------------------------------
    auto eth0
    iface eth0 inet dhcp
    pre-up ifconfig eth0 hw ether 00:40:B7:13:37:01
    #----------------------------------
    # WLAN - wlan0
    #----------------------------------
    auto wlan0
    iface wlan0 inet static
    address 10.42.0.1
    netmask 255.255.255.0
    network 10.42.0.0
    broadcast 10.42.0.255
    pre-up ifconfig wlan0 hw ether 00:40:B7:13:37:00
    #----------------------------------
    up /sbin/iptables-restore < /etc/iptables-rules

    ReplyDelete