Wireguard on a USG Pro 4

I ran into some issues when trying to configure an OpenVPN tunnel between my Ubiquiti USG Pro 4 and a Debian VPS. I was very disappointed to discover that the version of OpenVPN on the USG only supports TLS 1.0! My issue was the Debian side rejecting that as insecure.

Thankfully, it was fairly painless to get Wireguard configured on the USG Pro 4. I was hesitant to do so at first because I knew every time my USG was updated I would lose the wireguard pacakge. Fortunately that can be resolved by configuring a post-install script. Thanks to ilar.in and calypte.cc and this github gist for the steps on how to do so.

curl -O https://raw.githubusercontent.com/britannic/install-edgeos-packages/master/install-pkgs
sudo install -o root -g root -m 0755 install-pkgs /config/scripts/post-config.d/install-pkgs
  • Add wireguard DEB package to persistent storage that the script will look for:
sudo mkdir -p /config/data/install-packages
cd /config/data/install-packages
curl -fLSs https://github.com/WireGuard/wireguard-vyatta-ubnt/releases/download/1.0.20200729-1/ugw4-v1-v1.0.20200729-v1.0.20200513.deb
  • Generate a public/private keypair for USG use
cd /config/auth
umask 077
wg genkey > wg_private.key
wg pubkey < wg_private.key > wg_public.key
  • Generate config.gateway.json config to use wireguard
    "interfaces": {
 ...
        "wireguard": {
            "wg0": {
                "address": "<IP_OF_USG_ON_WG_CLIENT_SUBNET>",
                "listen-port": "<WG_LISTEN_PORT>",
                "peer": {
                    "<ENDPOINT_CLIENT_PUBLIC_KEY>": {
                        "allowed-ips": "0.0.0.0/0",
                        "endpoint":  "<ENDPOINT_CLIENT_ADDRESS>:<ENDPOINT_CLIENT_PORT>
"
                    }
                },
                "private-key": "/config/auth/priv.key",
                "route-allowed-ips": false
            },
            "wg1": {
                "address": "<IP_OF_USG_ON_WG_SERVER_SUBNET",
                "firewall": {
                    "in": {
                        "name": "LAN_IN"
                    },
                    "local": {
                        "name": "LAN_LOCAL"
                    },
                    "out": {
                        "name": "LAN_OUT"
                    }
                },
                "listen-port": "<USG_WG_SERVER_LISTEN_PORT>",
                "mtu": "1352",
                "peer": {
                    "<PUBLIC_KEY_OF_WG_CONNECTING_CLIENT": {
                        "allowed-ips": "<SUBNETS_ON_REMOTE_HOST>"
                    }
                },
                "private-key": "/config/auth/wg-server.priv",
                "route-allowed-ips": true
            }
        }
    },

I have two different wireguard interfaces configured – wg0 to be a client to another server, and wg1 to be a server accepting other clients (site-to-site VPN.)

If you want to have multiple peers defined on a single wireguard interface, encapsulate the peers with brackets like so:

"peer": [{
						"--pubkey--": {
							"allowed-ips": [
								"172.255.252.2/32"
							],
							"persistent-keepalive": 60
						}
					},
					{
						"--pubkey--": {
							"allowed-ips": [
								"172.255.252.3/32"
							],
							"persistent-keepalive": 60
						}
					}
				],

Test configuration first

Before committing your config.gateway.json code, test it line by line by SSHing into the USG-Pro 4 and entering config mode. Then type out your JSON lines one at a time, with each key being a new argument separated by a space. The first section above would look like this:

configure
edit interfaces
set wireguard wg0 address WIREGUARD_ADDRESS
set wireguard wg0 listen-port WG_LISTEN_PORT
set wireguard wg0 peer ENDPOINT_CLIENT_PUBLIC_KEY allowed-ips 0.0.0.0/0
set wireguard wg0 peer ENDPOINT_CLIENT_PUBLIC_KEY endpoint ENDPOINT_ADDRESS:ENDPOINT_PORT
set wireguard wg0 private-key /config/auth/priv.key
set wireguard wg0 route-allowed-ips false
commit

If the commit works without error, you can then drop out of the configure section and look at your wireguard config:

exit
sudo wg show

If all looks well, then copy your config.gateway.json to your controller and trigger a reprovision.

Verify after provisioning: 

sudo netstat -npl | grep <WIREGUARD_PORT> | grep udp

Troubleshooting

USG not connecting to changed endpoint address

