Remapping a network 1:1 via OpenVPN

I had this situation where by myself and a friend wanted to share our network with each other via a VPN. However in this case we both had used the same IP address space for our internal LAN (192.168.1.0/24) and bridging wasn't possible as we had used the same numbers in this range.

To get around this problem when the VPN was created it was setup so that it would remap the entire address space of each of our networks into another range so we would not have an overlapping IP space.

In this case the network running the openvpn server will be remapped from 192.168.1.x to 192.168.10.x.

If the client was running linux then we could make use of the iroute, route and client-config-dir openvpn commands to have the client expose their network via NAT too. With a windows client its just too hard.

The server is going to perform the NAT so that we can also use a windows openvpn client without issue. This is also useful as a road warrior as lots of cyber-cafes and companys also use this 192.168.1.x range so it allows easy access to a home network without IP overlap. Note: In the example outputs however I use a Linux client.

Inspired by http://www.nimlabs.org/~nim/dirtynat.html there had to be an easier way.

Configuration file for OPENVPN Server. Although I have used tcp:443 I recommend if you can use udp:1194.

Don't forget that you also need to configure a FIREWALL rule on your GATEWAY to forward (tcp/443) to your VPN server otherwise the client will not be able establish a tunnel.

openvpn.conf

#Begin server.conf
#port 1194
#proto udp
port 443
proto tcp
dev tun
ca keys/ca.crt
cert keys/server.crt
key keys/server.key # This file should be kept secret
dh keys/dh.pem
#Make sure this is your tunnel address pool
server 10.0.1.0 255.255.255.0
ifconfig-pool-persist ipp.txt
#This is the route to push to the client, add more if necessary
push "route 192.168.10.0 255.255.255.0"
keepalive 10 120
cipher BF-CBC #Blowfish encryption
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 6
mute 20
up ./openvpn.up

Now the magic where we NETMAP our network via the OPENVPN tunnel from 192.168.1.0/24 to 192.168.10.0/24. We must also MASQUERADE all packets to eth0 otherwise they will be presented to this interface with the IP of the tun0 nic (10.0.1.x)

$1 will be the name of the virtual network interface passed by the openvpn server in our example this is passed as tun0.

openvpn.up

#!/bin/sh
echo 1 > /proc/sys/net/ipv4/ip_forward
WLAN=$1
# Clear all chains
iptables -F
iptables -F -t nat
# Accept from the OPENVPN tunnel
iptables -I INPUT -i $WLAN -j ACCEPT
iptables -I OUTPUT -o $WLAN -j ACCEPT
# Remap our network 1:1 to a different IP space. Update openvpn.conf file too
# push "route 192.168.10.0 255.255.255.0"
iptables -t nat -A PREROUTING -i $WLAN -d 192.168.10.0/24 -j NETMAP --to 192.168.1.0/24
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

If you have any other IPTABLE configuration on your box you might want to remove the two lines that CLEAR the iptables when openvpn starts up.

Or perhaps use “down ./openvpn.down” to only remove the openvpn rules added by this script.

On the openvpn server side you're routing table will look like this. The route via the tun0 interface were automatically added by OPENVPN.

[root@bingo openvpn]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.1.2        0.0.0.0         255.255.255.255 UH    0      0        0 tun0
10.0.1.0        10.0.1.2        255.255.255.0   UG    0      0        0 tun0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
[root@bingo openvpn]#

A quick listing of the interfaces when the tunnel is up shows us what IP address has been used for the VPN tunnel.

[root@bingo openvpn]# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 00:B0:C2:02:1E:1E
          inet addr:192.168.1.13  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::2b0:c2ff:fe02:1e1e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:55623840 errors:0 dropped:137 overruns:0 frame:0
          TX packets:57635730 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:4247993585 (3.9 GiB)  TX bytes:1775265718 (1.6 GiB)
          Interrupt:10 Base address:0x2000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:476213 errors:0 dropped:0 overruns:0 frame:0
          TX packets:476213 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:43755155 (41.7 MiB)  TX bytes:43755155 (41.7 MiB)

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.0.1.1  P-t-P:10.0.1.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:487388 errors:0 dropped:0 overruns:0 frame:0
          TX packets:319625 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:184935466 (176.3 MiB)  TX bytes:19783112 (18.8 MiB)

The client side configuration is simple enough. I like to have a single PKCS12 key on the client.

Combine client keys into a pkcs12 file

openssl pkcs12 -export -in client.crt -inkey client.key -certfile ca.crt -out dbzoo-cert.p12

openvpn.conf

########################################
# OpenVPN Client Configuration
client
dev tun
proto tcp
remote remote.site.com 443
nobind
persist-tun
persist-key
keepalive 60 360
pkcs12 dbzoo-cert.p12
comp-lzo
verb 4
mute 5

Once the tunnel has been established your client side routing table will look like this. The 192.168.10.0 network route is a result of the push from the openvpn server.

[root@vpnout root]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.1.5        0.0.0.0         255.255.255.255 UH    0      0        0 tun0
10.0.1.1        10.0.1.5        255.255.255.255 UGH   0      0        0 tun0
192.168.10.0    10.0.1.5        255.255.255.0   UG    0      0        0 tun0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0

Client side network interface configuration

# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 00:0C:29:FE:6C:8D
          inet addr:192.168.1.2  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:899708 errors:0 dropped:0 overruns:0 frame:0
          TX packets:870730 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:243943585 (232.6 Mb)  TX bytes:254323062 (242.5 Mb)
          Interrupt:11 Base address:0x1424

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:62 errors:0 dropped:0 overruns:0 frame:0
          TX packets:62 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4564 (4.4 Kb)  TX bytes:4564 (4.4 Kb)

tun0      Link encap:Point-to-Point Protocol
          inet addr:10.0.1.6  P-t-P:10.0.1.5  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:278295 errors:0 dropped:0 overruns:0 frame:0
          TX packets:423061 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:17739929 (16.9 Mb)  TX bytes:176600254 (168.4 Mb)

Performing a traceroute from the CLIENT side out to a box on the SERVER side which has an IP of 192.168.1.20 but via the NAT/VPN tunnel will be 192.168.10.20.

[root@vpnout root]# traceroute 192.168.10.20
traceroute to 192.168.10.20 (192.168.10.20), 30 hops max, 38 byte packets
 1  10.0.1.1 (10.0.1.1)  56.439 ms  69.490 ms  59.346 ms
 2  192.168.10.20 (192.168.10.20)  31.985 ms  29.301 ms  63.890 ms
[root@vpnout root]#

We can see the 10.0.1.1 is the IP address of the Point-to-Point VPN server endpoint (tun0) when the VPN server route's out eth0 it will be NAT'd into the 192.168.10.x address space.