5

I have two home LANs (100km apart) connected to internet via internet provider routers and would like to them connect with wireguard VPN with two single board computers (NanoPi R2S). NanoPi R2S boards already have armbian and wireguard installed.

One of internet connections has static and other dynamic internet IP. Both are entered in dynamic DNS, and now I have the chance to install dynamic DNS client on nanopis, because clients on routers don't work very well. I can expose wireguard computers via NAT virtual servers functionality on both internet routers.

Site A:

  • Static public IP A.A.A.A and name sitea
  • LAN 192.168.0.0/24 with default gateway 192.168.0.1
  • NanoPi eth0 with DHCP reservation 192.168.0.250

Site B:

  • Dynamic public IP B.B.B.B and name siteb
  • LAN 192.168.1.0/24 with default gateway 192.168.1.1
  • NanoPi eth0 with DHCP reservation 192.168.1.250

I thought Site B would establish a connections from dynamic IP site to Site B exposed server port.

Then all computers on Site A (192.168.0.0/24) should have an additional route, which would direct traffic for Site B (192.168.1.0/24) via 192.168.0.250. Similarly, all computers on Site B (192.168.1.0/24) should have a route to direct traffic for Site A (192.168.0.0/24) via 192.168.1.250. Will that work?

What IPs should I assign to wg0 interfaces? 10.0.0.0/24? How would then routes look like? How do I route 10.0.0.0/24 traffic then? Do I need to route it? How should I configure wireguard? I think I don't need exact commands for wireguard. I just need pointers, how the traffic (IPs, routes) should be organized.

With eth0 and wg0, NanoPi R2S would need eth0 for traffic in both ways. Could I easily use another ethernet port on NanoPi (lan0) to increase throughput or to dedicate one port for wireguard and another for LAN? How?

What about devices (phones, laptops), which I move from one site to another and they connect to WiFi/DHCP? I will probably have to enter routes every time, as route in Site A would make a mess on another Site B and vice versa. I know that one of the routers allows entering some static routes, but I need to figure out what they are for.

2
  • 1
    the DHCP part is really a separate question not really about Unix/Linux if youre routers aren't running Unix/Linux (including a shell access). You can configure additional routes with DHCP option 121. See tools.ietf.org/html/rfc3442 . Standard home routers probably don't provide this. Clients (phone...) must also handle it. You might ponder switching the DHCP role to the NanoPis then (if they provide such package).
    – A.B
    Aug 1, 2020 at 18:55
  • 1
    On the same topic the router with static route settings would instead send an ICMP redirect to the correct gateway (the NanoPi) to achieve the same goal, but it's less efficient.
    – A.B
    Aug 1, 2020 at 19:02

2 Answers 2

5

The solution to this is pretty straightforward, however, I have not found any description on internet how to make such site-to-site VPN. Therefore, I decided to post a solution that works for me, here.

Disclaimer: This solution works for IPv4 only. Since one of my ISPs does not provide any IPv6, I did not configure for IPv6. That remains for the future improvement.

IP forwarding

First IP forwarding needs to be enabled, so nanopi will forward traffic from one interface to another. A line

net.ipv4.ip_forward=1

should be present in /etc/sysctl.conf or in some .conf file in /etc/sysctl.d/. Run sysctl -p or service procps reload (depending on linux distribution), or just reboot to make the change effective.

Wireguard

I will not go into the details how to configure wireguard. There are plenty of them on the internet. I will just write some network details used in my case, and point out two atypical configuration changes that I did in /etc/wireguard/wg0.conf. As mentioned in the question there are two sites:

  1. 192.168.0.0/24 with nanopi acting as a wireguard server with wireguard address 10.0.0.1 on wg0 interface.
  2. 192.168.1.0/24 with nanopi acting as a wireguard client with wireguard address 10.0.0.2 on wg0 interface.

Changes in /etc/wireguard/wg0.conf are:

First, an instruction is added to prevent wg-quick to setup its ip rules and routes. A line Table = off is added to [Interface] section:

Table = off

Second, add a route to direct traffic through VPN connection. Again in [Interface] section:

PostUp = ip route add 192.168.1.0/24 via 10.0.0.2 dev wg0
PreDown = ip route del 192.168.1.0/24 via 10.0.0.2 dev wg0

The lines above are from the first site, and tell the kernel to route all traffic for another network (192.168.1.0/24) to the IP connected on another side of VPN (10.0.0.2) via device wg0. On another site IP numbers in configuration are different (192.168.0.0/24, and 10.0.0.1).

