creating a VPN as subnet of a LAN… and enjoying it

While I was configuring a VPN one of these days following the excellent wiki at, I realised that there’s another “creative” way to configure it so no iptables’ configuration is needed.

In my particular case I was trying to use routing, and to install OpenVPN not running on the default gateway of my LAN. This ASCII graph from clarifies this configuration:

               (public IP)|                         |
  {INTERNET}=============={     Router              |
                          |                         |
                          |         LAN switch      |
                                       | (
                                       |              +-----------------------+
                                       |              |                       |
                                       |              |        OpenVPN        |  eth0:
                                       +--------------{eth0    server         |  tun0:
                                       |              |                       |
                                       |              |           {tun0}      |
                                       |              +-----------------------+
                              |                    |
                              |  Other LAN clients |
                              |                    |
                              |   |
                              |   (internal net)   |

From now on I would suppose a Debian 7 (Wheezy) or Debian 8 (Jessie) for the OpenVPN server — though this is relevant only at the final list of instructions in this post.

Be aware that this post is for experienced users with networking skills, as connectivity issues that could lead to a reboot of the OpenVPN server (or worst) might occur, and you may be well on your own to understand what the hell happened and solve it. So be cautious, and… you’re warned!

The point with iptables in my case, where I couldn’t modify the routing table on the main router or on each client, is that two different sets of rules where needed: the ones for iptables routing back and forth between tun0 and eth0 (two rules):

    # iptables -I FORWARD -i tun0 -o eth0 \
             -s -d \
             -m conntrack --ctstate NEW -j ACCEPT

    # iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED \
             -j ACCEPT

and another rule to masquerade the traffic from the vpn to the LAN/internet, so packets could be sent and received as if they came from the server where OpenVPN were to be installed:

    # iptables -t nat -I POSTROUTING -o eth0 \
              -s -j MASQUERADE

This latter rule is set on the “nat” table of iptables.

In fact, some guide to set up OpenVPN like this one at can be followed. Nonetheless there’s some “apprehension” surrounding iptables, which in many cases leads to the use of tools like ufw, which I don’t find particularly useful for this case: I would recommend to follow that manual, substituting the part relative to ufw with the three previous iptables ready-to-use commands.

As a side note, I cannot really understand this trend in the linux community that tends to substitute supposedly complicated tools with supposedly easier-to-use ones… that in fact make a heavy and incomprehensible use of the underlaying ones: as is the case with ufw, which creates literally dozens of iptables tables and rules most of which aren’t needed or will never be used… when what we do usually need is just to type two or three commands to make the same job … :-(

ok, let’s continue:

Once that simple OpenVPN is set and correctly running, there’s something funny to note:

What if the OpenVPN IP addresses range could be set inside the IP addresses range of our LAN?

This way…

  • The previous two first iptables rules wouldn’t be needed as communication between IPs in the same LAN is just possible
  • The third rule isn’t needed anymore, as masquerade is simply unneeded for the same previous reason
  • So, no iptables (or btw, ufw or any other) firewall rules are needed

Configuration is so greatly reduced that the question is “is it possible to share the LAN between a VPN and the rest of the hosts?”

Well, the answer in general is “yes”: let’s just split up the network in two: one half for the LAN (for example the lower one) and the other for the VPN.

For a typical (and very reduced) network you would need to allocate more than 127 hosts (half the network) in it for this solution not to be feasible. On a network the number would be 255*255*127 hosts…

There’s no need to modify your DHCP server or router settings to accommodate this partition: you can leave it as it is as far as you don’t allocate more than half the network IP numbers. It is enough to split the network in the VPN configuration, and in fact it is very easy to do so.

So if you already set up a VPN with OpenVPN following previous indications and using iptables, tested it, and everything was ok, and supposing:

  • a LAN
  • router at
  • a previous OpenVPN configuration using network
  • your ssh connection is between IPs in the same LAN, in case you’re not already on the server’s console: this is because at some point the routing table losses the default router (at least in my case with Debian 7 Wheezy, see note below for Debian 8 Jessie) so you’d lost connectivity otherwise — we will have to patch this.

follow these instructions:

  • Stop OpenVPN server:
    # service openvpn stop
  • disable openvpn at boot, so any issues can be solved… with a reboot:
    # update-rc.d openvpn disable
  • Modify /etc/openvpn/server.conf commenting out previous “server” settings:
  • Execute these three commands in batch to split the LAN at the eth0 interface and then to patch the fact that with Debian 7 the default gateway might be lost with this change:
        # ifconfig eth0 netmask
        # ifconfig eth0 broadcast
        # route add default gw dev eth0
  • This is needed to allow the vpn network at tun0 to send and receive ARP packets from the LAN — otherwise there’d be no communication with the LAN or with internet:
    # echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
  • Delete previous iptables rules, as they’re not needed anymore:
        # iptables -D FORWARD -i tun0 -o eth0 \
                 -s -d \
                 -m conntrack --ctstate NEW -j ACCEPT
        # iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED \
                 -j ACCEPT
        # iptables -t nat -D POSTROUTING -o eth0 \
                  -s -j MASQUERADE
  • Start the openvpn again… and check that you can communicate with LAN hosts as well as with internet:
    # service openvpn start


Please, note that with Debian 8 Jessie, there seems to be no need to execute the previous three commands in batch to “split the LAN at the eth0 interface and then patch the default gateway”: and easy way to check this is that the (hopefully unharmful) command:

    # ifconfig eth0 netmask

does not affect the output of

    # netstat -nr

so just check this in your case.

If everything runs ok, you can pack the previous three commands plus the “proxy_arp” command (Wheezy), or just the “proxy_arp” command (Jessie) after the openvpn daemon has been started, so everything is set up when the first client connects.

Now you can re-enable openvpn at boot:

    # update-rc.d openvpn enable


Note that this configuration is extremely useful with application protocols that have the bad habit of inserting the clients IP addresses inside the UDP/TCP packets sent (SIP, for example):

So after a masquerading, a server would receive a packet from the “vpn’ed” client with an IP encapsulation (masqueraded) telling one thing and an UDP/TCP content inside, with a different IP value (the original client’s IP before masquerading). Some SIP servers could block these packets as they do not “come”, in SIP sense, from the LAN as expected (or obliged), so the SIP session would not be established, and so… no (cheap) IP phone call!

Previous configuration avoid this potentially undesirable effects.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s