Skip to content

Instantly share code, notes, and snippets.

@kafeg
Forked from mehstg/wg_mqtt_exporter.sh
Last active December 3, 2024 23:02
Show Gist options
  • Save kafeg/51689dcad1b175481d7586d36a2b5af8 to your computer and use it in GitHub Desktop.
Save kafeg/51689dcad1b175481d7586d36a2b5af8 to your computer and use it in GitHub Desktop.
Wireguard CLI to MQTT Bash Script - For getting Wireguard information in to Home Assistant MQTT sensors
# A script to pull information from the Wireguard CLI and print
# Based on the original script from here https://gist.github.com/mehstg/466045bbd0316d7be0a196c1a049477e
# Original script publishes to MQTT, but in my case broker unavilable, I call this script via SSH from HomeAssistant
#!/bin/bash
# Function to parse the transfer line and convert units to bytes
parse_transfer_line() {
local line="$1"
# Split the line by spaces and extract the values and units
local received_value=$(echo "$line" | awk '{print $1}')
local received_unit=$(echo "$line" | awk '{print $2}')
local sent_value=$(echo "$line" | awk '{print $3}')
local sent_unit=$(echo "$line" | awk '{print $4}')
# Convert received to bytes
case "$received_unit" in
"GiB")
received_bytes=$(echo "$received_value * 1024 * 1024 * 1024" | bc | awk '{print int($1)}')
;;
"MiB")
received_bytes=$(echo "$received_value * 1024 * 1024" | bc | awk '{print int($1)}')
;;
"TiB")
received_bytes=$(echo "$received_value * 1024 * 1024 * 1024 * 1024" | bc | awk '{print int($1)}')
;;
"KiB")
received_bytes=$(echo "$received_value * 1024" | bc | awk '{print int($1)}')
;;
"B")
received_bytes=$(echo "$received_value" | awk '{print int($1)}')
;;
esac
# Convert sent to bytes
case "$sent_unit" in
"GiB")
sent_bytes=$(echo "$sent_value * 1024 * 1024 * 1024" | bc | awk '{print int($1)}')
;;
"MiB")
sent_bytes=$(echo "$sent_value * 1024 * 1024" | bc | awk '{print int($1)}')
;;
"TiB")
sent_bytes=$(echo "$sent_value * 1024 * 1024 * 1024 * 1024" | bc | awk '{print int($1)}')
;;
"KiB")
sent_bytes=$(echo "$sent_value * 1024" | bc | awk '{print int($1)}')
;;
"B")
sent_bytes=$(echo "$sent_value" | awk '{print int($1)}')
;;
esac
# Print the received and sent bytes
echo "$received_bytes $sent_bytes"
}
while IFS= read -r RESULT
do
IP=$(docker exec amnezia-awg wg | grep -A 5 $RESULT | grep 'endpoint' | sed 's/endpoint://' | sed -e 's/^[[:space:]]*//')
ALLOWED_IPS=$(docker exec amnezia-awg wg | grep -A 5 $RESULT | grep 'allowed ips' | sed 's/allowed ips://' | sed -e 's/^[[:space:]]*//')
LASTSEEN=$(docker exec amnezia-awg wg | grep -A 5 $RESULT | grep 'latest' | sed 's/latest handshake://' | sed -e 's/^[[:space:]]*//')
DATA=$(docker exec amnezia-awg wg | grep -A 5 $RESULT | grep 'transfer' | sed 's/transfer://' | sed -e 's/^[[:space:]]*//')
PEER_ID_CLEAN=$(echo $RESULT | tr -d '+#/=,')
PEER_NAME_CLEAN=$(docker exec amnezia-awg cat /opt/amnezia/awg/clientsTable | grep $RESULT -A 5 | grep clientName | sed -e 's/^[[:space:]]*//' | cut -d" " -f2 | tr -d '"+#/=,')
received_bytes="0"
sent_bytes="0"
DATA_CLEAN=$(echo $DATA | sed 's/received//' | sed 's/sent//' | sed 's/,//' | sed 's/^ *//;s/ *$//')
received_sent=$(parse_transfer_line "$DATA_CLEAN")
received_bytes=$(echo "$received_sent" | awk '{print $1}')
sent_bytes=$(echo "$received_sent" | awk '{print $2}')
FINAL='{"id":"'"$PEER_ID_CLEAN"'","name":"'"$PEER_NAME_CLEAN"'","ip":"'"$IP"'","allowed":"'"$ALLOWED_IPS"'","handshake":"'"$LASTSEEN"'","data":"'"$DATA"'","rx":"'"$received_bytes"'","tx":"'"$sent_bytes"'"}'
echo $FINAL
done < <(docker exec amnezia-awg wg | grep peer | cut -d" " -f2)
# This script must be runned in the HomeAssistant container (for e.g. save it in ./homeassistant/packages/wireguard_mqtt/wireguard_mqtt.sh)
# After the call it will ssh to server, get WireGuard stats and publish it to local MQTT broker
# Please keep in mind you must have set up SSH keys to access servers from Home Assistant + added to known hosts
#!/bin/bash
MQTT_IP="core-mosquitto.local.hass.io"
MQTT_USERNAME="user" # change to yours
MQTT_PASSWORD="pass" # change to yours
# Function to generate a shortened client identifier using first and last characters
shorten_client_id() {
local client_id="$1"
local shortened="${client_id:0:4}-${client_id: -4}"
echo "$shortened"
}
# Function to generate a custom client identifier using the = inserties for better line breaks
insert_hyphens() {
local input="$1"
local output=""
# Use a loop to read 8 characters at a time and append them with a hyphen
while [[ -n "$input" ]]; do
output+="${input:0:8}-"
input="${input:8}"
done
# Remove the trailing hyphen
output="${output%-}"
echo "$output"
}
# Function to detect online status (handshake <= 5 minutes ago)
check_status() {
local handshake="$1"
if [[ -z "$handshake" ]]; then
echo "OFF"
return
fi
# Convert handshake to minutes
local minutes=0
if [[ "$handshake" == *"day"* ]]; then
echo "OFF"
return
elif [[ "$handshake" == *"minute"* ]]; then
minutes=$(echo "$handshake" | awk '{print $1}')
elif [[ "$handshake" == *"second"* ]]; then
minutes=0
fi
if [[ $minutes -lt 5 ]]; then
echo "ON"
else
echo "OFF"
fi
}
# Function to publish MQTT configuration for each entity
publish_mqtt_config() {
topic="$1"
model="$2"
prefix="$3"
client="$4"
short_client_id=$(shorten_client_id "$client")
breaked_client_id=$(insert_hyphens "$client")
ip="$5"
allowed="$6"
handshake="$7"
received="$8"
sent="$9"
data="${10}"
name="${11}"
status=$(check_status "$handshake")
# Publish IP sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/ip/config" -m \
"{
\"name\": \"IP\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.ip }}\",
\"unique_id\": \"${short_client_id}_ip\",
\"icon\": \"mdi:ip\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"],
\"name\": \"${prefix} ${short_client_id}\",
\"manufacturer\": \"WireGuard\",
\"model\": \"$model\"
}
}"
# Publish Allowed IPs sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/allowed/config" -m \
"{
\"name\": \"Allowed IPs\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.allowed }}\",
\"unique_id\": \"${short_client_id}_allowed\",
\"icon\": \"mdi:format-list-bulleted\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Full Client Identifier sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/id/config" -m \
"{
\"name\": \"Uniq Id\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.id }}\",
\"unique_id\": \"${short_client_id}_id\",
\"icon\": \"mdi:identifier\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Last Seen sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/handshake/config" -m \
"{
\"name\": \"Last Handshake\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.handshake }}\",
\"unique_id\": \"${short_client_id}_handshake\",
\"icon\": \"mdi:handshake\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Received sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/rx/config" -m \
"{
\"name\": \"Received\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.rx }}\",
\"unique_id\": \"${short_client_id}_rx\",
\"icon\": \"mdi:call-received\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Sent sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/tx/config" -m \
"{
\"name\": \"Sent\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.tx }}\",
\"unique_id\": \"${short_client_id}_tx\",
\"icon\": \"mdi:call-made\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Data string sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/data/config" -m \
"{
\"name\": \"Data\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.data }}\",
\"unique_id\": \"${short_client_id}_data\",
\"icon\": \"mdi:cable-data\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Name sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/sensor/${prefix}_${short_client_id}/name/config" -m \
"{
\"name\": \"Name\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.name }}\",
\"unique_id\": \"${short_client_id}_name\",
\"icon\": \"mdi:devices\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
# Publish Status sensor configuration
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "homeassistant/binary_sensor/${prefix}_${short_client_id}/status/config" -m \
"{
\"name\": \"Online status\",
\"state_topic\": \"${topic}/${short_client_id}\",
\"value_template\": \"{{ value_json.status }}\",
\"unique_id\": \"${short_client_id}_status\",
\"device\": {
\"identifiers\": [\"${prefix}_${short_client_id}\"]
}
}"
}
publish_mqtt_values() {
topic="$1"
model="$2"
prefix="$3"
client="$4"
short_client_id=$(shorten_client_id "$client")
breaked_client_id=$(insert_hyphens "$client")
ip="$5"
allowed="$6"
handshake="$7"
received="$8"
sent="$9"
data="${10}"
name="${11}"
status=$(check_status "$handshake")
mosquitto_pub -h $MQTT_IP -u $MQTT_USERNAME -P $MQTT_PASSWORD -t "${topic}/${short_client_id}" -m \
"{
\"id\": \"${breaked_client_id:=-}\",
\"ip\": \"${ip:=-}\",
\"allowed\": \"${allowed:=-}\",
\"handshake\": \"${handshake:=-}\",
\"rx\": \"${received:=-}\",
\"tx\": \"${sent:=-}\",
\"data\": \"${data:=-}\",
\"name\": \"${name:=-}\",
\"status\": \"${status:=-}\"
}"
}
# vpn.example.com (auth by SSH keys must be activated)
while IFS= read -r RESULT
do
# first params are important: 'MQTT topic', 'device model' and entities 'prefix'
publish_mqtt_config "wireguard-vpn" "vpn.example.com" "vpn-wg" "$(echo $RESULT | jq .id -r)" "$(echo $RESULT | jq .ip -r)" "$(echo $RESULT | jq .allowed -r)" "$(echo $RESULT | jq .handshake -r)" "$(echo $RESULT | jq .rx -r)" "$(echo $RESULT | jq .tx -r)" "$(echo $RESULT | jq .data -r)" "$(echo $RESULT | jq .name -r)"
sleep 1
publish_mqtt_values "wireguard-vpn" "vpn.example.com" "vpn-wg" "$(echo $RESULT | jq .id -r)" "$(echo $RESULT | jq .ip -r)" "$(echo $RESULT | jq .allowed -r)" "$(echo $RESULT | jq .handshake -r)" "$(echo $RESULT | jq .rx -r)" "$(echo $RESULT | jq .tx -r)" "$(echo $RESULT | jq .data -r)" "$(echo $RESULT | jq .name -r)"
#exit 0
done < <(ssh [email protected] -- /root/wireguard_stats.sh)
# add more servers here if needed...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment