11

I have a PC with one physical LAN adapter connecting to a VPN server. Is there a way i can setup a (virtual) gateway interface on that same LAN adapter in a way so the other devices on my network can use that as gateway and run their traffic through that and the VPN connection?

Most of my ifconfig:

enp0s21f5 Link encap:Ethernet  HWaddr 4c:cc:6a:d5:94:96  
      inet addr:192.168.1.120  Bcast:192.168.1.255  Mask:255.255.255.0
      inet6 addr: fe80::76e3:9399:187d:fdad/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
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:65536  Metric:1
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
      inet addr:10.11.0.2  P-t-P:10.11.0.2  Mask:255.255.0.0
      inet6 addr: fdda:d0d0:cafe:1197::1000/64 Scope:Global
      inet6 addr: fe80::c9b:2e1b:882:1637/64 Scope:Link
      UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
virbr0    Link encap:Ethernet  HWaddr 00:00:00:00:00:00  
      inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
      UP BROADCAST MULTICAST  MTU:1500  Metric:1

And here routing info:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.11.0.1       0.0.0.0         UG    50     0        0 tun0
0.0.0.0         192.168.1.1     0.0.0.0         UG    100    0        0 enp0s21f5
10.11.0.0       0.0.0.0         255.255.0.0     U     50     0        0 tun0
89.238.176.34   192.168.1.1     255.255.255.255 UGH   100    0        0 enp0s21f5
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 enp0s21f5
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 enp0s21f5
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
5
  • use route add command on the other client machines to include your pc as gateway. on your pc with vpn you will need to accept connections and redirect the incoming connections to the vpn interface.
    – kukulo
    Jun 16, 2017 at 16:52
  • 1
    Thanks @kukulo, It is those two server steps that i do not really know how or the best way to do. Not sure if i need to use iptables something like: {iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT}? And then rerouting something like: {iptables -t nat -A PREROUTING -s 192.168.1.0 -j DNAT --to 10.11.0.1 iptables -t nat -A POSTROUTING -s 192.168.1.0 -d 10.11.0.1 -j MASQUERADE}? Also i have added my routing table above.
    – UbuNoob
    Jun 17, 2017 at 20:21
  • How the rest of client will connect to you? To me, it seems you're trying to make your pc as the router, so you need to enable ip forwarding, but your goal is not clear.
    – fugitive
    Jun 17, 2017 at 20:35
  • You could use something like hostapd, get wifi adapter, and make it as a access point, but still not very reliable solution.
    – fugitive
    Jun 17, 2017 at 20:41
  • Thanks @fugitive, And yes I do want it to act as a router and pass traffic from other pc's(devices) on the same (V)LAN through its VPN connection. With adding a wifi adapter (or an extra rj45 plug) i am pretty sure i could make it work, as i have come across a few how-to's for that while looking to solve this problem, but i would like to do it without adding extra hardware if it is possible. I managed to get a linksys/dd-wrt router to do it once using only one port, but i do not have it anymore, so would like to get it working on my ubuntu pc now.
    – UbuNoob
    Jun 17, 2017 at 20:56

2 Answers 2

7

@fugitive's answer works, even on Ubuntu 19.04 but if you don't need to host an internet connection for your other LAN devices, then you can skip a few steps.

