Share VPN connection over Ethernet

I'm trying to setup and old pc with linux (CentOS) as an access point to a VPN I have in another home. I have two ethernet interfaces, so I want to use one to connect to internet through my router, connect to my VPN and then share that VPN connection over my second ethernet. The ip on the second device should be assigned by DHCP.

I've been reading lots of tutorials/posts, and I was able to share my plain internet connection, with my VPN down. However, once I start the VPN, no matter what my iptables/routes rules are, I'm stuck with no internet in my second device. I'm clueless about what I'm doing wrong. Could someone provide some help?

Here are my configurations: - enp2s0: this is connected to my main router. - enp0s29f7u1: this will be connected to a second device

enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP                                                                                           group default qlen 1000
    link/ether bc:ee:7b:19:89:68 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.26/24 brd 192.168.1.255 scope global noprefixroute enp2s0
       valid_lft forever preferred_lft forever
    inet6 fe80::c25c:2c9d:4777:79fc/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
enp0s29f7u1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast stat                                                                                          e UP group default qlen 1000
    link/ether 00:e0:4c:69:35:d0 brd ff:ff:ff:ff:ff:ff
    inet 10.8.0.5/24 brd 10.8.0.255 scope global noprefixroute enp0s29f7u1
       valid_lft forever preferred_lft forever
    inet6 fe80::2e0:4cff:fe69:35d0/64 scope link
       valid_lft forever preferred_lft forever

Once I connect to my VPN, there is another interface, tun0:

tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none
    inet 10.8.0.2/24 brd 10.8.0.255 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::2d75:64c0:6c21:c9d9/64 scope link flags 800
       valid_lft forever preferred_lft forever

My /etc/dhcp/dhcpd.conf has the following options:

subnet 10.8.0.0 netmask 255.255.255.0 {
  range 10.8.0.10 10.8.0.15;
  option routers 10.8.0.5;
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

The second device is getting 10.8.0.11 as ip, so I guess its working fine.

I've added the following rules using iptables:

iptables -t nat -I POSTROUTING 1 -o tun0 -j MASQUERADE
iptables -I FORWARD 1 -i tun0 -o enp0s29f7u1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 1 -i enp0s29f7u1 -o tun0 -j ACCEPT

Additional information:

  • I do have ip4 forwarding enabled: /sbin/sysctl net.ipv4.ip_forward returns net.ipv4.ip_forward = 1

  • I can access internet with the ip from my VPN server in another home as expected. However, I can only do it from the computer in which im setting up this configuration, not from the device connected through enp0s29f7u1.

  • This are the routes before/after launching the vpn.

BEFORE

ip route
default via 192.168.1.1 dev enp2s0 proto static metric 101
10.8.0.0/24 dev enp0s29f7u1 proto kernel scope link src 10.8.0.5 metric 100

AFTER

ip route

0.0.0.0/1 via 10.8.0.1 dev tun0
default via 192.168.1.1 dev enp2s0 proto static metric 101
10.8.0.0/24 dev tun0 proto kernel scope link src 10.8.0.2
10.8.0.0/24 dev enp0s29f7u1 proto kernel scope link src 10.8.0.5 metric 100
xx.xx.xx.xx via 192.168.1.1 dev enp2s0
128.0.0.0/1 via 10.8.0.1 dev tun0
192.168.1.0/24 dev enp2s0 proto kernel scope link src 192.168.1.26 metric 101

192.168.1.0/24 dev enp2s0 proto kernel scope link src 192.168.1.26 metric 101

I've replaced my VPN server public ip by xx.xx.xx.xx

What am I missing here?

EDIT: Out of desperation, I tried to bridge interfaces, even if I knew it wasn't a great idea. It didn't work either.


Solution 1:

You've got a lot of things right, so congrats on getting this far. A few things look wrong to me.

Your tun0 default route is wrong: 0.0.0.0/1 only passes half the internet to tun0. You need the other half. Try adding 128.0.0.0/1. Alternatively use 'default' or 0.0.0.0/0 to get both halves in one go, but then make sure you use a lower metric that 'default via 192.168.1.1'. After doing this, see my last paragraph. You may introduce another problem.

One of the other things that is bothering me is you are using 10.8.0.0/24 for both the tun subnet and the LAN subnet. You probably want these to be different subnets. This is also manifesting itself as two duplicate routes in your routing table for 10.8.0.0/24. Try bumping enp0s29f7u1 to the next subnet, 10.8.1.5/24, and doing the same with your dhcp server.

subnet 10.8.1.0 netmask 255.255.255.0 {
  range 10.8.1.10 10.8.1.15;
  option routers 10.8.1.5;
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Other than that the configuration looks good. There is one more sanity check. Make sure you are not choking your VPN's connection to the internet. You still need a route that takes precedence over 0.0.0.0/0 so that tun doesn't trying to use itself to get to the VPN server. You must have a route in your table that is more specific than 0.0.0.0/0. I believe you already have this route, but it its a common mistake.

xx.xx.xx.xx via 192.168.1.1 dev enp2s0

To verify this, make sure your Rx counters on the tun interface increment after establishing the tunnel.

Solution 2:

This is an answer which I found nowhere, but for another network topology. Posting it in case of someone is searching for this.


HOST3 hosts an openvpn client to a vpn provider.

What I wanted was that any local host could choose its internet access from the 2 possibilities :

  • normally ( through 192.168.0.254 )
  • via the VPN connection ( through 10.81.0.1 )

I had to :

  • add a second IP address (192.168.0.6) to enp2s0 on HOST3 with tinyproxy listening and bound on it.
  • add a second routing table
  • use netfilter SNAT ( or MASQUERADE )
                 INTERNET 
                    |
                   ISP 
                    |
             LOCAL NETWORK 192.168.0.0/24
                    |
+-------------------+---------------------------+
|                   |                           |
ISP                HOST3                      HOST4
ROUTER GATEWAY     enp2s0 192.168.  0.  3     enp2s0 192.168.0.4
192.168.0.254             192.168.  0.  6 
                   tun0    10. 81.  0. 13    
                    |                        
                   VPN GATEWAY 10.81.0.1
............................................................................
ip rules:
0:  from all lookup local 
32765:  from 192.168.0.6 lookup VPN 
32766:  from all lookup main 
32767:  from all lookup default 

table [main]:
default             via 192.168.  0.254     dev enp2s0            metric 200
 10. 81.  0.  0 /16                         dev tun0   scope link metric 100
192.168.  0.  0 /24                         dev enp2s0 scope link metric 200

table [VPN]:
default             via  10. 81.  0.  1     dev tun0              metric 200
192.168.  0.  0 /24                         dev enp2s0 scope link metric 100

[Netfilter:NAT]
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source       destination         
   10   600 SNAT       all  --  *      tun0    192.168.0.6  0.0.0.0/0   to:10.81.0.13

Each host on the ISP local network that wants to use the VPN simply configures the browser to use the proxy at 192.168.0.6.

Packets pathway : HOST --> [email protected] --> tun0 ( routing table [VPN] ) --> SNAT with the VPN local IP address( else the openvpn client drop the packet )