Third, the second wireguard computer acting as a wireguard client has an Endpoint defined in the [Peer] section, while the first one, acting as a server, does not. That endpoint is public IP and port, where server nanopi is accessible. On the router, the server nanopi has to be exposed to the internet in order to allow incoming connections. On the site where the server wireguard computer is, the internet router shall have NAT or Port forwarding or something like that. There should be UDP on port, where wireguard connects, forwarded to the IP and port of the wireguard server IP and port. I will not show that here, because every router, has different GUI for setting that up.

Routing & DHCP

Now, when the wireguard connection works, you should be able to access nano pi on another site via VPN. While logged to 192.168.0.250 (10.0.0.1 on wg0) one should be able to ping (or login to) 10.0.0.2, and vice versa. However, other clients on both networks do not have information how to reach there through VPN. They have a default gateway where they forward all the traffic that is not for the local network. Since addresses from the other site are not local, all traffic that should go through VPN goes out to the internet via ISP routers.

One way would be to add custom static route on each device on the network. Some allow that, but many don't. Windows or linux computers have an option to add a route. On android devices that is already a problem. So, other solutions should be found, where one do not need to set a static route on each device.

If ISP router has an option to add custom routes, such a route can be added. I cannot show here how exactly that can be accomplished. In general, all addresses from another site (e.g. 192.168.0.0 with netmask 24 or 255.255.255.0 shall be redirected to 192.168.1.250).

If that is not possible, I would recommend setting up a DHCP server on nanopi and disable DHCP function on ISP router. isc-dhcp-server can be installed on practically all linux distributions, and that server can send proper routing information to all clients on the network, as long as they use DHCP. I will not go into details of DHCP server configuration. Here is an example of /etc/dhcp/dhcpd.conf:

default-lease-time 600;
max-lease-time 7200;

option subnet-mask 255.255.255.0;
option broadcast-address 192.168.0.255;
option routers 192.168.0.1;
option domain-name "localdomain";
option domain-name-servers 192.168.0.250;

option rfc3442-classless-static-routes code 121 = array of integer 8;
option ms-classless-static-routes code 249 = array of integer 8;

option rfc3442-classless-static-routes 24, 192, 168, 1, 192, 168, 0, 250, 0, 192, 168, 0, 1;
option ms-classless-static-routes 24, 192, 168, 1, 192, 168, 0, 250, 0, 192, 168, 0, 1;

subnet 192.168.0.0 netmask 255.255.255.0 {
    range 192.168.0.150 192.168.0.229;

    default-lease-time 86400;
    max-lease-time 172800;
}

host staticip {
    default-lease-time 86400;
    max-lease-time 172800;

    hardware ethernet aa:bb:cc:dd:ee:ff;
    fixed-address 192.168.0.4;
}

Everything in dhcp configuration is pretty standard. DHCP is assigning addresses from 192.168.0.150 to 192.168.0.229. Change that to your preferences.

I should point out the lines option rfc3442... and option ms-classless.... They define options for DHCP to send route information. One is for clients following RFC 3442, and another for Microsoft clients, which use another option. The numbers 24, 192, 168, 1, 192, 168, 0, 250, 0, 192, 168, 0, 1 have the following meaning:

  1. First static route:
    • 24 - netmask size
    • 192, 168, 1 - prefix for the netmask defined above
    • 192, 168, 0, 250 - gateway for the network defined above
  2. Second static route:
    • 0 - netmask size (default gateway)
    • no network since the mask above is 0
    • 192, 168, 0, 1 - gateway for the network defined above

Default route has to be provided here, too, because default route should get ignored on client if this information is received via DHCP.

At the end of dchp config file there is an example how to make a DHCP reservation for clients that will have static IP addresses. Enter you hardware ethernet (MAC) address and desired IP.

Firewalls

Now clients from one network should be able access clients on another network via wireguard VPN, provided firewalls will let the traffic through.

If there is a firewall on your VPN computer (e.g. nanopi) it may not allow traffic to enter. Make firewall rules according to your preferences and security requirements of your environment. You can open each individual port that you need to go through on a VPN computer, or you can open all, if it is in a trusted environment. One way to do that is with using firewall-cmd commands. Here is an example:

# set "trusted" as a default zone
firewall-cmd --set-default-zone=trusted

# see in which zones the interfaces are
firewall-cmd --get-active-zones

# you may have to remove eth0 from the zone where it belongs to (public in this case)
firewall-cmd --permanent --zone=public --remove-interface=eth0
# add eth0 to trusted zone
firewall-cmd --permanent --zone=trusted --add-interface=eth0

