Compare commits

...

2 Commits

5 changed files with 1198 additions and 211 deletions

View File

@ -2,12 +2,64 @@
Wireguard management and monitoring utils. Wireguard management and monitoring utils.
* [`wg_status`.py](https://git.hmp.today/pavel.muhortov/wireguard-management#wg_status-py)
* [`wg-client-management`.sh](https://git.hmp.today/pavel.muhortov/wireguard-management#wg-client-management-sh) * [`wg-client-management`.sh](https://git.hmp.today/pavel.muhortov/wireguard-management#wg-client-management-sh)
* [`wg-connect-handling`.sh](https://git.hmp.today/pavel.muhortov/wireguard-management#wg-connect-handling-sh)
* [`wg-heavy@wg1`.service](https://git.hmp.today/pavel.muhortov/wireguard-management#wg-heavy-wg1-service) * [`wg-heavy@wg1`.service](https://git.hmp.today/pavel.muhortov/wireguard-management#wg-heavy-wg1-service)
____ ____
## `wg_status`.py
**Description:**
> Wireguard server status parser.
**Dependencies:**
>
> * privileged rights
> * [Python 3](https://www.python.org/downloads/) (tested version 3.9.5 on [Debian GNU/Linux 11](http://ftp.debian.org/debian/dists/bullseye/))
> * [requests](https://requests.readthedocs.io/) Python 3 module (tested version 2.31.0)
> * to use peer names instead of their public keys, the existence of a directory with configurations or public keys of peers is required
| PARAMETERS | DESCRIPTION | DEFAULT |
|--------------|------------------------|---------------|
|**[-p, --peers_root]**|root path to peers configs or public keys|`/etc/wireguard/pki`|
|**[-f, --filter]**|client names filter by regex|`.*`|
|**[-g, --geo]**|check client real ip geo location (may be slow)|`None`|
Example usage with Zabbix agent:
```bash
# install dependencies
sudo pip install requests
# download
sudo wget https://git.hmp.today/pavel.muhortov/wireguard-management/raw/branch/master/wg_status.py -O /etc/wireguard/wg_status.py
sudo chmod +x /etc/wireguard/wg_status.py
```
```bash
# edit sudoers
sudo sh -c "echo '
zabbix ALL=(ALL) NOPASSWD:/etc/wireguard/wg_status.py
' > /etc/sudoers.d/zabbix_agentd"
# check permission
sudo -u zabbix sudo /etc/wireguard/wg_status.py
```
```bash
# add UserParameter to Zabbix agent
sudo sh -c "echo '
Timeout=30
AllowRoot=0
UserParameter=discovery.wg, sudo /etc/wireguard/wg_status.py
' >> /etc/zabbix/zabbix_agentd.conf"
sudo systemctl restart zabbix-agent
```
Download [Wireguard_by_Zabbix_agent.yaml](https://git.hmp.today/pavel.muhortov/wireguard-management/raw/branch/master/Wireguard_by_Zabbix_agent.yaml) template
Zabbix Server -> Configuration -> Templates -> Import template
____
## `wg-client-management`.sh ## `wg-client-management`.sh
**Description:** **Description:**

944
Wireguard_by_Zabbix_agent.yaml Executable file
View File

@ -0,0 +1,944 @@
zabbix_export:
version: '6.0'
date: '2023-08-16T11:10:34Z'
groups:
-
uuid: a571c0d144b14fd4a87a9d9b2aa9fcd6
name: Templates/Applications
templates:
-
uuid: c3272861e3ff46e2b3daa302066c53c7
template: 'OpenVPN by Zabbix agent'
name: 'OpenVPN by Zabbix agent'
description: 'OpenVPN by Zabbix agent'
groups:
-
name: Templates/Applications
items:
-
uuid: 51151af0bb704668a1bb3b390cee2039
name: 'OpenVPN stats'
key: discovery.ovpn
history: 14d
trends: '0'
value_type: TEXT
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: raw
-
uuid: 877b2f94cd4645fcaae13543f42d79be
name: 'OpenVPN clients limit'
type: DEPENDENT
key: ovpn.clients.limit
delay: '0'
history: 14d
units: client
preprocessing:
-
type: JSONPATH
parameters:
- $.clients_limit
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN server'
value: 'clients limit'
-
uuid: 00c5526a838e4f7791b4edafc20bb094
name: 'OpenVPN expiration ca'
type: DEPENDENT
key: ovpn.expiration.ca
delay: '0'
history: 14d
units: s
preprocessing:
-
type: JSONPATH
parameters:
- $.ca_expiration
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN server'
value: expiration
triggers:
-
uuid: 34fbc5a346d0458c8e529b92f0aa39c5
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.ca,#1)<86400'
name: 'OpenVPN ca certificate expires in 1 day'
priority: DISASTER
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 016c7d7c40b342c883ff81d0a5817b75
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.ca,#1)<604800'
name: 'OpenVPN ca certificate expires in 7 days'
priority: HIGH
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 2d9f9da08348499ab9b7584a9386abfc
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.ca,#1)<2592000'
name: 'OpenVPN ca certificate expires in 30 days'
priority: AVERAGE
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 65912ffeb36a4b2c8bae996c0b865f69
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.ca,#1)<7776000'
name: 'OpenVPN ca certificate expires in 90 days'
priority: WARNING
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 591d03b0553645788c5b178670cb8bc9
name: 'OpenVPN expiration cert'
type: DEPENDENT
key: ovpn.expiration.cert
delay: '0'
history: 14d
units: s
preprocessing:
-
type: JSONPATH
parameters:
- $.ce_expiration
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN server'
value: expiration
triggers:
-
uuid: 6a2bc06ed9944e95bfdec45af330bd53
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.cert,#1)<86400'
name: 'OpenVPN cert certificate expires in 1 day'
priority: DISASTER
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: da6ae766472541e8addb2712584289c7
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.cert,#1)<604800'
name: 'OpenVPN cert certificate expires in 7 days'
priority: HIGH
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 5571d2aa00a2479889bdd853b37d7160
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.cert,#1)<2592000'
name: 'OpenVPN cert certificate expires in 30 days'
priority: AVERAGE
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 083b3ed043db4d209b093056c04605c3
expression: 'last(/OpenVPN by Zabbix agent/ovpn.expiration.cert,#1)<7776000'
name: 'OpenVPN cert certificate expires in 90 days'
priority: WARNING
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: expiration
-
uuid: 5ba0b1d455444ec8851c4cdda408ed24
name: 'OpenVPN clients count'
type: DEPENDENT
key: ovpn.stats.clients_count
delay: '0'
history: 14d
units: clients
preprocessing:
-
type: JSONPATH
parameters:
- $.clients_count
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: 'clients count'
-
uuid: 731f61d192f944769aaf82c2fb05676b
name: 'OpenVPN clients found'
type: DEPENDENT
key: ovpn.stats.clients_found
delay: '0'
history: 14d
units: clients
preprocessing:
-
type: JSONPATH
parameters:
- $.clients_found
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: 'clients found'
-
uuid: f38e82ba64f14385bd60a1397eda278c
name: 'OpenVPN stats updated'
type: DEPENDENT
key: ovpn.stats.updated
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- $.stats_updated
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN stats'
value: updated
discovery_rules:
-
uuid: f6b3ac3373544c1f820c207234177816
name: 'Discovery openvpn clients'
type: DEPENDENT
key: get.ovpn.stats
delay: '0'
item_prototypes:
-
uuid: fc55509717fc4ee7bef6f684932ee01a
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" bytes recieved'
type: DEPENDENT
key: 'ovpn.client.b_rx.name[{#OVPN_CLIENT_NAME}]'
delay: '0'
history: 14d
units: B
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#OVPN_CLIENT_NAME}")].b_rx.first()'
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN client'
value: '{#OVPN_CLIENT_NAME}'
-
uuid: e75ed01ce6cd45e0822e021f6733b115
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" bytes transmitted'
type: DEPENDENT
key: 'ovpn.client.b_tx.name[{#OVPN_CLIENT_NAME}]'
delay: '0'
history: 14d
units: B
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#OVPN_CLIENT_NAME}")].b_tx.first()'
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN client'
value: '{#OVPN_CLIENT_NAME}'
-
uuid: 332feedbbd314a479ba27d43c7bb7523
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" real ip'
type: DEPENDENT
key: 'ovpn.client.r_ip.name[{#OVPN_CLIENT_NAME}]'
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#OVPN_CLIENT_NAME}")].r_ip.first()'
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN client'
value: '{#OVPN_CLIENT_NAME}'
-
tag: 'OpenVPN stats'
value: 'real ip'
-
uuid: 0dc7671cdc9b47c6a7c06b47a8de25ca
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" connect duration'
type: DEPENDENT
key: 'ovpn.client.t_cd.name[{#OVPN_CLIENT_NAME}]'
delay: '0'
history: 14d
units: s
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#OVPN_CLIENT_NAME}")].t_cd.first()'
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN client'
value: '{#OVPN_CLIENT_NAME}'
-
uuid: 127fd46950194d9ba5325f183cb6e940
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" connect time'
type: DEPENDENT
key: 'ovpn.client.t_cs.name[{#OVPN_CLIENT_NAME}]'
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#OVPN_CLIENT_NAME}")].t_cs.first()'
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN client'
value: '{#OVPN_CLIENT_NAME}'
-
uuid: 2bb9be1dd4a041b09e68f7e9022676d4
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" virtual ip'
type: DEPENDENT
key: 'ovpn.client.v_ip.name[{#OVPN_CLIENT_NAME}]'
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#OVPN_CLIENT_NAME}")].v_ip.first()'
master_item:
key: discovery.ovpn
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN client'
value: '{#OVPN_CLIENT_NAME}'
-
tag: 'OpenVPN stats'
value: 'virtual ip'
graph_prototypes:
-
uuid: 0e740374d0d7435990fba99d19211947
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" connect duration'
show_work_period: 'NO'
show_triggers: 'NO'
graph_items:
-
color: FFBF00
item:
host: 'OpenVPN by Zabbix agent'
key: 'ovpn.client.t_cd.name[{#OVPN_CLIENT_NAME}]'
-
uuid: 48b62a9621c64082919a6e041defc546
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" traffic'
graph_items:
-
drawtype: GRADIENT_LINE
color: 00FF00
item:
host: 'OpenVPN by Zabbix agent'
key: 'ovpn.client.b_rx.name[{#OVPN_CLIENT_NAME}]'
-
sortorder: '1'
drawtype: BOLD_LINE
color: 0080FF
item:
host: 'OpenVPN by Zabbix agent'
key: 'ovpn.client.b_tx.name[{#OVPN_CLIENT_NAME}]'
master_item:
key: discovery.ovpn
lld_macro_paths:
-
lld_macro: '{#OVPN_CLIENT_NAME}'
path: $..name.first()
-
lld_macro: '{#OVPN_CLIENT_R_IP}'
path: $..r_ip.first()
-
lld_macro: '{#OVPN_CLIENT_V_IP}'
path: $..v_ip.first()
-
lld_macro: '{#OVPN_CLIENT_B_RX}'
path: $..b_rx.first()
-
lld_macro: '{#OVPN_CLIENT_B_TX}'
path: $..b_tx.first()
-
lld_macro: '{#OVPN_CLIENT_T_CS}'
path: $..t_cs.first()
-
lld_macro: '{#OVPN_CLIENT_T_CD}'
path: $..t_cd.first()
dashboards:
-
uuid: d25222f632c74c83ac80c8cbce480db0
name: OpenVPN
auto_start: 'NO'
pages:
-
name: Server
widgets:
-
type: ITEM
width: '5'
hide_header: 'YES'
fields:
-
type: ITEM
name: itemid
value:
host: 'OpenVPN by Zabbix agent'
key: ovpn.expiration.ca
-
type: ITEM
x: '6'
width: '5'
hide_header: 'YES'
fields:
-
type: ITEM
name: itemid
value:
host: 'OpenVPN by Zabbix agent'
key: ovpn.expiration.cert
-
type: GRAPH_CLASSIC
'y': '2'
width: '11'
height: '5'
hide_header: 'YES'
fields:
-
type: GRAPH
name: graphid
value:
host: 'OpenVPN by Zabbix agent'
name: 'OpenVPN certificates expiration'
-
name: Clients
widgets:
-
type: ITEM
width: '5'
hide_header: 'YES'
fields:
-
type: ITEM
name: itemid
value:
host: 'OpenVPN by Zabbix agent'
key: ovpn.stats.clients_count
-
type: ITEM
x: '6'
width: '5'
hide_header: 'YES'
fields:
-
type: ITEM
name: itemid
value:
host: 'OpenVPN by Zabbix agent'
key: ovpn.stats.clients_found
-
type: GRAPH_PROTOTYPE
'y': '7'
width: '11'
height: '5'
fields:
-
type: INTEGER
name: columns
value: '1'
-
type: GRAPH_PROTOTYPE
name: graphid
value:
host: 'OpenVPN by Zabbix agent'
name: 'OpenVPN client "{#OVPN_CLIENT_NAME}" traffic'
-
type: GRAPH_CLASSIC
'y': '2'
width: '11'
height: '5'
hide_header: 'YES'
fields:
-
type: GRAPH
name: graphid
value:
host: 'OpenVPN by Zabbix agent'
name: 'OpenVPN clients sum'
-
uuid: 3face906272745a7963b5b4e29eaaadc
template: 'Wireguard by Zabbix agent'
name: 'Wireguard by Zabbix agent'
description: 'Wireguard by Zabbix agent'
groups:
-
name: Templates/Applications
items:
-
uuid: 0c599346296b401cb7eaffa1c78978ed
name: 'Wireguard stats'
key: discovery.wg
history: 14d
trends: '0'
value_type: TEXT
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard stats'
value: raw
-
uuid: 0bbe3c2e64cc4dbd88c6c7722a3f929e
name: 'Wireguard clients count'
type: DEPENDENT
key: wg.stats.clients_count
delay: '0'
history: 14d
units: clients
preprocessing:
-
type: JSONPATH
parameters:
- $.clients_count
master_item:
key: discovery.wg
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard stats'
value: 'clients count'
-
uuid: ee3c34a9ae024592b869f27841e6006f
name: 'Wireguard clients found'
type: DEPENDENT
key: wg.stats.clients_found
delay: '0'
history: 14d
units: clients
preprocessing:
-
type: JSONPATH
parameters:
- $.clients_found
master_item:
key: discovery.wg
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard stats'
value: 'clients found'
-
uuid: 7893f7024c4d45df9ee2774006efe175
name: 'Wireguard stats updated'
type: DEPENDENT
key: wg.stats.updated
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- $.stats_updated
master_item:
key: discovery.wg
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard stats'
value: updated
discovery_rules:
-
uuid: 8b3ade0f42f84419947638024d2b4d13
name: 'Discovery wireguard clients'
type: DEPENDENT
key: get.wg.stats
delay: '0'
item_prototypes:
-
uuid: 5f1215ede2b14a9496ab3e3f6bd3e741
name: 'Wireguard client "{#WG_CLIENT_NAME}" bytes recieved'
type: DEPENDENT
key: 'wg.client.b_rx.name[{#WG_CLIENT_NAME}]'
delay: '0'
history: 14d
units: B
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#WG_CLIENT_NAME}")].b_rx.first()'
master_item:
key: discovery.wg
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard client'
value: '{#WG_CLIENT_NAME}'
-
uuid: 93378d553fd34f9bb99f747024a1a32a
name: 'Wireguard client "{#WG_CLIENT_NAME}" bytes transmitted'
type: DEPENDENT
key: 'wg.client.b_tx.name[{#WG_CLIENT_NAME}]'
delay: '0'
history: 14d
units: B
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#WG_CLIENT_NAME}")].b_tx.first()'
master_item:
key: discovery.wg
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard client'
value: '{#WG_CLIENT_NAME}'
-
uuid: 9a206a744cdb4c8a86ceadc20b2602d4
name: 'Wireguard client "{#WG_CLIENT_NAME}" real ip'
type: DEPENDENT
key: 'wg.client.r_ip.name[{#WG_CLIENT_NAME}]'
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#WG_CLIENT_NAME}")].r_ip.first()'
master_item:
key: discovery.wg
tags:
-
tag: Application
value: OpenVPN
-
tag: 'Wireguard client'
value: '{#WG_CLIENT_NAME}'
-
tag: 'Wireguard stats'
value: 'real ip'
-
uuid: 7a1b854401714952aaa86e4769dcdcfa
name: 'Wireguard client "{#WG_CLIENT_NAME}" latest handshake'
type: DEPENDENT
key: 'wg.client.t_lh.name[{#WG_CLIENT_NAME}]'
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#WG_CLIENT_NAME}")].t_lh.first()'
master_item:
key: discovery.wg
tags:
-
tag: Application
value: Wireguard
-
tag: 'Wireguard client'
value: '{#WG_CLIENT_NAME}'
-
uuid: 257ade43285748baa5e2c826028a411a
name: 'Wireguard client "{#WG_CLIENT_NAME}" virtual ip'
type: DEPENDENT
key: 'wg.client.v_ip.name[{#WG_CLIENT_NAME}]'
delay: '0'
history: 14d
trends: '0'
value_type: TEXT
preprocessing:
-
type: JSONPATH
parameters:
- '$.data.[?(@.name=="{#WG_CLIENT_NAME}")].v_ip.first()'
master_item:
key: discovery.wg
tags:
-
tag: Application
value: OpenVPN
-
tag: 'Wireguard client'
value: '{#WG_CLIENT_NAME}'
-
tag: 'Wireguard stats'
value: 'virtual ip'
graph_prototypes:
-
uuid: aa1bb73c2276432b96c7d0ee3fc4b292
name: 'Wireguard client "{#WG_CLIENT_NAME}" traffic'
graph_items:
-
drawtype: GRADIENT_LINE
color: 00FF00
item:
host: 'Wireguard by Zabbix agent'
key: 'wg.client.b_rx.name[{#WG_CLIENT_NAME}]'
-
sortorder: '1'
drawtype: BOLD_LINE
color: 0080FF
item:
host: 'Wireguard by Zabbix agent'
key: 'wg.client.b_tx.name[{#WG_CLIENT_NAME}]'
master_item:
key: discovery.wg
lld_macro_paths:
-
lld_macro: '{#WG_CLIENT_B_RX}'
path: $..b_rx.first()
-
lld_macro: '{#WG_CLIENT_B_TX}'
path: $..b_tx.first()
-
lld_macro: '{#WG_CLIENT_NAME}'
path: $..name.first()
-
lld_macro: '{#WG_CLIENT_R_IP}'
path: $..r_ip.first()
-
lld_macro: '{#WG_CLIENT_T_LH}'
path: $..t_lh.first()
-
lld_macro: '{#WG_CLIENT_V_IP}'
path: $..v_ip.first()
dashboards:
-
uuid: 282c5db5bd1a4e7a84b856060beafb51
name: Wireguard
auto_start: 'NO'
pages:
-
name: Server
-
name: Clients
widgets:
-
type: ITEM
width: '5'
hide_header: 'YES'
fields:
-
type: ITEM
name: itemid
value:
host: 'Wireguard by Zabbix agent'
key: wg.stats.clients_count
-
type: ITEM
x: '6'
width: '5'
hide_header: 'YES'
fields:
-
type: ITEM
name: itemid
value:
host: 'Wireguard by Zabbix agent'
key: wg.stats.clients_found
-
type: GRAPH_PROTOTYPE
'y': '7'
width: '11'
height: '5'
fields:
-
type: INTEGER
name: columns
value: '1'
-
type: GRAPH_PROTOTYPE
name: graphid
value:
host: 'Wireguard by Zabbix agent'
name: 'Wireguard client "{#WG_CLIENT_NAME}" traffic'
-
type: GRAPH_CLASSIC
'y': '2'
width: '11'
height: '5'
hide_header: 'YES'
fields:
-
type: GRAPH
name: graphid
value:
host: 'Wireguard by Zabbix agent'
name: 'Wireguard clients sum'
triggers:
-
uuid: 022e1211349c48a4be951588cda2dba0
expression: 'max(/OpenVPN by Zabbix agent/ovpn.stats.clients_count,#1)>=max(/OpenVPN by Zabbix agent/ovpn.clients.limit,#1)'
name: 'Maximum number of OpenVPN clients reached'
priority: AVERAGE
tags:
-
tag: Application
value: OpenVPN
-
tag: 'OpenVPN server'
value: 'clients limit'
graphs:
-
uuid: a23bdc304f5d49e1b42597f9cbd4e840
name: 'OpenVPN certificates expiration'
graph_items:
-
drawtype: GRADIENT_LINE
color: FFBF00
item:
host: 'OpenVPN by Zabbix agent'
key: ovpn.expiration.ca
-
sortorder: '1'
drawtype: BOLD_LINE
color: FF8000
item:
host: 'OpenVPN by Zabbix agent'
key: ovpn.expiration.cert
-
uuid: 94d1e1cc40424214a291067790d3db89
name: 'OpenVPN clients sum'
graph_items:
-
color: FF8000
item:
host: 'OpenVPN by Zabbix agent'
key: ovpn.stats.clients_count
-
sortorder: '1'
color: FFBF00
item:
host: 'OpenVPN by Zabbix agent'
key: ovpn.stats.clients_found
-
uuid: 644326c90dac454a94b6b98136d1efaf
name: 'Wireguard clients sum'
graph_items:
-
color: BF00FF
item:
host: 'Wireguard by Zabbix agent'
key: wg.stats.clients_count
-
sortorder: '1'
color: FFBF00
item:
host: 'Wireguard by Zabbix agent'
key: wg.stats.clients_found

View File

@ -113,11 +113,14 @@ createcert() {
wg genkey | tee "/etc/wireguard/pki/${clientname}-private.key" | wg pubkey > "/etc/wireguard/pki/${clientname}-public.key" wg genkey | tee "/etc/wireguard/pki/${clientname}-private.key" | wg pubkey > "/etc/wireguard/pki/${clientname}-public.key"
clientpublkey=$(cat "/etc/wireguard/pki/${clientname}-public.key") clientpublkey=$(cat "/etc/wireguard/pki/${clientname}-public.key")
clientprivkey=$(cat "/etc/wireguard/pki/${clientname}-private.key") clientprivkey=$(cat "/etc/wireguard/pki/${clientname}-private.key")
wg set wg0 peer "${clientpublkey}" allowed-ips "${clientaddr}/32" wg set wg0 peer "${clientpublkey}" \
allowed-ips "${clientaddr}/32" \
persistent-keepalive 5
{ {
echo -e "[Peer]" echo -e "[Peer]"
echo -e " PublicKey = ${clientpublkey}" echo -e " PublicKey = ${clientpublkey}"
echo -e " AllowedIPs = ${clientaddr}/32" echo -e " AllowedIPs = ${clientaddr}/32"
echo -e " PersistentKeepalive = 5"
} >> ${servercfgname} } >> ${servercfgname}
ip -4 route add "${clientaddr}/32" dev wg0 ip -4 route add "${clientaddr}/32" dev wg0
} }
@ -173,10 +176,15 @@ deletecert() {
wg set wg0 peer "${clientpublkey}" remove wg set wg0 peer "${clientpublkey}" remove
rm -f "/etc/wireguard/pki/${clientname}-public.key" rm -f "/etc/wireguard/pki/${clientname}-public.key"
rm -f "/etc/wireguard/pki/${clientname}-private.key" rm -f "/etc/wireguard/pki/${clientname}-private.key"
# PublicKey =
s2=$(grep -n "${clientpublkey}" ${servercfgname} | cut -d":" -f1) s2=$(grep -n "${clientpublkey}" ${servercfgname} | cut -d":" -f1)
# [Peer]
s1=$(( s2 - 1 )) s1=$(( s2 - 1 ))
# AllowedIPs =
s3=$(( s2 + 1 )) s3=$(( s2 + 1 ))
sed -i "${s1}d;${s2}d;${s3}d" ${servercfgname} # PersistentKeepalive =
s4=$(( s2 + 2 ))
sed -i "${s1}d;${s2}d;${s3}d;${s4}d" ${servercfgname}
ip -4 route del "${clientaddr}/32" dev wg0 ip -4 route del "${clientaddr}/32" dev wg0
} }

View File

@ -1,208 +0,0 @@
#!/usr/bin/env bash
# DESCRIPTION:
# handling client connection
# and
# preparing stats for monitoring
#
# DEPENDENCIES:
# - privileged rights
# - jq
# - grepcidr
# - Python 3
# - existing /usr/local/bin/sendmail.py
#
# PARAMETERS:
# 1: root path for counter, names, log
# 2: "mail" - send email notification
# 3: "geo" - check client address geolocation
#
# FUNCTIONS:
#
#######################################
# Print message and add to log.
# Globals:
# logs
# Arguments:
# 1: message to print and logging
#######################################
addtologs() {
echo "$(date +'%Y.%m.%d-%H:%M:%S') $1" | tee -a "${logs}"
}
#######################################
# Exit procedure.
# Globals:
# show
# Arguments:
# None
#######################################
execquite() {
addtologs "execution time is $(($(date +%s)-time)) seconds, exit"
exit
}
#######################################
# Error exit procedure
# Globals:
# None
# Arguments:
# 1: message to print and logging
#######################################
execerror() {
addtologs "error: $1"
execquite
}
#######################################
# Checking user rights.
# Globals:
# None
# Arguments:
# None
# return:
# 0 - if privileged rights, 1 - if not privileged rights
#######################################
checkroot() {
if [ "${EUID}" -ne 0 ]; then
return 1 # false
else
return 0 # true
fi
}
#######################################
# Get information about client address
# Globals:
# flaggeol
# show_from_addr
# conf_client_nm
# Arguments:
# None
#######################################
# shellcheck disable=SC2154
expandaddress() {
ipinfo="Source address is ${show_from_addr}"
localnetworks="10.0.0.0/8
100.64.0.0/10
127.0.0.1/8
172.16.0.0/12
192.168.0.0/16
"
if ! grepcidr "${localnetworks}" <(echo "${show_from_addr}") >/dev/null; then
if [ "${flaggeol}" == "geo" ]; then
ipinfo=$(curl "https://api.ipbase.com/v1/json/${show_from_addr}")
if [ "$(jq -r '.country_name' <<< "$ipinfo")" != "" ]; then
z=$(jq -r '.zip_code' <<< "$ipinfo")
c=$(jq -r '.country_name' <<< "$ipinfo")
r=$(jq -r '.region_name' <<< "$ipinfo")
t=$(jq -r '.city' <<< "$ipinfo")
ipinfo="Source address ${show_from_addr} is from ${z}, ${c}, ${r}, ${t}"
fi
fi
fi
addtologs "client ${conf_client_nm} checked. ${ipinfo}"
}
#######################################
# Send email notification about client connect
# Globals:
# ipinfo
# conf_client_nm
# conf_ipaddress
# Arguments:
# None
#######################################
startsendmail() {
subj="[VPN Connected] $(cat /etc/hostname): ${conf_client_nm} connect to ${conf_ipaddress}"
(
python3 /usr/local/bin/sendmail.py \
-u "$(grep "from=" /usr/local/bin/sendmail.config | cut -d= -f2)" \
-p "$(grep "pass=" /usr/local/bin/sendmail.config | cut -d= -f2)" \
-d "$(grep "dest=" /usr/local/bin/sendmail.config | cut -d= -f2)" \
--smtp "$(grep "smtp=" /usr/local/bin/sendmail.config | cut -d= -f2)" \
--port "$(grep "port=" /usr/local/bin/sendmail.config | cut -d= -f2)" \
--stls "True" \
--subj "${subj}" \
--text "${ipinfo}" \
>> /dev/null 2>&1 &
)
addtologs "sent mail with subject '${subj}'"
}
#
# VARIABLES:
#
pathroot=$1
flagmail=$2
flaggeol=$3
time=$(date +%s)
logs="${pathroot}/$(basename -s .sh "$0").log"
counts_file="${pathroot}/wg-counts.log"
counts_temp=$(cat "${counts_file}")
if [ -z "${pathroot}" ]; then
logs=/dev/null
execerror "Usage example: $0 '/var/log/wireguard' '-' '-'"
elif [ ! -e "${logs}" ]; then
touch "${logs}"
fi
if ! command -v curl &> /dev/null || \
! command -v /usr/local/bin/sendmail.py &> /dev/null || \
! command -v python3 &> /dev/null || \
! command -v grepcidr &> /dev/null || \
! command -v jq &> /dev/null; then
execerror "Not found dependencies"
fi
#
# MAIN:
#
if checkroot; then
allowed_cfg=$(find /etc/wireguard/ -name "*.conf" | grep -v "wg0.conf")
counter_now=0
clients_now=""
while read -r file; do
conf_keepalive=$(grep "PersistentKeepalive" "${file}" |cut -d"=" -f2 |tr -d " ")
conf_ipaddress=$(grep "Address" "${file}" |cut -d"=" -f2 |cut -d"/" -f1 |tr -d " ")
conf_client_nm=$(basename -s .conf "${file}")
show_handshake=$(wg show all dump |grep "${conf_ipaddress}" |cut -f6)
show_from_addr=$(wg show all dump |grep "${conf_ipaddress}" |cut -f4 |cut -d":" -f1)
if [ "${show_handshake}" -ne 0 ]; then
calc_handshake="$(date -d "-${conf_keepalive} min" +"%s")"
if [ "${show_handshake}" -ge "${calc_handshake}" ]; then
(( counter_now ++))
connect_status="connected"
if ping -q -c 1 -W 1 "${conf_ipaddress}" > /dev/null; then
connect_status="connected, ping responded"
else
connect_status="connected, ping loss"
fi
clients_now+=$(printf "%s\n\r" "${conf_client_nm}_${conf_ipaddress}")
if ! grep -q "${conf_client_nm}_${conf_ipaddress}" <<< "${counts_temp}"; then
addtologs "client ${conf_client_nm} ${connect_status}"
expandaddress
if [ "${flagmail}" == "mail" ]; then
startsendmail
fi
fi
else
connect_status="disconnected"
if grep -q "${conf_client_nm}_${conf_ipaddress}" <<< "${counts_temp}"; then
addtologs "client ${conf_client_nm} ${connect_status}"
fi
fi
else
connect_status="never connected"
fi
done <<< "$allowed_cfg"
printf "%s\n" "total=${counter_now}=" > "${counts_file}"
printf "%s\n" "${clients_now}" >> "${counts_file}"
else
execerror "Restart this as root!"
fi
execquite

191
wg_status.py Executable file
View File

@ -0,0 +1,191 @@
#!/usr/bin/env python3
# pylint: disable=W0612
"""It's the Wireguard server status parser.
"""
import json
import re
import time
from argparse import ArgumentParser
from os import path, walk
from subprocess import Popen, PIPE, STDOUT
import requests
def status(configs_root: str, client_filter: str = '.*', client_geo: bool = False) -> dict:
"""Wireguard server's peers status parser.
Args:
configs_root (str): root path to peers configs.
client_filter (str, optional): client names filter by regex. Defaults to '.*'.
client_geo (bool, optional): check client real ip geo location. Defaults to False.
Returns:
dict: {
'stats_updated': timestamp,
'clients_count': int,
'clients_found': int,
'data': [
{
"name": str,
"r_ip": str,
"r_cc": str,
"v_ip": str,
"b_rx": int,
"b_tx": int,
"t_lh": timestamp,
},
]
}
"""
clients_dump = wg_dmp()
clients_array = []
clients_count = len(clients_dump)
clients_found = 0
stats_updated = time.strftime("%Y-%m-%d %H:%M:%S")
if clients_count > 0:
configs_dump = []
for root, dirs, files in walk(configs_root, topdown=False):
for file_name in files:
file_path = path.join(path.realpath(root), file_name)
with open(file_path, mode='r', encoding='utf-8') as file:
try:
file_data = file.read()
configs_dump.append(
{
'file_name': file_name,
'file_path': file_path,
'file_data': file_data
}
)
except UnicodeDecodeError:
pass
for client in clients_dump:
client_name = client['name']
for config in configs_dump:
if client_name in config['file_data'] and not client['w_if'] in config['file_name']:
client_name = config['file_name'].replace('.key', '').replace('.conf', '')
break
if re.findall(client_filter, client_name) or re.findall(client_filter, client['name']):
reject_after_time = 180
client_dl = int(time.mktime(time.strptime(stats_updated, "%Y-%m-%d %H:%M:%S")))
if client['p_lh'] + reject_after_time >= client_dl:
client_r_ip = client['r_ip']
client_r_cc = '--'
if client_geo and re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', client_r_ip):
client_r_cc = ip_geo(addr=client_r_ip)
client_t_lh = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(client['p_lh']))
clients_array.append(
{
'name': client_name,
'r_ip': client_r_ip,
'r_cc': client_r_cc,
'v_ip': client['v_ip'],
'b_rx': client['b_rx'],
'b_tx': client['b_tx'],
't_lh': client_t_lh
}
)
clients_found += 1
clients_stats = {
'stats_updated': stats_updated,
'clients_count': clients_count,
'clients_found': clients_found,
'data': clients_array,
}
return clients_stats
def wg_dmp() -> list:
"""Parse 'wg show all dump' result.
Returns:
list: [
{
"name": str,
"r_ip": str,
"v_ip": str,
"b_rx": int,
"b_tx": int,
"p_lh": int,
"i_ka": int,
"w_if": str
},
]
"""
process = ['wg', 'show', 'all', 'dump']
with Popen(process, stdout=PIPE, stderr=STDOUT) as proc:
dlm = '\t'
dump_text = proc.stdout.read().decode('utf-8')
peer_list = []
for dump_line in dump_text.splitlines():
line_list = dump_line.split(dlm)
w_if = line_list[0]
if len(line_list) == 5:
pass
if len(line_list) == 9:
peer_list.append(
{
"name": line_list[1],
"r_ip": line_list[3].split(':')[0],
"v_ip": line_list[4],
"b_rx": int(line_list[6]),
"b_tx": int(line_list[7]),
"p_lh": int(line_list[5]),
"i_ka": int(line_list[8]),
"w_if": w_if
}
)
return peer_list
def ip_geo(addr: str) -> str:
"""Get ip address geo location.
Args:
addr (str): ip address.
Returns:
str: country code.
"""
try:
request = 'https://geolocation-db.com/json/' + addr
response = requests.get(request, timeout=5)
result = json.loads(response.content.decode())
return result['country_code']
except requests.exceptions.RequestException:
return '--'
if __name__ == "__main__":
args = ArgumentParser(
prog='wg_status',
description='Wireguard server status parser',
epilog='Dependencies: '
'- Python 3 (tested version 3.9.5), '
'- Python 3 modules: requests '
)
args.add_argument('-p', '--peers_root', type=str, default='/etc/wireguard/pki', required=False,
help='root path to peers configs or public keys')
args.add_argument('-f', '--filter', type=str, default='.*', required=False,
help='client names filter by regex')
args.add_argument('-g', '--geo', action='store_true', required=False,
help='check client real ip geo location (may be slow)')
args = vars(args.parse_args())
json_data = status(
configs_root=args['peers_root'],
client_filter=args['filter'],
client_geo=args['geo']
)
print(json.dumps(json_data, indent=2))