plugins/inputs: New input for Wireguard server (#6367)

This commit is contained in:
Kevin Lin 2020-03-09 15:34:43 -07:00 committed by GitHub
parent 318a963a89
commit d35290ac7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 338 additions and 1 deletions

View File

@ -321,6 +321,7 @@ For documentation on the latest development code see the [documentation index][d
* [rollbar](./plugins/inputs/webhooks/rollbar)
* [win_perf_counters](./plugins/inputs/win_perf_counters) (windows performance counters)
* [win_services](./plugins/inputs/win_services)
* [wireguard](./plugins/inputs/wireguard)
* [wireless](./plugins/inputs/wireless)
* [x509_cert](./plugins/inputs/x509_cert)
* [zfs](./plugins/inputs/zfs)

View File

@ -4647,6 +4647,13 @@
# # timeout = "1s"
# # Collect Wireguard server interface and peer statistics
# [[inputs.wireguard]]
# ## Optional list of Wireguard device/interface names to query.
# ## If omitted, all Wireguard interfaces are queried.
# # devices = ["wg0"]
# # Monitor wifi signal strength and quality
# [[inputs.wireless]]
# ## Sets 'proc' directory path

3
go.mod
View File

@ -51,7 +51,7 @@ require (
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 // indirect
github.com/golang/protobuf v1.3.2
github.com/google/go-cmp v0.3.0
github.com/google/go-cmp v0.4.0
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.0.0 // indirect
github.com/gorilla/mux v1.6.2
@ -122,6 +122,7 @@ require (
golang.org/x/net v0.0.0-20200202094626-16171245cfb2
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200205215550-e35592f146e4
gonum.org/v1/gonum v0.6.2 // indirect
google.golang.org/api v0.3.1
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107

31
go.sum
View File

@ -186,6 +186,9 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
@ -258,6 +261,9 @@ github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw=
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@ -300,8 +306,16 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/apcupsd v0.0.0-20190314144147-eb3dd99a75fe h1:yMrL+YorbzaBpj/h3BbLMP+qeslPZYMbzcpHFBNy1Yk=
github.com/mdlayher/apcupsd v0.0.0-20190314144147-eb3dd99a75fe/go.mod h1:y3mw3VG+t0m20OMqpG8RQqw8cDXvShVb+L8Z8FEnebw=
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
github.com/mdlayher/netlink v1.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg=
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
@ -451,8 +465,11 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -476,8 +493,11 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -498,11 +518,16 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -522,6 +547,12 @@ golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard v0.0.20200121 h1:vcswa5Q6f+sylDfjqyrVNNrjsFUUbPsgAQTBCAg/Qf8=
golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200205215550-e35592f146e4 h1:KTi97NIQGgSMaN0v/oxniJV0MEzfzmrDUOAWxombQVc=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200205215550-e35592f146e4/go.mod h1:UdS9frhv65KTfwxME1xE8+rHYoFpbm36gOud1GhBe9c=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.6.2 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q=
gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=

View File

@ -170,6 +170,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/webhooks"
_ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters"
_ "github.com/influxdata/telegraf/plugins/inputs/win_services"
_ "github.com/influxdata/telegraf/plugins/inputs/wireguard"
_ "github.com/influxdata/telegraf/plugins/inputs/wireless"
_ "github.com/influxdata/telegraf/plugins/inputs/x509_cert"
_ "github.com/influxdata/telegraf/plugins/inputs/zfs"

View File

@ -0,0 +1,73 @@
# Wireguard Input Plugin
The Wireguard input plugin collects statistics on the local Wireguard server
using the [`wgctrl`](https://github.com/WireGuard/wgctrl-go) library. It
reports gauge metrics for Wireguard interface device(s) and its peers.
### Configuration
```toml
# Collect Wireguard server interface and peer statistics
[[inputs.wireguard]]
## Optional list of Wireguard device/interface names to query.
## If omitted, all Wireguard interfaces are queried.
# devices = ["wg0"]
```
### Metrics
- `wireguard_device`
- tags:
- `name` (interface device name, e.g. `wg0`)
- `type` (Wireguard tunnel type, e.g. `linux_kernel` or `userspace`)
- fields:
- `listen_port` (int, UDP port on which the interface is listening)
- `firewall_mark` (int, device's current firewall mark)
- `peers` (int, number of peers associated with the device)
- `wireguard_peer`
- tags:
- `device` (associated interface device name, e.g. `wg0`)
- `public_key` (peer public key, e.g. `NZTRIrv/ClTcQoNAnChEot+WL7OH7uEGQmx8oAN9rWE=`)
- fields:
- `persistent_keepalive_interval_ns` (int, keepalive interval in nanoseconds; 0 if unset)
- `protocol_version` (int, Wireguard protocol version number)
- `allowed_ips` (int, number of allowed IPs for this peer)
- `last_handshake_time_ns` (int, Unix timestamp of the last handshake for this peer in nanoseconds)
- `rx_bytes` (int, number of bytes received from this peer)
- `tx_bytes` (int, number of bytes transmitted to this peer)
### Troubleshooting
#### Error: `operation not permitted`
When the kernelspace implementation of Wireguard is in use (as opposed to its
userspace implementations), Telegraf communicates with the module over netlink.
This requires Telegraf to either run as root, or for the Telegraf binary to
have the `CAP_NET_ADMIN` capability.
To add this capability to the Telegraf binary (to allow this communication under
the default user `telegraf`):
```bash
$ sudo setcap CAP_NET_ADMIN+epi $(which telegraf)
```
N.B.: This capability is a filesystem attribute on the binary itself. The
attribute needs to be re-applied if the Telegraf binary is rotated (e.g.
on installation of new a Telegraf version from the system package manager).
#### Error: `error enumerating Wireguard devices`
This usually happens when the device names specified in config are invalid.
Ensure that `sudo wg show` succeeds, and that the device names in config match
those printed by this command.
### Example Output
```
wireguard_device,host=WGVPN,name=wg0,type=linux_kernel firewall_mark=51820i,listen_port=58216i 1582513589000000000
wireguard_device,host=WGVPN,name=wg0,type=linux_kernel peers=1i 1582513589000000000
wireguard_peer,device=wg0,host=WGVPN,public_key=NZTRIrv/ClTcQoNAnChEot+WL7OH7uEGQmx8oAN9rWE= allowed_ips=2i,persistent_keepalive_interval_ns=60000000000i,protocol_version=1i 1582513589000000000
wireguard_peer,device=wg0,host=WGVPN,public_key=NZTRIrv/ClTcQoNAnChEot+WL7OH7uEGQmx8oAN9rWE= last_handshake_time_ns=1582513584530013376i,rx_bytes=6484i,tx_bytes=13540i 1582513589000000000
```

View File

@ -0,0 +1,139 @@
package wireguard
import (
"fmt"
"log"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
const (
measurementDevice = "wireguard_device"
measurementPeer = "wireguard_peer"
)
var (
deviceTypeNames = map[wgtypes.DeviceType]string{
wgtypes.Unknown: "unknown",
wgtypes.LinuxKernel: "linux_kernel",
wgtypes.Userspace: "userspace",
}
)
// Wireguard is an input that enumerates all Wireguard interfaces/devices on
// the host, and reports gauge metrics for the device itself and its peers.
type Wireguard struct {
Devices []string `toml:"devices"`
client *wgctrl.Client
}
func (wg *Wireguard) Description() string {
return "Collect Wireguard server interface and peer statistics"
}
func (wg *Wireguard) SampleConfig() string {
return `
## Optional list of Wireguard device/interface names to query.
## If omitted, all Wireguard interfaces are queried.
# devices = ["wg0"]
`
}
func (wg *Wireguard) Init() error {
var err error
wg.client, err = wgctrl.New()
return err
}
func (wg *Wireguard) Gather(acc telegraf.Accumulator) error {
devices, err := wg.enumerateDevices()
if err != nil {
return fmt.Errorf("error enumerating Wireguard devices: %v", err)
}
for _, device := range devices {
wg.gatherDeviceMetrics(acc, device)
for _, peer := range device.Peers {
wg.gatherDevicePeerMetrics(acc, device, peer)
}
}
return nil
}
func (wg *Wireguard) enumerateDevices() ([]*wgtypes.Device, error) {
var devices []*wgtypes.Device
// If no device names are specified, defer to the library to enumerate
// all of them
if len(wg.Devices) == 0 {
return wg.client.Devices()
}
// Otherwise, explicitly populate only device names specified in config
for _, name := range wg.Devices {
dev, err := wg.client.Device(name)
if err != nil {
log.Printf("W! [inputs.wireguard] No Wireguard device found with name %s", name)
continue
}
devices = append(devices, dev)
}
return devices, nil
}
func (wg *Wireguard) gatherDeviceMetrics(acc telegraf.Accumulator, device *wgtypes.Device) {
fields := map[string]interface{}{
"listen_port": device.ListenPort,
"firewall_mark": device.FirewallMark,
}
gauges := map[string]interface{}{
"peers": len(device.Peers),
}
tags := map[string]string{
"name": device.Name,
"type": deviceTypeNames[device.Type],
}
acc.AddFields(measurementDevice, fields, tags)
acc.AddGauge(measurementDevice, gauges, tags)
}
func (wg *Wireguard) gatherDevicePeerMetrics(acc telegraf.Accumulator, device *wgtypes.Device, peer wgtypes.Peer) {
fields := map[string]interface{}{
"persistent_keepalive_interval_ns": peer.PersistentKeepaliveInterval.Nanoseconds(),
"protocol_version": peer.ProtocolVersion,
"allowed_ips": len(peer.AllowedIPs),
}
gauges := map[string]interface{}{
"last_handshake_time_ns": peer.LastHandshakeTime.UnixNano(),
"rx_bytes": peer.ReceiveBytes,
"tx_bytes": peer.TransmitBytes,
}
tags := map[string]string{
"device": device.Name,
"public_key": peer.PublicKey.String(),
}
acc.AddFields(measurementPeer, fields, tags)
acc.AddGauge(measurementPeer, gauges, tags)
}
func init() {
inputs.Add("wireguard", func() telegraf.Input {
return &Wireguard{}
})
}

View File

@ -0,0 +1,84 @@
package wireguard
import (
"net"
"testing"
"time"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
func TestWireguard_gatherDeviceMetrics(t *testing.T) {
var acc testutil.Accumulator
wg := &Wireguard{}
device := &wgtypes.Device{
Name: "wg0",
Type: wgtypes.LinuxKernel,
ListenPort: 1,
FirewallMark: 2,
Peers: []wgtypes.Peer{{}, {}},
}
expectFields := map[string]interface{}{
"listen_port": 1,
"firewall_mark": 2,
}
expectGauges := map[string]interface{}{
"peers": 2,
}
expectTags := map[string]string{
"name": "wg0",
"type": "linux_kernel",
}
wg.gatherDeviceMetrics(&acc, device)
assert.Equal(t, 3, acc.NFields())
acc.AssertDoesNotContainMeasurement(t, measurementPeer)
acc.AssertContainsTaggedFields(t, measurementDevice, expectFields, expectTags)
acc.AssertContainsTaggedFields(t, measurementDevice, expectGauges, expectTags)
}
func TestWireguard_gatherDevicePeerMetrics(t *testing.T) {
var acc testutil.Accumulator
pubkey, _ := wgtypes.ParseKey("NZTRIrv/ClTcQoNAnChEot+WL7OH7uEGQmx8oAN9rWE=")
wg := &Wireguard{}
device := &wgtypes.Device{
Name: "wg0",
}
peer := wgtypes.Peer{
PublicKey: pubkey,
PersistentKeepaliveInterval: 1 * time.Minute,
LastHandshakeTime: time.Unix(100, 0),
ReceiveBytes: int64(40),
TransmitBytes: int64(60),
AllowedIPs: []net.IPNet{{}, {}},
ProtocolVersion: 0,
}
expectFields := map[string]interface{}{
"persistent_keepalive_interval_ns": int64(60000000000),
"protocol_version": 0,
"allowed_ips": 2,
}
expectGauges := map[string]interface{}{
"last_handshake_time_ns": int64(100000000000),
"rx_bytes": int64(40),
"tx_bytes": int64(60),
}
expectTags := map[string]string{
"device": "wg0",
"public_key": pubkey.String(),
}
wg.gatherDevicePeerMetrics(&acc, device, peer)
assert.Equal(t, 6, acc.NFields())
acc.AssertDoesNotContainMeasurement(t, measurementDevice)
acc.AssertContainsTaggedFields(t, measurementPeer, expectFields, expectTags)
acc.AssertContainsTaggedFields(t, measurementPeer, expectGauges, expectTags)
}