We will use our VPN server to connect to different hosts. In other words, the VPN server will be our gateway, and all the connections we make will appear as originated from the VPN server.

Plan

We will connect from client to a public web page via server. The web page we will be connecting to will be one of those that tell you which IP address you have. There are plenty of them, for example:

We will use http://api.ipify.org because you can query your IP from the command line quite easily. Since we will be connecting to a web page we will test the OpenVPN for HTTP connections, but it would be the same for SSH, FTP, etc.

Server configuration

Enable IP forwarding

/etc/sysctl.conf:
-----------------
...
net.ipv4.ip_forward=1
(server)_$: sudo sysctl -p /etc/sysctl.conf
(server)_$: iptables -A FORWARD -i tun+ -o eth0 -j ACCEPT
(server)_$: iptables -A FORWARD -i eth0 -o tun+ -j ACCEPT

Enable Masquerading

(server)_$: iptables -t nat -A POSTROUTING -s 10.200.0.0/16 -o eth0 -j MASQUERADE

We can save the iptables IP forwarding and masquerading commands in the iptables rules file for the next time:

/etc/iptables.up.rules:
-----------------------
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.200.0.0/16 -o eth0 -j MASQUERADE
COMMIT
###############################################################################
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-P INPUT DROP
-P FORWARD DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22    -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 1194  -j ACCEPT
-A INPUT -j DROP
-A FORWARD -i tun+ -o eth0 -j ACCEPT
-A FORWARD -i eth0 -o tun+ -j ACCEPT
COMMIT

Start OpenVPN

(server)_$: openvpn --config /etc/openvpn/proxy-vpn.conf

Client

a) Use the OpenVPN’s redirect-gateway option

  • Pros: Simply add an option to a configuration file.
  • Cons: Redirects ALL traffic (SSH, HTTP, FTP, DNS, etc) to the tunnel. It is quite possible that we have some difficulties with the DNS traffic (easy to solve) and DHCP (not so easy to solve).

Well, I lied when I said it was only the redirect-gateway option what you had to change. You will have to add four options, but we will be solving the DNS issue at the same time, so it is worth it. To solve the DNS issue we will use one of Google’s DNS servers (thanks Google), actually the good old 8.8.8.8 server.

/etc/openvpn/proxy-vpn.conf:
----------------------------
# Server
remote <server IP address>

# Networking
dev tun
ifconfig 10.200.0.2 10.200.0.1
redirect-gateway def1
dhcp-option DNS 8.8.8.8

# Security
secret /etc/openvpn/certs/static.key

# Only in (some?) Linux clients
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf
(client)_$: openvpn --config /etc/openvpn/proxy-vpn.conf

b) Use the route command to add routes.

  • Pros: Highly customizable.
  • Cons: Needs to be done manually.
(client)_$: dig server.com +short
<server IP address>
(client)_$: route add -host <server IP address> gw 10.200.0.1
(client)_$: route -n
Kernel IP routing table
Destination         Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0             192.168.1.1     0.0.0.0         UG    0      0        0 eth0
10.200.0.1          0.0.0.0         255.255.255.255 UH    0      0        0 tun0
<server IP address> 10.200.0.1      255.255.255.255 UGH   0      0        0 tun0
...

Check

(client)_$: curl api.ipify.org
<server IP address>

Troubleshooting

Is the tunnel ok?

(client)_$: ping 10.200.0.1

Are we sending to and receiving from <server IP address>?

(server)_$: tcpdump -i tun0

Is DNS working?

(client)_$: ping 8.8.8.8        # Can you ping IP addresses?
(client)_$: ping google.com     # Can you ping DNS names?

Are we correctly forwarding packets?

(server)_$: iptables -A FORWARD -j ACCEPT

Are the packets going out via the VPN server or are they taking some other route?

(client)_$: traceroute <server IP address>
(client)_$: traceroute 8.8.8.8