OpenVPN for certain IPs, eth0 for everything else
Summary: I'd like to connect to my VPN and have access to certain servers, but for all other traffic I'd like to use my regular networking.
I've setup an OpenVPN server on my VPS, my server.conf
file looks like so:
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
log /var/log/openvpn.log
verb 4
push "route 10.132.0.0 255.255.0.0"
I use the following .ovpn
file to setup the VPN Connection:
client
dev tun
proto udp
remote <my.vpn.server.com> 1194
nobind
user nobody
group nogroup
persist-key
persist-tun
remote-cert-tls server
comp-lzo
verb 3
<ca>....</ca>
<cert>...</cert>
<key>...</key>
Finally, in the Network Manager for the VPN Connection, under IPv4 Settings I have made sure to set the "Method" to "Automatic (VPN) addresses only".
VPN connects fine, I can access all the internal servers I need (10.132.x.x), however I cannot access anything else (like google.com). I'd like my eth0 settings to be used for everything except for the 10.132.x.x IPs which I would like routed through the VPN.
P.S. based on other articles I've tried using no-pull
in the .ovpn file and adding in my route
settings there but to no avail.
EDIT 1:
Results of running ip a
and traceroute
while connected to VPN:
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:dc:a6:ef brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
valid_lft 86320sec preferred_lft 86320sec
inet6 fe80::f3d1:6eb3:e13e:d61b/64 scope link
valid_lft forever preferred_lft forever
15: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.8.0.6 peer 10.8.0.5/32 brd 10.8.0.6 scope global tun0
valid_lft forever preferred_lft forever
$ traceroute google.com
google.com: Temporary failure in name resolution
Cannot handle "host" cmdline arg `google.com' on position 1 (argc 1)
EDIT 2: results of ip r
$ ip r
default via 10.8.0.5 dev tun0 proto static metric 50
default via 10.0.2.2 dev eth0 proto static metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
10.8.0.1 via 10.8.0.5 dev tun0 proto static metric 50
10.8.0.5 dev tun0 proto kernel scope link src 10.8.0.6 metric 50
10.132.0.0/16 via 10.8.0.5 dev tun0 proto static metric 50
104.236.239.153 via 10.0.2.2 dev eth0 proto static metric 100
169.254.0.0/16 dev eth0 scope link metric 1000
The "Use this connection only for resources on its network" checkbox in nm-connection-editor controls whether NetworkManager should add a default route through the VPN. If it is checked, as you did, only packets directed to the VPN subnet will go through the VPN gateway and the system will use the existing default route for other destinations.
You can change the same setting from command line using nmcli:
nmcli connection modify <VPN connection> ipv4.never-default yes
I managed to get the desired effect by playing around with the client GUI (Ubuntu NetworkManager). I had to make sure the checkbox under IPv4 Settings -> Routes
for "Use this connection only for resources on its network" was checked:
I'm not entirely sure what I would need to do in the .ovpn file in order to replicate this.
My routing table now looks like so:
$ sudo netstat -r -n
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.8.0.1 10.8.0.5 255.255.255.255 UGH 0 0 0 tun0
10.8.0.5 0.0.0.0 255.255.255.255 UH 0 0 0 tun0
10.132.0.0 10.8.0.5 255.255.0.0 UG 0 0 0 tun0
104.236.239.153 10.0.2.2 255.255.255.255 UGH 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
Remember that I had the push "route 10.132.0.0 255.255.0.0"
in my server.conf
so that explains the entry for 10.132.0.0
and thus why I can now access my servers while everything else is routed outside the VPN (i.e. the 0.0.0.0
entry)
Without this setting being checked in the GUI my routing table looked like this:
$ sudo netstat -r -n
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.8.0.5 0.0.0.0 UG 0 0 0 tun0
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.8.0.1 10.8.0.5 255.255.255.255 UGH 0 0 0 tun0
10.8.0.5 0.0.0.0 255.255.255.255 UH 0 0 0 tun0
10.132.0.0 10.8.0.5 255.255.0.0 UG 0 0 0 tun0
104.236.239.153 10.0.2.2 255.255.255.255 UGH 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
My guess is that first 0.0.0.0
entry (default route) was messing everything up.
To expound on jdmorei's answer, you need what is called a "split tunnel" VPN - you actually almost had the solution when you stated: P.S. based on other articles I've tried using no-pull in the .ovpn file and adding in my route settings there but to no avail.
.
You will want the following in your ovpn file:
route-nopull # Make sure not to pull the default routes
route 10.8.0.0 255.255.255.0 # Route the /24 of 10.8.0.0 across the VPN
route 192.168.2.2 255.255.255.255 # Route the /32 (single IP) across the VPN
Now the key is that, since you are running windows, you must run the openvpn application as an administrator. If you do not, you will see entries in the log like:
Sat Nov 13 11:31:05 2010 ROUTE: route addition failed using CreateIpForwardEntry
: Access denied. [status=5 if_index=11]
The requested operation requires elevation.
Sat Nov 13 11:31:05 2010 ERROR: Windows route add command failed [adaptive]: ret
urned error code 1
Sat Nov 13 11:31:05 2010 Initialization Sequence Completed