If you change the address of the wireguard endpoint, USG pro will not connect to that new address. You have to delete and re-create the interface (thanks to https://github.com/Lochnair/vyatta-wireguard/issues/72#issuecomment-423840448 for the information)

Fix this by deleting the wireguard interface

admin@Firewall:~$ configure
[edit]
admin@Firewall# delete interfaces wireguard
[edit]
admin@Firewall# commit


Then reprovision by making a small change, force provision, then change back, and force another provision (annoying) or alternatively reboot firewall.

Wireguard shows established but ping doesn’t work

Example error:

From 10.99.13.1 icmp_seq=5 Destination Host Unreachable
ping: sendmsg: Required key not available

To figure out what’s going on, enable logging to kernel buffer (dmesg) Thanks to procustodibus.com for the info.

echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control

With debug on, ping again and check kernel messages (dmesg)

[Tue Dec 21 22:16:12 2021] wireguard: wg0: No peer has allowed IPs matching 10.99.13.2

This showed I didn’t have my access control properly configured. Modify /etc/wireguard/wg0.conf on your client config and make sure your AllowedIPs are properly letting traffic through.

AllowedIPs = 10.99.13.0/24

USG not allowing connections

Clients unable to connect to USG despite having a good config. Double check your firewall rules. I had neglected to create a WAN LOCAL rule allowing UDP packets on my wireguard port. Once that was configured, handshakes completed successfully.

Firewalls can’t ping each other

I had an issue where the firewalls would pass traffic through, but they couldn’t ping each other. The solution was to add the VPN subnet you created to allowed-ips on both sides of the connection.

5 thoughts on “Wireguard on a USG Pro 4”

  1. I am looking for a guide to establish a WireGuard client connection from a USG to a Ionos Ubutnu VPS server where I have installed a wireguard server with the help of a nice script. Your guide sounds like you are using the USG as both a server and client? I am operating at limits of my knowledge and only interested in a USG-as-client solution for the moment. Is there a clear way to show which steps are applicable only to USG-as-client? Thank you, Rob

    1. If you are only interested in client config, then skip the wg1 stanza in config.gateway.json. All the other steps apply. Good luck!

      1. Thank you very much for the reply. I’m hoping this won’t take long to enlighten me. I have downloaded and installed the DEB package. The script seemed okay but when I tried to copy the file to the install-packages, the putty screen filled with junk. Not sure why. I consider that a bit secondary as I can recreate if needed though I would be happy to get that to work too.

        In any case, I continued on with the directions and was able to create a public/private key so I think the installation of Wireguard itself worked.

        However, I’m not clear on (at least) 2 things:
        1) How does the public/private key work when the VPS server I created also issued both of those for the client file. Did I still need to do that step or only when an inbound VPN connection is desired? I am guessing I didn’t as I didn’t have to create new files in order for my computer/phone to connect as clients.
        2) My plan was to use the configure / edit interface method to set up the system, then download the config and try to extract just the relevant elements for the .json file.

        On the VPS server that I created and in the config file that I generated for the USG, it has the following info:
        ——————————-
        [Interface]
        PrivateKey = WFQX………………………..=
        Address = 10.66.66.4/32,fd42:42:42::4/128
        DNS = 94.140.14.14,94.140.15.15

        [Peer]
        PublicKey = njm2P……………….=
        PresharedKey = gE3x2vA……….=
        Endpoint = 198.25x.xx.xx:54xxx
        AllowedIPs = 0.0.0.0/0,::/0
        ———————————————–

        Based on this information, does this look correct for the network commands:

        configure
        edit interfaces
        set wireguard wg0 address 192.168.4.0/24 # local LAN
        set wireguard wg0 listen-port 54xxx
        set wireguard wg0 peer njm2P……………….= allowed-ips 0.0.0.0/0
        set wireguard wg0 peer njm2P……………….= endpoint 198.25x.xx.xx:54xxx
        set wireguard wg0 private-key /config/auth/priv.key
        set wireguard wg0 route-allowed-ips false
        commit

        If the private key required was the one generated by the Wireguard server, then I should update the priv.key file with the private key in the [Interface] section? Or, do I use both the public and public key that I generated on the USW instead only? Does the preshared key get used at all?

        Thank you for taking a look, Rob

  2. I have made some progress. The USG is connected to the Wireguard server. I can now ping the wireguard server (10.66.66.1) from a computer connected to USG (IP 192.168.4.100) but when I do a tracert 8.8.8.8, the traffic doesn’t flow across the VPN.

    I have added 192.168.4.1/24 to the allowed IPs on the Wireguard server.

    I have added the firewall WAN_OUT rule for UDP to port 54xxx.

    I have tried several different static routes. I wanted to do 192.168.4.1/24 nexthop 10.66.66.1 but the Unifi GUI doesn’t allow that. I have tried 10.66.66.0/24 & 10.66.66.1/32 but neither seem to change anything.

    My USG is in load-balance mode and I have seen some entries about that but at this point I’m not sure what to try next.

    If you have an minute, I would appreciate any ideas.

    1. It sounds like you’re mostly there. If you wish for all traffic to route over the wireguard VPN, I believe all you have to do is set
      “route-allowed-ips”: true
      And then for allowed IPs, do 0.0.0.0/0
      “allowed-ips”: “0.0.0.0/0”,

      Hope this helps!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.