If all devices are connected to your LAN via wifi or wired, you can follow these steps:

  1. Confirm that your PC with the VPN connection can forward packets like a router

    cat /proc/sys/net/ipv4/ip_forward  #(this should return `1`)
    

    If the above returns 0 instead of 1, you need to enable forwarding like this:

    echo '1' >> /proc/sys/net/ipv4/ip_forward`  
    
    • [optional] make it persistent across reboots:

      echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p 
      
  2. get your adapter names to use while setting iptables Use ifconfig or ip link to list adapters on your machine.

    Here's an example from my machine:

    term-prompt$:>  ifconfig -a  enp0s31f6: 
    flags=-28605<UP,BROADCAST,RUNNING,MULTICAST,DYNAMIC>  mtu 1500
            inet 192.168.199.71  netmask 255.255.255.0  broadcast 192.168.199.255
            inet6 fe80::ac93:1176:160:e2cd  prefixlen 64  scopeid 0x20&lt;link>
            ether 04:0e:3c:4d:50:ab  txqueuelen 1000  (Ethernet)
            RX packets 90437  bytes 61674092 (61.6 MB)
            RX errors 0  dropped 20  overruns 0  frame 0
            TX packets 178888  bytes 41623722 (41.6 MB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
            device interrupt 16  memory 0xec300000-ec320000    
    
    enx00e04c680345: flags=28669<UP,BROADCAST,MULTICAST,DYNAMIC> mtu 1500
            ether 00:e0:4c:68:03:45  txqueuelen 1000  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10&lt;host&gt;
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 122658  bytes 19677105 (19.6 MB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 122658  bytes 19677105 (19.6 MB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
            inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
            ether 52:54:00:19:32:b8  txqueuelen 1000  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    virbr1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
            inet 192.168.220.1  netmask 255.255.252.0  broadcast 192.168.223.255
            ether 52:54:00:0a:f9:8a  txqueuelen 1000  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    wlp58s0: flags=-28670<BROADCAST,MULTICAST,DYNAMIC> mtu 1500
            ether 80:45:dd:06:00:22  txqueuelen 1000  (Ethernet)
            RX packets 258636  bytes 148222512 (148.2 MB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 35682  bytes 4577182 (4.5 MB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    help: as you can see, my Ethernet adapter is named enp0s31f6 and my Wi-Fi adapter is named wlp58s0. This means that when I issue the iptables commands on my machine I have to change wlan+ to wlp+ or wlp58s0 for them to be correct. I don't currently have a tun interface in my example output because I'm not connected to any VPNs or tunnels. Tunnel interfaces usually show up with the default naming convention of tun{X} with {X} being an integer from 0 to infinity. So using the tun+ wildcard name in your iptables rules should be fine unless you have more than one VPN/tunnel and a more complex routing scheme.

  3. set iptables to NAT and forward packets received on your local LAN interface and send out of your tun interface (VPN)

    iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
    
    iptables -A FORWARD -i wlan+ -o tun+ -j ACCEPT
    iptables -A FORWARD -o tun+ -j ACCEPT
    iptables -A FORWARD -i tun+ -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    
    iptables -A INPUT -i tun+ -j ACCEPT
    

    note: tun+—used in the netfilter/iptable commands above—is a wildcard match for any adapter named tun followed by a character (e.g. tun0, tun1, tun2, ...). The same goes for wlan+. You'll need to make sure the tun+ and wlan+ entries match what your adapters are named on your machine otherwise the forwarding rules won't be applied to your packets and things won't work as desired. read more Red Hat Enterprise Linux 4: Reference Guide, 18.3.3. iptables Parameter Options for the -i flag option.

  4. on your other device/computer: use the route command to add a route for the VPN subnets and set the gateway to the IP of your computer with the VPN connection (not tun, but the wlan+ or en+ adapter)

    example: if the computer with the VPN connection has a adapter on your local network with an ip of 192.168.0.100, and your VPN accessible network subnet is 10.0.0.0/24. On your other LAN computer that doesn't have the VPN connection, you need to enter a route that uses 192.168.0.100 as the gateway for 10.0.0.0/24.

    On Windows the command would look something like this:

    route add 10.0.0.0 mask 255.255.255.0 192.168.0.100 metric 200 if <interface>
    
2
  • This is an excellent answer, but I find it would gain by pointing out that the netfilter rules established above use wildcards in the interface names. Many people have never been in touch with those, despite their usefulness. Jun 15, 2020 at 8:45
  • Thanks for the advice @0xC0000022L. I've made edits to reflect your suggestions and I'm just awaiting approval.
    – wsmyth
    Apr 7, 2022 at 22:01
3

Solution with wifi adapter and hostapd software:

sudo apt-get install hostapd -y

Configure hostapd

interface=wlan0
ssid=Your_WLAN
hw_mode=g # can be b/g/n
wpa=2
wpa_passphrase=PASS
wpa_key_mgmt=WPA-PSK WPA-EAP WPA-PSK-SHA256 WPA-EAP-SHA256

Edit /etc/network/interfaces

auto wlan0
iface wlan0 inet static
hostapd /etc/hostapd/hostapd.conf
address 192.168.0.1
netmask 255.255.255.0

Because your PC is router you need to enable forwarding to interfaces

  • 1st way echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p # persistent mode
  • 2nd - echo 1 > /proc/sys/net/ip/ipv4/ip_forward

To enable it on the boot and start it: systemctl enable hostapd && systemctl start hostapd

Install dnsmasq as it will be both your dns and dhcp server.

sudo apt install dnsmasq

edit it's conf file: vi /etc/dnsmasq.conf

interface=lo,wlan0
no-dhcp-interface=lo
dhcp-range=192.168.0.2,192.168.0.254,255.255.255.0,12h

Iptables:

iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE

iptables -A FORWARD -i wlan+ -o tun+ -j ACCEPT
iptables -A FORWARD -o tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -m conntrack --ctstate ESTABLISHED,RELATED   -j ACCEPT
iptables -A INPUT -i tun+ -j ACCEPT

Let me know if it works for you.

4
  • I use something similar on my home, but on raspi which is used as a firewall, and old router that is used for wifi. Routers are more reliable for then wifi adapter
    – fugitive
    Jun 17, 2017 at 21:26
  • The iptables rules worked like a charm. I didn't need to install dnsmasq though
    – danidee
    Apr 20, 2019 at 18:39
  • Worked well thanks :) and sorry for the late reply here!
    – UbuNoob
    Jun 29, 2019 at 19:13
  • 1
    iptables -A FORWARD -o tun+ -j ACCEPT is unnecessary, since it's nothing but a more generic version of the iptables -A FORWARD -i wlan+ -o tun+ -j ACCEPT line above it, which is already sufficient in combination with the other listed rules. (You can verify this by checking the byte counters of iptables -L -v -n: rules for which the counter remains 0 despite successful traffic are never applied.)
    – Will
    Jul 7, 2020 at 1:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .