Quantcast
Channel: Tutorials — LowEndTalk
Viewing all articles
Browse latest Browse all 1028

OpenVPN with public IPv6 for clients, port forwarding and HTTPS encapsulation

$
0
0

Hi!

First and foremost, I wish to state that I do not have extensive knowledge in the matters of what I am sharing here. I am writing this a form of documentation of the processes I went through and decided to share it to those who are interested.

Introduction

That said, in this post, I am going to share the way I setup my OpenVPN on my VPS with IPv6 enabled which assigns public IPv6 addresses to clients connected to it. This is perfect for people who want a public IPv6 address but do not have native IPv6 on their internet connection. You will need a VPS which has an IPv6 subnet (a /64 will do just fine). It does not matter if it is 'routed' to you or you need to manually assign addresses from within the VPS control panel such as SolusVM. In my case, it is the latter. If you use a tunnel broker service such as Hurricane Electric's Tunnel Broker [1], you may refer to this guide [2] (it is an inspiration for this guide as well). As for IPv4, either public or NAT address works just fine.

In addition, since OpenVPN traffic is distinguishable from normal HTTPS traffic that setting up OpenVPN on port 443 would not be able to fool some advanced firewalls, I will also be sharing how I encapsulate the OpenVPN traffic in HTTPS using a combination of TLS/SSL tunneling application and a protocol multiplexer application so that passive firewalls (which just observe traffic as compared to an active firewall which probes the connection; refer to this relevant information [3]) would not be able to tell that the payload is the OpenVPN traffic.

Since we are using a protocol multiplexer which supports connection to multiple protocol under a single HTTPS connection and directs the traffic based on their pattern, we are going to install a simple web server as well that is running on port 443 (or any port of your choosing) so that -- for instance -- if people are curious about the connection and decide to enter the VPS IP using a browser will be connected to the web server instead of the OpenVPN server.

As a bonus, inspired by an iptables tutorial [4], we are also including a few iptables rules for the purposes of port forwarding to be used by our OpenVPN clients just in case they wish to have the ability to bind a port so the outside world may connect to them using IPv4. If you are using a NAT VPS, these ports will be made available to you by your host. As for IPv6 this is not necessary as we are assigning globally routable addresses for them.

This guide is based on my OS install which is Debian 9 (Stretch) on a KVM platform. Your mileage may vary depending on your OS and virtualisation technology. I apologise as I might be unable to help if your setup is different than what I have.

Please note that all commands need to be run as root.

