Table of Contents
Switching to systemd-networkd for managing your networking interfaces makes things quite a bit simpler over standard networking scripts or NetworkManager. Aside from being easier to configure, it uses fewer resources on your system, which can be handy for smaller virtual machines or containers.
Managing tunnels between interfaces is also easier with systemd-networkd. This post will show you how to set up a GRE tunnel between two hosts running systemd-networkd.
Getting started #
You’ll need two hosts running a recent version of systemd-networkd. I’d recommend Fedora 22 since it provides very recent versions of systemd which include enhancements to systemd-networkd.
For this example, I’ve built one Rackspace Cloud Server in the DFW datacenter and another in IAD. I’ll connect them both together with a simple GRE tunnel.
Switch to systemd-networkd #
I’ve detailed out this process before but I’ll do it again here. First off, we will need a directory made on both servers to hold systemd-networkd configuration files:
Let’s add a very simple network configuration for our
eth0 interface on both hosts:
# cat /etc/systemd/network/eth0.network [Match] Name=eth0 [Network] Address=x.x.x.x/24 Gateway=x.x.x.x DNS=126.96.36.199 DNS=188.8.131.52
Do this on both servers and be sure to fill in the
Gateway lines with the correct data for your servers. Also, feel free to use something other than Google’s DNS servers if needed.
It’s time to get our services in order so that systemd-networkd will handle our networking after a reboot:
systemctl disable network systemctl disable NetworkManager systemctl enable systemd-networkd systemctl enable systemd-resolved systemctl start systemd-resolved rm -f /etc/resolv.conf ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
Don’t start systemd-networkd yet. Having systemd-networkd and NetworkManager fight over your interfaces can lead to a bad day.
Reboot both hosts and wait for them to come back online.
Configure the GRE tunnel #
A GRE tunnel is a simple way to encapsulate packets between two hosts and send almost any protocol across the tunnel you build. However, it’s not encrypted. (If you’re planning to use this long-term, consider only using encrypted streams across the link or add IPSec on top of the GRE tunnel.)
If we want to route traffic over the GRE tunnel, we will need IP addresses on both sides. I’ll use 192.168.254.0/24 for this example, but you’re free to use any subnet of any size (except /32!) for this network.
We need to tell systemd-networkd about a new network device that it doesn’t know about. We do this with
.netdev files. Create this file on both hosts:
# cat /etc/systemd/network/gre-example.netdev [NetDev] Name=gre-example Kind=gre MTUBytes=1480 [Tunnel] Remote=[public ip of remote server] Local=[public ip of local server]
We’re making a new network device called
gre-example here and we’re telling systemd-networkd about the servers participating in the link. Add this configuration file to both hosts but be sure that your
Remote= line is correct. If you’re writing the configuration file for the first host, then the
Remote= line should have the IP address of your second host. Do the same thing on the second host, but use the IP address of your first host there.
Now that we have a network device, we need to tell systemd-networkd how to configure the IP address on these new GRE tunnels. Let’s make a
.network file for our GRE tunnel.
On the first host:
# cat /etc/systemd/network/gre-example.network [Match] Name=gre-example [Network] Address=192.168.254.1/24
On the second host:
# cat /etc/systemd/network/gre-example.network [Match] Name=gre-example [Network] Address=192.168.254.2/24
Bringing up the tunnel #
Although systemd-networkd knows we have a tunnel configured now, it’s not sure which interface should manage the tunnel. In our case, our public interface (
eth0) is required to be up for this tunnel to function. Go back to your original
eth0.network files and add one line under the
[Network] section for our tunnel:
Restart systemd-networkd on both hosts and check the network interfaces:
# systemctl restart systemd-networkd # networkctl IDX LINK TYPE OPERATIONAL SETUP 1 lo loopback carrier unmanaged 2 eth0 ether routable configured 3 eth1 ether off unmanaged 4 gre0 ipgre off unmanaged 5 gretap0 ether off unmanaged 6 gre-example ipgre routable configured 6 links listed.
Hooray! Our GRE tunnel is up! However, we have a firewall in the way.
Fixing the firewall #
We need to tell the firewall two things: trust the GRE interface and trust the public IP of the other server. Trusting the GRE interface is easy with firewalld — just add this on both hosts:
firewall-cmd --add-interface=gre-example --zone=trusted
Now, we need a rich rule to tell firewalld to trust the public IP of each host. I talked about this last year on the blog. Run this command on both hosts:
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="[IP ADDRESS]" accept'
If you run this on your first host, use the public IP address of your second host in the
firewall-cmd command. Use the first host’s public IP address when you run the command on the second host.
Save your configuration permanently on both hosts:
Try to ping between your servers using the IP addresses we configured on the GRE tunnel and you should get some replies!
Final words #
Remember that GRE tunnels are not encrypted. You can add IPSec over the tunnel or you can ensure that you use encrypted streams across the tunnel at all times (SSL, ssh, etc).