Using Wireguard, DigitalOcean and firewalld to give your roaming computer a static IP

"Have fun storming the castle"

While we’re waiting to figure out where in Ireland we’ll be living long-term, we’re currently using mobile broadband. I’d like to be able to ssh into my home network from outside, but when I looked into setting up DDNS, I found that I don’t even have a public IP address. My mobile dongle says that its IP address is in the 10.0.0.0/8 range, so there’s no way to direct traffic to it from the internet.

After my first foray in using wireguard, I figured it should be a good fit to give myself ssh access to the home network. I could have just forwarded a specific port to my home network, but I prefer not to have to deal with non-standard ports. And, as this site is hosted on DigitalOcean, the natural next step was to see if I could pull it off with them.

It took a couple of hours (mainly dealing with firewalld as I’m much more comfortable with iptables), but I got there in the end, and I can now ssh into my home network (using key-based authentication, of course).

This guide will walk you through the process, step by step. It assumes you have a DigitalOcean droplet running, that you’re using Fedora on both the roaming computer and the DigitalOcean droplet, and that you have firewalld on both.

Step 1 - Give your droplet a Floating IP

  1. Log into DigitalOcean
  2. Go to Networking, Floating IPs
  3. Select the droplet you want to use as your gateway and click Assign Floating IP:
  4. Check to see what address you got. This will be your new static IP address

Do note that the floating IP will not appear when you run ip addr in your droplet, but there will be a local IP (most likely in the 10.16.0.0/16 range) that all the floating IP’s traffic will be forwarded to.

Step 2 - Setup wireguard between DigitalOcean and your roaming computer

On both the DigitalOcean droplet and your roaming computer, install wireguard. I want to quickly note that it’s not available from the official Fedora repositories because the kernel module hasn’t been merged into the mainline kernel yet. It has just become available in the RPM Fusion Free testing repositories. This guide assumes you’ve already configured the RPM Fusion Free repository on your system.

$ sudo dnf --enablerepo=rpmfusion-free-updates-testing install wireguard

Now, it’s time to set wireguard up on the DigitalOcean droplet.

  1. We’ll use the wg-quick service to set everything up, so put the following in /etc/wireguard/wgnet0.conf:

     [Interface]
     Address = 192.168.32.1/24
     SaveConfig = true
     ListenPort = 51820
     PrivateKey = 
    
     [Peer]
     PublicKey = 
     PresharedKey = 
     AllowedIPs = 192.168.32.0/24
    
  1. Generate a private key and insert it into the line that says PrivateKey:

     $ wg genkey
    
  1. Generate a pre-shared key (which should protect your VPN from the omnipresent quantum computers that are undoubtedly listening in) and insert it into the line that says PresharedKey:

     $ wg genpsk
    
  1. Figure out the public key from the private key you generated in step 2:

     $ echo {private key} | wg pubkey
    

Now for the roaming computer. Because the roaming computer initiates the connection to the DigitalOcean droplet, we need to setup a keepalive so traffic that starts at the droplet (which is the whole point of this exercise) will get back to the roaming computer in 10 seconds max if the link is completely idle.

  1. Put the following in /etc/wireguard/wgnet0.conf, substituting your droplet’s hostname or public IP (but not the floating IP) for www.example.com:

     [Interface]
     Address = 192.168.32.2/24
     PrivateKey = 
    
     [Peer]
     PublicKey = 
     PresharedKey = 
     AllowedIPs = 192.168.32.0/24
     Endpoint = www.example.com:51820
     PersistentKeepalive = 10
    
  1. Insert the public key we extracted in step 4 of the droplet configuration into the line that says PublicKey

  2. Insert the pre-shared key generated in step 3 of the droplet configuration into the line that says PresharedKey

  3. Generate a private key and insert it into the line that says PrivateKey:

     $ wg genkey
    
  1. Now, extract the public key from the private key you just generated, go back to the droplet and insert it into the line that says PublicKey:

     $ echo {private key} | wg pubkey
    

At this point, you should have two configuration files with everything filled in.

Go back to the DigitalOcean droplet now and get the service running.

  1. First open the service port in the firewall:

     $ sudo firewall-cmd --add-port=51820/udp --permanent
     $ sudo firewall-cmd --reload
    
  1. Enable and start the service

     $ sudo systemctl enable wg-quick@wgnet0.service
     $ sudo systemctl start wg-quick@wgnet0.service
    