The application and script we will be using are:

  • OpenVPN [5] (using Nyr's script [6])
  • sslh [7]
  • stunnel [8]
  • nginx [9]

Steps

  1. Add a subnet from our /64 (for example a /112) for our OpenVPN server. This will be dependent upon two things:

    [1a] If you have a 'routed' /64 (that is, the provider routed a subnet directly to your single /64 address), then you do not have to do anything on this stage.

    [1b] If your /64 is assigned to a control panel such as SolusVM (as with the case of many providers), then you will need to manually add the addresses from within the panel. You will need to add three types of address (let us assume our /64 subnet is 2001:0db8:85a3:1ab2::/64):

    • Main VPS address: This one you can just assign any address from your /64 as it will be used as the primary IPv6 address of your VPS. Example in our scenario: 2001:0db8:85a3:1ab2::1

    • Main OpenVPN server address: In our case, we choose a /112 subnet and assigned a primary IP to be used as the main OpenVPN server address. For example, as the subnet for our VPS is 2001:0db8:85a3:1ab2::/64, we are going to assign 2001:0db8:85a3:1ab2:0:0:2b1a::/112 for OpenVPN. With that, we choose 2001:0db8:85a3:1ab2:0:0:2b1a:1 as the main OpenVPN server address, so we add that IP to SolusVM.

    • OpenVPN clients addresses: By default, OpenVPN assigns addresses from :1000 (example: 2001:0db8:85a3:1ab2:0:0:2b1a:1000). This one depends on your preference. If you have five clients, then add :1000 until :1004. Please note that IPv6 uses hexadecimal addressing, so if you add 11 clients, the 10th client would be :1009 and the 11th client would be :100a (followed until :100f, then :1010, and so on). Note also the subnet. In our case, it is a /112, so we need to add ::2b1a:1000, ::2b1a:1001, and so on in the control panel.

    For this guide, we are going to assume we have the following IP information:

        VPS IPv4 IP: 8.8.8.100
        VPS IPv4 NM: 255.255.255.0
        VPS IPv4 GW: 8.8.8.1
    
        VPS IPv6 IP: 2001:0db8:85a3:1ab2::1
        VPS IPv6 NM: /48
        VPS IPv6 GW: 2001:0db8:85a3::1
    
        OVPN IPv4 IP: 10.8.0.1 (server)
                      10.8.0.2 and above (clients)
        OVPN IPv4 NM: /24
    
        OVPN IPv6 IP: 2001:0db8:85a3:1ab2:0:0:2b1a:1 (server)
                      2001:0db8:85a3:1ab2:0:0:2b1a:1000 and above (clients)
        OVPN IPv6 NM: /112
    

    Please refer to the information provided by your host regarding gateway and netmask settings, especially for IPv6.

  2. Apply the IP information to our /etc/network/interfaces file. Please take note the interface name (check using "ip addr" command; in my case it is "enp0s3") I prefer to rewrite the file using this template:

    source /etc/network/interfaces.d/*
    
    auto lo
    iface lo inet loopback
    iface lo inet6 loopback
    
    auto enp0s3
    iface enp0s3 inet static
            address 8.8.8.100
            netmask 255.255.255.0
            gateway 8.8.8.1
    iface enp0s3 inet6 static
            address 2001:0db8:85a3:1ab2::1
            netmask 48
            gateway 2001:0db8:85a3::1
    
  3. Edit your /etc/resolv.conf to include both IPv4 and IPv6 DNS addresses. In my case it is Google DNS:

    nameserver 8.8.8.8
    nameserver 8.8.4.4
    nameserver 2001:4860:4860::8888
    nameserver 2001:4860:4860::8844
    
  4. Install OpenVPN using Nyr's script [6]. During setup, choose TCP and not UDP. You may choose any port (I suggest the default port) but if you use NAT VPS, please use the provided port by your host and take note of it.

  5. Add these lines to the end of /etc/openvpn/server.conf file (note the OpenVPN /112 subnet and the VPS IPv4 address):

    server-ipv6 2001:0db8:85a3:1ab2:0:0:2b1a::/112
    push "redirect-gateway-ipv6 def1 bypass-dhcp-ipv6"
    push "route-ipv6 2000::/3"
    push "route 8.8.8.100 255.255.255.255 net_gateway"
    

    You may need to push an IPv6 route to your /64 (I do not apply it but some tutorials include this, so if you have IPv6 problems later on, you might need to add it):

    push "route-ipv6 2001:0db8:85a3:1ab2::/64"
    

    If you need to push IPv6 DNS, add:

    push "dhcp-option DNS6 2001:4860:4860::8888"
    push "dhcp-option DNS6 2001:4860:4860::8844"
    

    If you wish for the clients to be able to connect each other through the internal OpenVPN network, add:

    client-to-client
    

    Restart the OpenVPN server using "systemctl restart openvpn@server.service".

  6. Add these lines to the end /etc/sysctl.conf file:

    net.ipv6.conf.all.forwarding = 1
    net.ipv6.conf.all.proxy_ndp = 1
    

    Then, run "sysctl -p".

  7. In Debian 9, /etc/rc.local is no longer supported (replaced by systemd). As Nyr's script is still using /etc/rc.local to implement some iptables rules and we are also going to use it to include our own iptables rules, we need to enable it. Following the guide on [10], we can enable it as a systemd service.

    First, create /etc/systemd/system/rc-local.service file with this:

    [Unit]
    Description=/etc/rc.local Compatibility
    ConditionPathExists=/etc/rc.local
    
    [Service]
    Type=forking
    ExecStart=/etc/rc.local start
    TimeoutSec=0
    StandardOutput=tty
    RemainAfterExit=yes
    SysVStartPriority=99
    
    [Install]
    WantedBy=multi-user.target
    

    Run "systemctl enable rc-local.service" and "systemctl start rc-local.service".

  8. As our OpenVPN server assigns global addresses to clients, we need to instruct our VPS to add NDP proxy to the OpenVPN IPv6 addresses (refer to [11]). Create a file in your home directory (/root) called openvpn-rules.sh containing this:

    #!/bin/bash
    
    echo -e "ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1 dev enp0s3"
    
    for i in {0..5}; do
        echo -e "ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:$(printf %x $(($i+0x1000))) dev enp0s3"
    done
    

    Change {0..5} accordingly to suit your needs. For example, we have six IPv6 addresses assigned to clients.

    If you have a 'routed' subnet, then you may skip this step (no need for NDP).

  9. To allow port forwarding for your clients, add these lines in the same file (/root/openvpn-rules.sh):

    for i in {0..5}; do
        echo -e "iptables -t nat -A PREROUTING -p tcp --dport $((10000+$i+2)) -j DNAT --to 10.8.0.$(($i+2)):$((10000+$i+2))"
        echo -e "iptables -A FORWARD -d 10.8.0.$(($i+2)) -p tcp --dport $((10000+$i+2)) -j ACCEPT"
    done
    

    Please adjust {0..5} accordingly to align with the NDP proxy lines. In the case above, our base port is 1000. I had offset the number by 2, so it will align the internal IPv4 address of the clients. So, the server will assign the ports as such:

    10.8.0.2 -> 10002
    10.8.0.3 -> 10003
    [...]
    
  10. The commands above, when made executable and executed, will not run as I had made it to only echo the output (just a preference; you may edit it so it runs directly).

    That said, we need to run openvpn-rules.sh and output it to a text file which we will later add to /etc/rc.local file.

    # chmod +x /root/openvpn-rules.sh
    # /root/openvpn-rules.sh > /root/openvpn-rules_output.txt
    

    Verify the contents of the openvpn-rules_output.txt as such:

    # cat /root/openvpn-rules_output.txt
    
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1 dev enp0s3
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1000 dev enp0s3
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1001 dev enp0s3
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1002 dev enp0s3
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1003 dev enp0s3
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1004 dev enp0s3
    ip -6 neigh add proxy 2001:0db8:85a3:1ab2:0:0:2b1a:1005 dev enp0s3
    iptables -t nat -A PREROUTING -p tcp --dport 10002 -j DNAT --to 10.8.0.2:10002
    iptables -A FORWARD -d 10.8.0.2 -p tcp --dport 10002 -j ACCEPT
    iptables -t nat -A PREROUTING -p tcp --dport 10003 -j DNAT --to 10.8.0.3:10003
    iptables -A FORWARD -d 10.8.0.3 -p tcp --dport 10003 -j ACCEPT
    iptables -t nat -A PREROUTING -p tcp --dport 10004 -j DNAT --to 10.8.0.4:10004
    iptables -A FORWARD -d 10.8.0.4 -p tcp --dport 10004 -j ACCEPT
    iptables -t nat -A PREROUTING -p tcp --dport 10005 -j DNAT --to 10.8.0.5:10005
    iptables -A FORWARD -d 10.8.0.5 -p tcp --dport 10005 -j ACCEPT
    iptables -t nat -A PREROUTING -p tcp --dport 10006 -j DNAT --to 10.8.0.6:10006
    iptables -A FORWARD -d 10.8.0.6 -p tcp --dport 10006 -j ACCEPT
    iptables -t nat -A PREROUTING -p tcp --dport 10007 -j DNAT --to 10.8.0.7:10007
    iptables -A FORWARD -d 10.8.0.7 -p tcp --dport 10007 -j ACCEPT
    
  11. Run the text file from /etc/rc.local file. Add this line in /etc/rc.local before "exit 0".

    bash /root/openvpn-rules_output.txt
    
  12. I suggest that you reboot your VPS and test your connection to the OpenVPN with your desktop and/or phone using the generated client file (transfer the .ovpn file to your device). Ensure that everything works well, including the port forwarding. Use applications such as netcat [12] to test it (one tutorial can be found here [13]).

    Check whether port forwarding is setup correctly by using netcat and verifying it with external sites like this [14].

    If everything works, we can go on to the next phase, which is to setup HTTPS encapsulation.

  13. Install stunnel4 and sslh ("apt-get install stunnel4 sslh"). Choose "inetd" when presented with the configuration of sslh.

  14. Generate a self-signed certificate [15]. You may use services such as Let's Encrypt but I find it easier to just use a self-signed certificate. In this instance, we are generating a 2048-bits certificate with 10 years validity. Change according to your needs.

    # openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 3650 -nodes
    # cat key.pem cert.pem > fullcert.pem
    # cp fullcert.pem /etc/ssl/private/.
    # chmod 600 /etc/ssl/private/fullcert.pem
    
  15. Configure stunnel4 and sslh on the VPS.

    Create /etc/stunnel/stunnel.conf file containing this:

    [sslh]
    accept = 443
    cert = /etc/ssl/private/fullcert.pem
    exec = /usr/sbin/sslh
    execArgs = sslh -t 5s -i --http 127.0.0.1:80 --openvpn 127.0.0.1:1194
    

    Edit /etc/default/stunnel4 file and change "ENABLED=0" to "ENABLED=1".

    Run "systemctl restart stunnel4.service".

    Reboot just to be on the safe side.

  16. Install stunnel4 on your computer or phone. Setup the configuration file (create /etc/stunnel/stunnel.conf file if you are on Linux; edit it from within the stunnel application if you are on Windows):

    [sslh]
    client = yes
    accept = 8443
    connect = 8.8.8.100:443
    

    "accept = 8443" can be any port number that is available on your computer or phone.

    Reload the configuration file by running "systemctl restart stunnel4.service" on Linux or choose the menu "Reload configuration file" on Windows.

    If you use Android, you can use the SSLDroid [16] application with the following configuration:

    Tunnel name: (Anything)
    Local port: 8443
    Remote host: 8.8.8.100
    Remote port: 443
    
  17. Create a copy of the .ovpn file with the necessary changes to connect to the OpenVPN server through stunnel.

    Change "remote 8.8.8.100 1194" line in our copy of client .ovpn file to "remote 127.0.0.1 8443".

  18. We may now connect to the OpenVPN server using the second profile if we wish to connect through 443 and the first profile for a direct connection. It is recommended to use direct connection whenever possible so that we do not add unnecessary overhead by having two forms of encryption.

    Check IPv4 and IPv6 connectivity with sites like [17], [18] and [19].

    Please note if you use Windows, you may need to configure Windows Firewall to allow ICMP ping (I just disable Windows Firewall; I know it is bad but I am okay with it). Refer to this guide [20]. Follow similar steps if you use other firewalls.

    Test reachability of clients's IPv6s address by going to ping sites like this [21].

Well, that is about it! This guide is written in one go, so I apologise for any mistakes and oversight I may have made.

Good luck and enjoy your OpenVPN connection!


References:

[1] https://tunnelbroker.net/ [2] https://lasse-it.dk/2015/08/how-to-setting-up-openvpn-with-individual-public-ipv6s-for-clients/ [3] https://serverfault.com/a/681497 [4] https://www.systutorials.com/816/port-forwarding-using-iptables/ [5] https://openvpn.net/ [6] https://github.com/Nyr/openvpn-install [7] http://www.rutschle.net/tech/sslh.shtml [8] https://www.stunnel.org/ [9] https://nginx.org/en/ [10] https://www.linuxbabe.com/linux-server/how-to-enable-etcrc-local-with-systemd [11] https://unix.stackexchange.com/a/136819 [12] http://nc110.sourceforge.net/ [13] http://www.binarytides.com/netcat-tutorial-for-beginners/ [14] http://www.canyouseeme.org/ [15] https://stackoverflow.com/a/10176685 [16] https://play.google.com/store/apps/details?id=hu.blint.ssldroid&hl=en [17] http://ipv6-test.com/ [18] http://test-ipv6.com/ [19] http://ds.testmyipv6.com/ [20] https://technet.microsoft.com/en-us/library/cc749323(v=ws.10).aspx [21] http://centralops.net/co/


Viewing all articles
Browse latest Browse all 1028

Trending Articles