# you may have to remove wg0 from the zone where it belongs to (public in this case)
firewall-cmd --permanent --zone=public --remove-interface=wg0
# add wg0 to trusted zone
firewall-cmd --permanent --zone=trusted --add-interface=wg0

# reload the new config
firewall-cmd --reload

Then there are firewalls on each device that may stop the incoming traffic. Typically, Windows firewall allows some connections from "local network" only. Another site is not on local network, so server will block the connections coming through VPN. You have to add another network (e.g. 192.168.1.0/24) for each rule that is blocking a particular connection. For instance, for Windows share you have to change all incoming rules for ports 135-139, and 445 on computer sharing. Similarly, you have to change outgoing rules on a computer accessing the share.

I would certainly recommend some time to fine tune the firewalls instead of just shutting them off.

I hope the instructions are clear enough and will help to setup a site-to-site VPN or at least give an idea how to do it. Some knowledge in networking and administration is required.

5
  • Upvote for the idea of disabling the ISP DHCP and setting it up on the Pi instead. However, I think putting in some static routes on the main router should be easy (once it is fully understood - I am still investigating.).
    – bomben
    Aug 17, 2022 at 16:53
  • @bomben I agree with you, and I would set up a route on a router, if it would have allowed. it. Unfortanetly, my ISP provider is some small local provider with very basic and outdated router. So my only option was to install ISC DHCP. On another site where I have better router, I have used its function to set up a route there. No need for ISCP DHCP on another site.
    – nobody
    Aug 18, 2022 at 18:33
  • Would you mind sharing your route for the router? Did you also have to set a static route for the router on the other side, where the wireguard server is located?
    – bomben
    Aug 19, 2022 at 5:28
  • 1
    There is not much to share. Router/modem on one side allows to enter a routing rule. In that rule it is specified that all traffic for the addresses on the other side of the VPN shall be routed to the local computer establishing a VPN to the other side. On the other side that rule cannot be entered. Therefore, DHCP publishes the route. I had to report a bug to the route manufacturer and wait for a long time until I got it working at least on one side. It does not matter which one is the server. Routing has to be established on both sides.
    – nobody
    Aug 19, 2022 at 11:55
  • Did you enable ipv4.forward on computers establishing VPN? linuxconfig.org/how-to-turn-on-off-ip-forwarding-in-linux
    – nobody
    Aug 19, 2022 at 19:54
1

tl;dr I wrote a script to help generate WireGuard plus systemd configurations.

Wireguard confiuration generators

You could try generating Wireguard site and client configurations using my script jtmoon79/wireguard-site-to-site.sh. The Wireguard Site to Site generator should generate exactly the configurations and commands you need, including Linux System adjustments and systemctl service commands. The systemctl commands configure the systemd daemon to control the Wireguard interfaces and routes as services.

From the usage message:

Generate Wireguard IPv4 VPN site-to-site configuration files and commands.
The user is expected to selectively copy+paste+run the highlighted output.

Usage:

    wireguard-site-to-site.sh OFFSET FQDN_SITE1 SITE1_NET SITE1_DNS FQDN_SITE2 SITE2_NET

For example:

    wireguard-site-to-site.sh 34 "my-site1.this-domain.org" 192.168.1.0/24 192.168.1.1 "my-site2.that-domain.org" 192.168.2.0/24

In your case, run command

./wireguard-site-to-site.sh 12 A.A.A.A 192.168.0.0/24 192.168.0.1 B.B.B.B 192.168.1.0/24

(12 is arbitrary, replace A.A.A.A, B.B.B.B)

The script will output a sample /etc/wireguard/wg12.conf for both Wireguard endpoints. Something like:

# /etc/wireguard/wg12.conf
#
# site-to-site tunnel for
# endpoint A.A.A.A:51012 (Wireguard server) (you are here)
# endpoint B.B.B.B:51012 (Wireguard client)
#
# Manually generated by wireguard-site-to-site.sh on Wed 02 Nov 2022 07:57:55 PM PDT

[Interface]
Address = 10.12.12.1/24
ListenPort = 51012
MTU = 1420
PrivateKey = iMHb+YRCT/3iCIeEIWoGsNje7oMzlBI3akApxm4r718=

PreUp = set -x; sysctl -w net.ipv4.ip_forward=1; ([[ -e /sys/kernel/debug/dynamic_debug/control ]] && (modprobe wireguard && echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control)) || true