Assuming you haven’t hit any errors, you should now have wireguard running on your droplet

On your roaming computer, get the service running.

  1. Enable and start the service

     $ sudo systemctl enable wg-quick@wgnet0.service
     $ sudo systemctl start wg-quick@wgnet0.service
    

Test the service by pinging 192.168.32.1 from your roaming computer and 192.168.32.2 from your DigitalOcean droplet. Assuming both work, congratulations, you’ve now setup a VPN between your two systems!

Step 3 - Forward ports from the roaming IP to your roaming computer

So now you have a floating IP on your DigitalOcean droplet and a VPN between the droplet and your roaming computer, so the final step is to put them together.

This process would be easier if DigitalOcean used different interfaces for the public IP and the floating IP, but they don’t, so we have to use firewalld’s rich rules to make this work.

First, figure out which ports you want to open up. We’ll just open the ssh port in this example.

On the droplet, do the following steps:

  1. Verify that you can ssh into the roaming computer:

     $ ssh user@192.168.32.2
    

    If this step fails, you’ve made a mistake in your ssh configuration, and fixing it is beyond the scope of this guide.

  2. Figure out the private address that traffic to the floating IP is coming to:

     $ ip addr show eth0
    

    Look for the line that begins with inet 10.x.x.x. 10.x.x.x is the IP address you’re looking for. On my system it’s 10.16.0.5, so that’s what I’m going to use for the rest of the example.

  3. Turn on masquerading for any traffic going over the VPN:

     $ sudo firewall-cmd --add-rich-rule "rule family=ipv4 destination address=192.168.32.2/32 masquerade" --permanent
    
  1. Forward the ports from the floating IP to the VPN, making sure to substitute the IP address you found in step 2 for 10.16.0.5:

     $ sudo firewall-cmd --add-rich-rule "rule family=ipv4 destination address=10.16.0.5/32 forward-port port=22 protocol=tcp to-port=22 to-addr=192.168.32.2" --permanent
    
  1. Repeat step four for any other ports you want open.

  2. Reload the firewall rules:

     $ sudo firewall-cmd --reload
    

VoilĂ ! When you ssh into your floating IP, it should be forwarded to your roaming computer, while your droplet is still accessible on its public IP.

Security notice: you do not want to allow root to ssh into your system using a password. That’s just begging for someone to guess the password and get root access on your roaming computer. Setup SSH keys, and, at the minimum, make sure that root can only log in with an SSH key

One of the benefits of wireguard is that the client (in this case, the roaming computer) will automatically reconnect as it moves from network to network, so your roaming computer will automatically be available at the floating IP no matter where it is as long as it’s on the Internet.

Do note that DigitalOcean doesn’t seem to allow you to connect more than one floating IP to a droplet at a time, so you’ll be limited to one forwarded IP per droplet.

Enjoy your new static IP. If you run into any problems, please leave a message in the comments below.

Flock 2018

Dresden

Last week, I had the opportunity to be at Flock, Fedora’s contributer conference, in Dresden. As I was preparing to leave for Flock, I seriously wondered whether it was going to be worth it, given that I’ve just moved countries and am still in the process of getting settled in and of job-searching. But as I got on the plane after it was over, I knew that it was definitely worth it! This year was, by far, the best Flock I’ve been too. There were a number of great talks, but the thing I appreciated the most was the sense of community evident at the conference.

Over the last few months, I’ve been working on getting Fedora’s metadata zchunked, so this was a great chance to meet with Igor Gnatenko and Neal Gompa, who have both been helping me. I was also able to talk with some of the DNF and Fedora Infrastructure guys, and got a lot of good feedback. A huge thank you to everyone who listened (sometimes unwillingly, I’m sure) to me talk about zchunk! (And kudos to Randy Barlow and Jeremy Cline who are thinking about doing a zchunk implementation in Rust!)

Talks

I made it to quite a number of talks, but there were three that really stood out to me.

The power of one: For the good of the community - Rebecca Fernandez

This was a great talk, mainly because it focuses on the soft skills that we geeks can sometimes be very weak on. She talked about how important it is to speak up, especially when someone is being offensive in the community and gave great ideas on how to speak up in a way that moves the conversation forward rather than increasing drama. She didn’t give us any magic wands that will supernaturally change people’s behavior, but, as a teacher who’s been stuck mediating many a student dispute, I think her methods are far more effective than most realize.

