How to Monitor Who’s Connected to Your WireGuard VPN

A WireGuard VPN (Virtual Private Network) is really easy to set up, thanks to WireGuard making the right cryptographic choices by default, and its overall simplicity and elegance of design. This simplicity makes it really hard to monitor, however — there’s no log file you can tail to watch who’s connecting to your VPN, and no audit trail you can check to see where and when critical changes have been made.

Fortunately, there are some tools out there that can help you keep tabs on who’s been accessing your WireGuard VPN, and alert you of any suspicious activity. Here’s a survey of your options:

SSH

The simplest thing you can do is just SSH into each of the WireGuard hosts on your network, and use WireGuard’s built-in status display to check the current status of each interface and peer. This might be feasible if you have just a few primary VPN servers through which your endpoints connect (rather than a mesh of endpoints connected point-to-point).

If you SSH into a host running WireGuard, you can get a nice command-line display of each WireGuard interface that’s active on the host, as well as a list of each peer configured for the interface, via the wg command:

$ sudo wg show
interface: wg1
  public key: /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
  private key: (hidden)
  listening port: 51821

peer: fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
  endpoint: 172.19.0.8:51822
  allowed ips: 10.0.0.2/32
  latest handshake: 1 minute, 22 seconds ago
  transfer: 3.48 MiB received, 33.46 MiB sent

peer: jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw=
  endpoint: 172.19.0.7:51823
  allowed ips: 10.0.0.3/32
  latest handshake: 2 hours, 3 minutes, 34 seconds ago
  transfer: 1.40 MiB received, 19.46 MiB sent

Note that wg, wg show, and wg show all produce the same output. You can also get an automatically-updating version of this if you run it with the watch command, like so (updating every 2 seconds by default):

$ sudo watch wg show
interface: wg1
  public key: /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
  ...

Each peer listed will include the public key used by the peer, as well as four other fields:

endpoint

Current public IP address (and UDP port) used by the peer. This is updated from the originally-configured value of the peer whenever the local interface receives a new packet from the peer with a different source address (or port).

allowed ips

IP addresses the local WireGuard interface will route to the peer.

latest handshake

If the local interface has successfully connected to the remote peer since the interface was started, this indicates the last time the connection was re-keyed. The re-keying “handshake” occurs every 2-3 minutes when the connection is actively used (and only when used), so it gives you a good approximation of the last time the connection was active. This field will be omitted if the interface hasn’t successfully connected to the peer since the interface was started.

transfer

If the local interface has attempted to connect to the remote peer since the interface was started, this indicates how much data was received from and sent to the peer. This field will be omitted if the interface hasn’t attempted to connect to the peer since the interface was started.

The obvious downsides to using this as your sole monitoring tool is that you have to keep an SSH session open to each host you want to monitor, and you can only see what’s happening right now (or the last time each peer was active) — and not what happened at the specific times you may want to investigate or analyze.

Pros

  • Free

  • Probably already have everything you need installed

Cons

  • No history

  • No audit trail

  • Not scalable to many hosts

  • Need a pair of eyes on it constantly

  • Frequent SSH access to your VPN servers is a bad security practice

Run a Web Server

Another option (especially if you only have a few hosts you want to monitor) is to run a web application on each WireGuard host you want to monitor. There are several open-source applications that you can download and run that will provide a nice, friendly GUI (Graphical User Interface) to display the status of WireGuard on the host on which it’s running, giving you a web-based analogue to the command-line wg tool.

While several previously popular GUIs, such as wg-dashboard, are no longer actively maintained, one nifty project that still is active is Wg Gen Web. In addition to allowing you to configure a WireGuard interface and its peers via web UI, Wg Gen Web also provides a status page that shows the current status of the VPN connections to that interface:

Wg Gen Web Screenshot
Figure 1. Wg Gen Web status page

Wg Gen Web is implemented with a Golang HTTP server as its “backend”, and a Vue.js web UI for its “frontend”; both parts are served by the “backend” HTTP server. It also relies on a second Golang HTTP server (from the WG-API project) to expose status data from the host.

The simplest way to use this would be to run a couple of Docker containers on each WireGuard host you want to monitor (one Docker container for the main HTTP server, and one for the status server). The Wg Gen Web project’s README includes an example docker-compose.yml file to demonstrate how to do this:

version: '2.0'
services:
  wg-gen-web:
    image: vx3r/wg-gen-web:latest
    container_name: wg-gen-web
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - WG_CONF_DIR=/data
      - WG_INTERFACE_NAME=wg0.conf
      - SMTP_HOST=smtp.gmail.com
      - SMTP_PORT=587
      - SMTP_USERNAME=example@gmail.com
      - SMTP_PASSWORD=****************
      - SMTP_FROM=Example <example@gmail.com>
      - OAUTH2_PROVIDER_NAME=github
      - OAUTH2_PROVIDER=https://github.com
      - OAUTH2_CLIENT_ID=******************
      - OAUTH2_CLIENT_SECRET=******************
      - OAUTH2_REDIRECT_URL=https://wg-gen-web.example.com
      - WG_STATS_API=$BRIDGE_GATEWAY_ADDRESS:8182
    volumes:
      - /etc/wireguard:/data
  wg-api:
    image: james/wg-api:latest
    container_name: wg-json-api
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    network_mode: "host"
    command: wg-api --device=wg0 --listen=$BRIDGE_GATEWAY_ADDRESS:8182

