Friday, March 28, 2014

Secure IPv6 gateway / tunnel broker using OpenVPN


For several years I have been running a VPN server at home. As a computer engineer, I know how easy it is to sniff traffic and I think everybody should connect to a VPN gateway when using a public or semi-public connection such as found in hotels, airports, and so on...

Today's setup is a Raspberry Pi on Arch Linux. This however will work fine on  most Linux distributions. Instructions are given for Debian-based distributions as well.

The generation of certificates won't be explained here as this matter is explained in several other how-to's. In fact you can even choose to use simple user/passwords.

For this to work you need to have a working IPv6 connection at home. Try http://test-ipv6.com/ and check you've got a perfect 10/10 score.

2a02:3456:ef01:abcd::/64 is the prefix my ISP assigned to me.
The VPN hosts will be in the 2a02:3456:ef01:abcd:2::/80 subnet. 

On Server

  1. Install OpenVPN
    pacman -S openvpn # Arch Linux
    sudo apt-get install openvpn # Debian, Ubuntu, Raspbian...
  2. Generate the appropriate certificates.
  3. Put this in /etc/openvpn/server.conf
    # Use 443 if the default port is blocked
    port 1194
    proto tcp
    dev tun
    ca /etc/openvpn/ca.crt
    cert /etc/openvpn/server.crt
    key /etc/openvpn/server.key
    dh /etc/openvpn/dh2048.pem
    tls-auth /etc/openvpn/ta.key 0

    # IP addresses that will be assigned to VPN hosts
    # will be in the following range
    server 10.8.0.0 255.255.255.0 # IPv4
    server-ipv6 2a02:3456:ef01:abcd:2::/80 # IPv6
    # That's right, clients will have both an IPv4 and IPv6 address.

    tun-ipv6

    ifconfig-pool-persist ipp.txt

    # Tell your clients how to find your home network
    push "route-ipv6 2a02:3456:ef01:abcd::/64"
    # Redirect IPv6 traffic to your VPN tunnel
    # If you remove this line, only IPv4 will go through
    # the tunnel.
    # AGAIN! If you remove this line, only IPv4 will go through
    # the tunnel. This means if the remote LAN has IPv6 connectivity
    # it will not redirect IPv6 traffic through the tunnel,
    # rendering it mostly innefective as hosts will preferably
    # use IPv6 instead of IPv4.
    # If you are curious, 2000::/3 represents all the public
    # address space assigned by IANA.
    push "route-ipv6 2000::/3"

    # Your home network subnet. I recommend using an unusual
    # private subnet.
    # If you *have* to use 192.168.1.0/24, you should do
    # IP addresses translation (NAT) so that your home network
    # appears as something else.
    # This line may be removed if you don't want VPN hosts
    # to reach your local network. You will also need
    # additional firewall rules to enforce this as clients
    # could manually enter this route themselves.
    push "route 192.168.20.0 255.255.255.0"

    # Redirect traffic through VPN tunnel
    # This will require IP forwarding in iptables
    push "redirect-gateway def1 bypass-dhcp"


    # DNS servers. Here OpenVPN. Make sure the servers you use
    # can resolve IPv6 requests, i.e. AAAA DNS records.
    push "dhcp-option DNS 208.67.222.222"
    push "dhcp-option DNS 208.67.220.220"

    comp-lzo
    user nobody
    group nobody
    persist-key
    persist-tun
    status openvpn-status.log
    verb 3

    keepalive 10 120 # ping every 10 seconds, assume down after no answer for 120 seconds
  4. Schedule the server to launch on system boot:
    systemctl enable openvpn@server.service

    (In fact you can name your file abcde.conf, and use "abcde" instead of "server" in the previous command.)
  5. You need to forward traffic from tun0 to your IPv6 capable Ethernet home network:
     iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  6. Persist the firewall rules:
    iptables-save > /etc/iptables/iptables.rules
    ip6tables-save > /etc/iptables/ip6tables.rules

    or if you use sudo:
    sudo iptables-save | sudo tee /etc/iptables/iptables.rules
    sudo ip6tables-save | sudo tee /etc/iptables/ip6tables.rules
  7. Make sure the files are loaded on boot:
    systemctl enable iptables ip6tables
    On Debian: echo "iptables-restore < /etc/iptables/iptables.rules" >> /etc/rc.local
    echo "ip6tables-restore < /etc/iptables/ip6tables.rules" >> /etc/rc.local
  8. Allow IP forwarding. Edit /etc/sysctl.d/40-ipv6.conf:
    net.ipv6.conf.all.use_tempaddr = 2
    net.ipv6.conf.default.use_tempaddr = 2

    net.ipv6.conf.eth0.use_tempaddr = 2

    net.ipv6.conf.all.forwarding = 1

    net.ipv6.conf.default.forwarding = 0

    net.ipv6.conf.eth0.forwarding = 0
  9. Edit /etc/sysctl.d/99-sysctl.conf:
    net.ipv4.ip_forward=1

    On Debian, steps 8-9 may need to be done in the file
    /etc/sysctl.conf
  10. Reboot
On Client(s)
  1. Download the certificates from the server.
  2. Install OpenVPN
  3. Edit the client configuration (say client.conf):
    client
    dev tun
    tun-ipv6
    proto tcp
    remote your-server.com 1194
    resolv-retry infinite
    nobind
    user nobody
    group nobody
    persist-key
    persist-tun
    ca ca.crt
    cert client.crt
    key client.key
    tls-auth ta.key 1
    comp-lzo
    verb 3
  4. Run:
    sudo openvpn client.conf
  5. Ping the server:
    ping 10.8.0.1

    ping6 2a02:3456:ef01:abcd:2::1
  6. Check http://test-ipv6.com/ yields a perfect 10/10 score.

That's all folks!