Wireguardifying crappy work VPN

written by daniel in devops on 28 Jun 2021

I need to connect to a VPN to access our development environments and various tools we use at work. We were given FortiClient as the VPN client, which is utter crap and probably the worst Mac app I’ve ever had the misfortune to use. To give you a picture of how bad it is:

FortClient playing Solitaire with error dialogs :(

Way out of here

I’m a spoiled computer nerd who likes to use software made in this century. What if I connect a remote box to the VPN using this piece of crap, and use Wireguard to connect to the box? Turn on IP forwarding and route traffic from my Laptop to the VPN subnet, like this:

            Tailscale       openfortivpn                   ┌─────┐
          ┌────────────┐   ┌─────────────┐                 │ DNS │
          │            │   │             │                 └─────┘
  ┌───────▼──┐      ┌──▼───▼──┐       ┌──▼──────────┐
  │          │      │         │       │             │
  │  Laptop  │  WG  │   VPS   │ IPsec │  VPN server │    VPN subnet
  │          ◄──────┼─────────┼───────┼─────────────┼──►
  └──────────┘      └─────────┘       └─────────────┘

Since the VPS will remain always connected and Wireguard is a lot more resilient than IPsec when it comes to roaming and reconnecting, this should solve both the disconnects and having to deal with a crappy app. I will still have to SSH in and manually log in with openfortivpn every once in a while, when the connection times out.

Tailscale to the rescue

Wireguard is awesome but takes a bit of work to set up and maintain. Tailscale, however, uses Wireguard internally, is even more awesome and is unbelievably easy to set up. It just works™. Also it’s free for a single account (which you can use for as many devices as you like 20 devices + one subnet route as of June 2021). It works behind all sorts of nasty NATs. Seriously, it’s amazing.

I used a $5 DigitalOcean VPS I have lying around for random purposes like this. I connected both using Tailscale, installed openfortivpn (an open-source CLI alternative to FortClient) and connected.

Tailscale machines screen with arcane-potato (VPS) connected

daniel@macbook $ ssh arcane-potato

# set bash create a new tmux session when SSHing in, so that openfortivpn doesn't terminate when I close the SSH session
daniel@arcane-potato:~$ cat << 'EOF' >> .bashrc
if command -v tmux &> /dev/null && [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ]; then
  exec tmux

# configure openfortivpn
daniel@arcane-potato:~$ cat << EOF > /etc/openfortivpn/config
host =
port = 12345
username = <username>
password = <password>
trusted-cert = 6f6205cddd796c6d58730df9d35f908d6c513690c6e24135dda4f662fc9997b3

daniel@arcane-potato:~$ echo "alias vpn=\"sudo openfortivpn -o \"" >> .bashrc
daniel@arcane-potato:~$ source .bashrc
daniel@arcane-potato:~$ vpn 123456
[sudo] password for daniel:
INFO:   Tunnel is up and running.

VPS is now connected to VPN. Next, I needed to tell Tailscale to forward packets to our VPN subnet. Also, DNS.

Forwarding traffic

I enabled IP forwarding and told Tailscale to add routes to the VPN subnet.

# enable IP forwarding
daniel@arcane-potato:~$ echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
daniel@arcane-potato:~$ echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
daniel@arcane-potato:~$ sudo sysctl -p /etc/sysctl.conf

# tell Tailscale that we have a route to our VPN subnet
daniel@arcane-potato:~$ sudo tailscale up --advertise-routes=

In the Tailscale control panel, arcane-potato now has a badge saying that it advertises routes. Before these routes are applied, they need to be reviewed and approved. Once that was done, I was able to reach services behind the VPN by their IP addresses.

Configuring DNS

To resolve domain names of services behind the VPN, I need to tell my laptop to use the DNS server on our VPN. I did that using Tailscale’s DNS settings panel, which supports split DNS. Split DNS tells Tailscale clients, “to resolve domain names in this domain, use this DNS server”. (If your services don’t all have a second level domain in common, you will have to add your VPN DNS as a global nameserver. In this case, DNS will only work when the VPS is connected to the VPN. You can disable Tailscale DNS in Tailscale > Preferences > Use Tailscale DNS settings without disconnecting when you don’t need it.)

Tailscale split DNS configuration

There’s one less distraction to ruin your flow 🎉