With those Docker containers up and running, you could then open up a web browser and access the Wg Gen Web status page at http://10.0.0.1:8080/status (if the IP address of the host is 10.0.0.1).

Obviously, you’d want to lock down access to this status page pretty thoroughly. And for a lot of people, running a pair of extra web servers on a VPN peer would be a two too many web servers.

Also, like with using the command-line wg tool, this status display includes only the current state of a single host, with no information from past activity available (and no information about peers not connected to this one particular host).

Pros

  • Free

  • Friendly UI

Cons

  • No history

  • No audit trail

  • Not scalable to many hosts

  • Need a pair of eyes on it constantly

  • Running a web server on your VPN servers is a bad security practice

Build Your Own Analytics

A more sophisticated approach, and more useful if your VPN includes a number of peers, would be to build yourself a tool that periodically checks the status of each WireGuard peer, and ships that info off to a centralized location. At this centralized location, which ideally would be your existing logging, analytics, or SIEM (Security Information and Event Management) system, you’d process this status information into a chain of audit records, dashboards showing trends and significant events, and alerts for issues you need your analysts to look at and respond to.

To start off, you’d need to write a client program to run on each host that you want to monitor, periodically checking the status of the WireGuard interface(s) on that host. The wg show all dump command provides a simple way to get the same status info as provided by the regular wg command, but in tab-delimited format:

$ sudo wg show all dump
wg1	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=	/TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=	51821	off
wg1	fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=	(none)	172.19.0.8:51822	10.0.0.2/32	1617235493	3481633	33460136	off
wg1	jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw=	(none)	172.19.0.7:51823	10.0.0.3/32	1609974495	1403752	19462368	off

There’s also a wg-json script in the wireguard-tools repository that will convert the output of this command into JSON (JavaScript Object Notation):

$ sudo wireguard-tools/contrib/json/wg-json
{
   "wg1": {
      "privateKey": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=",
      "publicKey": "/TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=",
      "listenPort": 51821,
      "peers": {
         "fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=": {
            "endpoint": "172.19.0.8:51822",
            "latestHandshake": 1617235493,
            "transferRx": 3481633,
            "transferTx": 33460136,
            "allowedIps": [
               "10.0.0.2/32"
            ]
         },
         "jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw=": {
            "endpoint": "172.19.0.7:51823",
            "latestHandshake": 1609974495,
            "transferRx": 1403752,
            "transferTx": 19462368,
            "allowedIps": [
               "10.0.0.3/32"
            ]
         }
      }
   }
}

Logging/analytics/SIEM systems are usually pretty good at ingesting tab-separated values or JSON, so you’d probably have your client program ship the output of one of the above commands to your system every so often (every two minutes aligns nicely with the re-keying “handshake” of the WireGuard protocol). You’d set up a pipeline in your logging/analytics/SIEM system to marshal this output into structured records tracked by the system. Once those records start coming in, you’d use your logging/analytics/SIEM system’s tools to start building reports, dashboards, and alerts based on that data.

That would be the start of a powerful solution — but it would take a lot of resources, domain knowledge, and coordination to implement.

Pros

  • Can capture history

  • Can build an audit trail

  • Can deploy to multiple servers and endpoints

  • Fully automated

  • Integrated into your existing analytics or SIEM systems

Cons

  • Very costly to build (developer time, project management, testing, etc)

  • Need WireGuard domain expertise

  • Ongoing maintenance costs

  • Ongoing data transit and storage costs

Pro Custodibus

Fortunately, there’s an easy way to do this. Pro Custodibus offers a service that’s simple to set up (as simple as SSHing into a host and running a few commands), provides you with lots of pretty dashboards (with charts and graphs and integrated searching through the full history of all your WireGuard peers), but with all the functionality and scalability of a custom analytics solution.

With Pro Custodibus, you only have to run a few simple commands on a host to install an agent (or have your configuration-management tool do it automatically), and the agent will periodically ping the Pro Custodibus servers with status data from the host. The agent only ever initiates outbound connections, so you never have to worry about securing any additional inbound access to your servers or endpoints.

You can view the full audit trail of all WireGuard activity and configuration changes from all your hosts, on demand, through the Pro Custodibus web app (hosted in Pro Custodibus’ secure cloud datacenters):

Endpoint Screenshot
Figure 2. The full history of an example WireGuard endpoint

Plus you get lots of other dashboards and alerts, tuned to show you critical information about your network, like which hosts and peers have been active, and from where:

Dashboard Screenshot
Figure 3. Overall history of activity on an example WireGuard VPN

This rich monitoring data allows you to finally answer important questions about how your VPN is being used, like:

  • When was the last time Alice accessed our database cluster? (check the timestamps on the activity log of her peer’s page)

  • Who downloaded a bunch of files from our secure file share over the weekend? (check the charts on the file-share peer’s page to see which peers connected to it and received lots of data over the weekend)

  • Have the VPN credentials on Bob’s laptop been stolen and illicitly used? (check the change log on his peer’s page for IP addresses other than his home or corporate offices)

Pros

  • Full history

  • Full audit trail

  • Easy to install on servers and endpoints

  • Fully automated

  • Friendly UI

  • Can integrate into your existing analytics or SIEM systems

  • Built-in smart alerting

  • Designed with WireGuard expertise, tuned for WireGuard best practices

Cons