I’d love to be able to point to a video of her talk, but it doesn’t look like it’s online yet. Here’s the video:

Ansible

I made it to a couple of the ansible talks, and they were quite fascinating. We’ve been using ansible in the school for workstation deployment for a few years now, but the talks quickly made it clear how little I actually know about ansible.

The first revelation was that you can use templates for configuration files, something that I had never caught onto. You can create a template for foo.conf, set a {{ variable }} in the template, and then watch as the the variable is replaced in the deployed file. This is the kind of thing that makes deployment so much easier.

We’ve been using roles for our ansible playbooks since the beginning, but my second revelation was that you could change the default task that runs in a role. When running a role, normally the default task is main.yaml, but, by setting the tasks_from: attribute in include_role, you can change that to any task you want. This allows us to specify different sets of tasks within a role, so we can just run the correct set when including the role.

The final revelation is that ansible allows you to create plugins that run on the controller for various purposes. These plugins can be used for purposes that range from writing a custom connection method for connecting to your hosts, to creating a custom strategy for running ansible on the hosts, to loading external data into your playbooks. This allows you to extend ansible far beyond its normal limitations.

The beauty of ansible is that you don’t have to be an expert to create functional playbooks, but it’s nice to see ways that I could make our playbooks more efficient.

Modularity

My last post deals with my experience building a module for Fedora, so I’m not going to spend much time discussing it, but I do have a lot of hope for where modularity could take us, especially as it relates to server packaging.

For those who want to try my LizardFS development module, on F28 server or Rawhide, run the following:

# dnf --enablerepo=updates-testing-modular module enable lizardfs:devel
# dnf --enablerepo=updates-testing-modular list "lizardfs*"

You’ll see and be able to install the 3.13.0 release candidate packages rather than the default 3.12 packages. To go back to 3.12, just run:

# dnf --enablerepo=updates-testing-modular module disable lizardfs:devel
# dnf --enablerepo=updates-testing-modular distro-sync "lizardfs*"

Once the LizardFS module has been in updates-testing-modular for a week, I’ll push it to stable and you’ll be able to remove “–enablerepo=updates-testing-modular” from your commands.

Lightning talks

I also gave a lightning talk explaining how zchunk works, and got to hear a lot of quick interesting things that people are working on. Luka described a new project called ignition that’s meant to be an interpreter-free replacement for cloud-init, Praveen shared about building a Fedora minishift ISO, Florian made an interesting proposal to remove the changelog from the spec file and automatically generate it from git, and Adam S. spoke about using Fedora containers in MacOS. Adam’s proposal is to try to make Fedora the default choice when a developer wants to use containers on MacOS, which could greatly expand the userbase.

Evening events

There were a few evening events, but the two that stuck out were the Dresden treasure hunt and the Roller Coaster Restaurant. For the treasure hunt, we were placed in teams of seven or eight and sent around the city center, filling in a “treasure” map. I was lucky enough to be on a team that included Matej, who was in charge of AV at Flock and is quite competitive, along with a couple of guys from Dresden. With Matej pushing us forward and the local guys acting as guides, we were the first team finished (though we came in second overall due to missing bonus tasks).

The second memorable event was the dinner organized at the Roller Coaster Restaurant. I was mildly concerned that we would be expected to eat on a roller coaster, but it turns out that the food is sent on a roller coaster to you. My first thought was, “What could possibly go wrong?” The answer, as it turns out, is that a beer bottle might just fall from five meters up, you might have flaming sparklers dropping sparks on your head, and your food might get stuck. Other than that, though… In all seriousness, it was a fun place to hang out at, and I got the opportunity to chat with Igor a bit and then with Zbigniew for quite a while. Definitely made up for the slight risk of having a bottle dropped on your head or being lit on fire.

Summary

I feel like this year’s Flock was the best that I’ve been to yet. I got the opportunity to get to know a number of the people that I normally only see on IRC or the mailing lists. Putting faces to names and getting a feel for personalities is important, so I’m really glad that I was able to make it again this year! I would strongly recommend that anyone who wants to be part of the Fedora community makes a point of being there if at all possible. A huge thank you to everyone involved in putting Flock together!

Updated 2018-09-03 to include YouTube link to Rebecca Fernandez’ talk