Send wireguard client info to HA with mqtt + template sensor to show active clients

Hello everyone and Merry Christmas.
About half a year ago I posted a simple way on how to show piVPN client info on HA. @woodmj74 has made an excellent script for that matter, so be sure to check out the thread if you’re still using piVPN.

However, I recently bought an Edge Router X so I decided to run Wireguard directly on the router.
Once again, I wanted to send my client’s info to home assistant, so here’s a very simple way to do this.

If you run the sudo wg command on your router’s terminal you will get a long list with all your clients and their activity (remote IP, last seen, data usage etc).
In order to send this data over to HA, use the following scipt and edit accordingly.

## Replace 'peer_id' with your actual peer id, eg. 6bUWCstPx52ufh=138fsf234efd ##
## Replace mqtt_ip, mqtt_user, mqtt_pass and mqtt_topic ##

#!/bin/bash

ip=$(sudo wg | grep -A 4 'peer_id' | grep 'endpoint' | sed s'/endpoint://' | sed -e 's/^[[:space:]]*//')
lastseen=$(sudo wg | grep -A 4 'peer_id' | grep 'latest' | sed s'/latest handshake://' | sed -e 's/^[[:space:]]*//')
data=$(sudo wg | grep -A 4 'peer_id' | grep 'transfer' | sed s'/transfer://' | sed -e 's/^[[:space:]]*//')

final='{"Client":"your_client_name","IP":"'"$ip"'","Last Seen":"'"$lastseen"'","Data":"'"$data"'"}'

mosquitto_pub -h mqtt_ip -u "mqtt_user" -P "mqtt_pass" -t mqtt_topic -m "$final" -r

Save the file as something.sh and run it with crontab at your desired schedule.

Create an mqtt sensor on your configuration.yaml or sensor.yaml with the following:

- platform: mqtt
  name: ## your desired sensor name ###
  state_topic: ## the mqtt_topic you specified earlier ##
  icon: mdi:vpn
  json_attributes_topic:  ## the mqtt_topic you specified earlier ##
  value_template: "{{ value_json.Client }}"

Finally, you will have something like this:
wg

Now, regarding the template binary_sensor that shows if a client is currently active.
The sudo wg command provides info on when the client was last seen in the format shown in the picture above. (eg. 3 seconds ago, 2 days 4 hours 6 minutes ago etc.)

In order to translate this to something useful, i’ve created a template binary_sensor that checks for words such as days, hours, minutes, seconds etc. And determines if a client was last seen in the previous 3 minutes, thus making this client active.
Maybe there is a better more efficient way, but this works for me, so here it is…

In your configuration.yaml or binary_sensor.yaml add a new template binary_sensor and remember to edit accordingly:

- platform: template
  sensors:   
    vpn_alexlaptop:
        friendly_name: "Alex Laptop VPN Active"                 
        value_template: >
                    {% if state_attr('sensor.vpn_alex_laptop','Last Seen') != '' %}
                        {% if 'day' in state_attr('sensor.vpn_alex_laptop','Last Seen') or 'days' in state_attr('sensor.vpn_alex_laptop','Last Seen') or 'hour' in state_attr('sensor.vpn_alex_laptop','Last Seen') or 'hours' in state_attr('sensor.vpn_alex_laptop','Last Seen') %}
                        False
                        {% elif 'minute' in state_attr('sensor.vpn_alex_laptop','Last Seen') or 'minutes' in state_attr('sensor.vpn_alex_laptop','Last Seen') %} 
                            {% if (state_attr('sensor.vpn_alex_laptop','Last Seen').replace("ago","").replace('minutes','').replace('minute','').replace('seconds','').replace('second','').split(',')[0].strip() | int) < 3 %}
                                True
                            {% else %}
                                False
                            {% endif %}
                        {% else %}
                        True
                        {% endif %}
                    {% else %}
                    False
                    {% endif %} 

binary

11 Likes

Can this be made to work with the Wireguard add-on for HA?

1 Like

I’m using a similar approach for the add on

3 Likes

Thanks for the link. I am using this in a slightly changed version:

...

sensor:
- platform: rest
    name: WireGuard peers status API
    resource: http://a0d7b954-wireguard
    value_template: "OK"
    json_attributes:
      - peer00
      - peer01
...

template:
  - binary_sensor:
      - name: WireGuard Peer peer00
        state: "{{ state_attr('sensor.wireguard_peers_status_api', 'peer00').latest_handshake > as_timestamp(now()) - 180 }}"
      - name: WireGuard Peer peer01
        state: "{{ state_attr('sensor.wireguard_peers_status_api', 'peer01').latest_handshake > as_timestamp(now()) - 180 }}"

(Edit: Had used the endpoint attribute checked against "(none)" before, but this apparently never resets…)

1 Like

Thank you for sharing this. I was able to get it up and running with a cronjob every minute to update binary sensor.

I am unable to see any of my data or allowed ips (i added this part in using your script). But both the data and allowed ips return empty in home assistant.

Below is my .sh being run by cron

#!/bin/bash
ip=$(sudo wg | grep -A 4 'Key' | grep 'endpoint' | sed s'/endpoint://' | sed -e 's/^[[:space:]]*//')
virtualip=$(sudo wg | grep -A 4 'Key' | grep 'virtualip' | sed s'/allowed ips://' | sed -e 's/^[[:space:]]*//')
lastseen=$(sudo wg | grep -A 4 'Key' | grep 'latest' | sed s'/latest handshake://' | sed -e 's/^[[:space:]]*//')
data=$(sudo wg | grep -A 4 'Key' | grep 'transfer' | sed s'/transfer://' | sed -e 's/^[[:space:]]*//')

final='{"Client":"Client-S21","IP":"'"$ip"'","Virtual IP":"'"$virtualip"'","Last Seen":"'"$lastseen"'","Data":"'"$data"'"}'

mosquitto_pub -h 192.168.0.111 -u "user" -P "pass" -t wgs21 -m "$final" -r

Below is what I get in home assistant

I am able to see all the stats in my machine with the command wg

Can the @valvex or anyone help me figure out whats going on?

Just wanted to say thanks very much for this. I made a modification to the script to allow multiple peers. Wireguard CLI to MQTT Bash Script - For getting Wireguard information in to Home Assistant MQTT sensors · GitHub

1 Like

I run Wireguard on a Windows computer. Has anyone figured out how to monitor the WG status of Windows machines?

The solution presented here does not query your client, but the Wireguard server. Therefore, it does not matter which client OS you use.

(If you are running a Wireguard server on Windows, sorry, then what I said is not true)

However, I am still struggling with the solution.