PostUp = set -x; iptables -v -t nat -I POSTROUTING 1 -o eth0 -j MASQUERADE -m comment --comment 'wireguard-a-wg12' && iptables -v -I INPUT 1 -i %i -j ACCEPT -m comment --comment 'wireguard-b-wg12' && iptables -v -I FORWARD 1 -i eth0 -o wg12 -j ACCEPT -m comment --comment 'wireguard-c-wg12' && iptables -v -I FORWARD 1 -i %i -o eth0 -j ACCEPT -m comment --comment 'wireguard-d-wg12' && iptables -v -I INPUT 1 -i eth0 -p udp --dport 51012 -j ACCEPT -m comment --comment 'wireguard-e-wg12'

PostDown = set -x; iptables -v -t nat -D POSTROUTING -o eth0 -j MASQUERADE -m comment --comment 'wireguard-a-wg12' && iptables -v -D INPUT -i %i -j ACCEPT -m comment --comment 'wireguard-b-wg12' && iptables -v -D FORWARD -i eth0 -o wg12 -j ACCEPT -m comment --comment 'wireguard-c-wg12' && iptables -v -D FORWARD -i %i -o eth0 -j ACCEPT -m comment --comment 'wireguard-d-wg12' && iptables -v -D INPUT -i eth0 -p udp --dport 51012 -j ACCEPT -m comment --comment 'wireguard-e-wg12'

# B (site 2 client)
[Peer]
PublicKey = yOkGU/rjUZgwViFbhlmEXdAvQvnoZvsCc77ZwZ/7fAo=
PresharedKey = vCHGe3nr2WkD/SVP0H5XhA64F4jzACZ+aJhZmv2QBkE=
AllowedIPs = 10.12.12.0/24
# this network is implied
#AllowedIPs = 192.168.0.0/24
AllowedIPs = 192.168.1.0/24
# unsetting Endpoint treats the peer as a client (and this host as a server)
#Endpoint = B.B.B.B:51012
PersistentKeepalive = 59

# test connection:
#     ping 10.12.12.2

# This WireGuard configuration should create 5 iptables rules.
# To list the rules by line number:
#    iptables --list --line-numbers
#    iptables --list --table nat --line-numbers
# In case of duplicate or bad rules, delete each rule individually. For example:
#    iptables --delete FORWARD 10
#    iptables --delete --table nat POSTROUTING 10
# Rules added by this configuration are denoted by the comment sequence "wireguard".

The script also provides systemctl commands like:

systemctl enable wg-quick@wg12.service
systemctl daemon-reload
systemctl start wg-quick@wg12
systemctl status wg-quick@wg12

What about routes?

As-is, the two Wireguard hosts will know about each other. But other computers will not know there is another network that can be accessed.

So when a computer at Site A, call it A2, wants to access a computer at Site B, say B2, the computer A2 would need route:

  • network 192.168.1.0/24
  • gateway 192.168.0.250

Now when A2 attempts to access B2 at, for example, 192.168.1.3, A2 will give those IP packets to the nearby Wireguard server at 192.168.0.250. That server will send packets through the Wireguard tunnel. Then the peer Wireguard server will forward to B2, 192.168.1.3.

One can manually configure A2 using the appropriate route command. I recommend getting this working first; configure A2 using the route command and ping B2. IIRC, you will also have to configure route on B2 so it knows where to send reply packets to A2.

When the A2 manual setup works, then work on a centralized setup. Most often, route information is pushed from a central server. There are many ways to "push" that IP route. Most often, route information is pushed from the DHCP server of the network.

DHCP server isc-dhcp-server

The Answer from user @nobody explains seting up a DHCP server isc-dhcp-server from scratch.

DHCP server DNSMasq

If are using DNSMasq DHCP server then adding this configuration declaration might do the trick. This is the Site A declaration:

# add route to Site B network 192.168.1.0/24 via Site A wireguard server gateway at 192.168.0.250
# due to odd DNSMasq DHCP behavior, must also distribute the default route 0.0.0.0 (presuming gateway 192.168.0.1) (https://ral-arturo.org/2018/09/12/dhcp-static-route.html)
dhcp-option=121,192.168.1.0/24,192.168.0.250,0.0.0.0/0,192.168.0.1

This is the Site B declaration:

# add route to Site A network 192.168.0.0/24 via Site B wireguard server gateway at 192.168.1.250
# due to odd DNSMasq DHCP behavior, must also distribute the default route 0.0.0.0 (presuming gateway 192.168.1.1) (https://ral-arturo.org/2018/09/12/dhcp-static-route.html)
dhcp-option=121,192.168.0.0/24,192.168.1.250,0.0.0.0/0,192.168.1.1

You must log in to answer this question.

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