From 86eee2848fb32cbff6acaa4bea97a9f49946906c Mon Sep 17 00:00:00 2001 From: Joshua Powers Date: Fri, 24 Feb 2023 02:46:09 -0700 Subject: [PATCH] feat(inputs.wireguard): Add allowed_peer_cidr field (#12729) --- plugins/inputs/wireguard/README.md | 3 +- plugins/inputs/wireguard/wireguard.go | 9 +++ plugins/inputs/wireguard/wireguard_test.go | 69 +++++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/plugins/inputs/wireguard/README.md b/plugins/inputs/wireguard/README.md index 067393e16..16d23e0ea 100644 --- a/plugins/inputs/wireguard/README.md +++ b/plugins/inputs/wireguard/README.md @@ -45,6 +45,7 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. - `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) + - `allowed_peer_cidr` (string, comma separated list of allowed peer CIDRs) ## Troubleshooting @@ -77,6 +78,6 @@ those printed by this command. ```shell 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= allowed_ips=2i,persistent_keepalive_interval_ns=60000000000i,protocol_version=1i,allowed_peer_cidr=192.168.1.0/24,10.0.0.0/8 1582513589000000000 wireguard_peer,device=wg0,host=WGVPN,public_key=NZTRIrv/ClTcQoNAnChEot+WL7OH7uEGQmx8oAN9rWE= last_handshake_time_ns=1582513584530013376i,rx_bytes=6484i,tx_bytes=13540i 1582513589000000000 ``` diff --git a/plugins/inputs/wireguard/wireguard.go b/plugins/inputs/wireguard/wireguard.go index ed14d1a85..ae97de623 100644 --- a/plugins/inputs/wireguard/wireguard.go +++ b/plugins/inputs/wireguard/wireguard.go @@ -4,6 +4,7 @@ package wireguard import ( _ "embed" "fmt" + "strings" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" @@ -114,6 +115,14 @@ func (wg *Wireguard) gatherDevicePeerMetrics(acc telegraf.Accumulator, device *w "allowed_ips": len(peer.AllowedIPs), } + if len(peer.AllowedIPs) > 0 { + cidrs := []string{} + for _, ip := range peer.AllowedIPs { + cidrs = append(cidrs, ip.String()) + } + fields["allowed_peer_cidr"] = strings.Join(cidrs, ",") + } + gauges := map[string]interface{}{ "last_handshake_time_ns": peer.LastHandshakeTime.UnixNano(), "rx_bytes": peer.ReceiveBytes, diff --git a/plugins/inputs/wireguard/wireguard_test.go b/plugins/inputs/wireguard/wireguard_test.go index 1eb8c308c..800817ed9 100644 --- a/plugins/inputs/wireguard/wireguard_test.go +++ b/plugins/inputs/wireguard/wireguard_test.go @@ -65,6 +65,7 @@ func TestWireguard_gatherDevicePeerMetrics(t *testing.T) { "persistent_keepalive_interval_ns": int64(60000000000), "protocol_version": 0, "allowed_ips": 2, + "allowed_peer_cidr": ",", } expectGauges := map[string]interface{}{ "last_handshake_time_ns": int64(100000000000), @@ -78,8 +79,74 @@ func TestWireguard_gatherDevicePeerMetrics(t *testing.T) { wg.gatherDevicePeerMetrics(&acc, device, peer) - require.Equal(t, 6, acc.NFields()) + require.Equal(t, 7, acc.NFields()) acc.AssertDoesNotContainMeasurement(t, measurementDevice) acc.AssertContainsTaggedFields(t, measurementPeer, expectFields, expectTags) acc.AssertContainsTaggedFields(t, measurementPeer, expectGauges, expectTags) } + +func TestWireguard_allowedPeerCIDR(t *testing.T) { + var testcases = []struct { + name string + allowedIPs []net.IPNet + allowedPeerCidr string + }{ + { + "single address", + []net.IPNet{{ + IP: net.IPv4(192, 168, 1, 0), + Mask: net.CIDRMask(20, 32), + }}, + "192.168.1.0/20", + }, + { + "multiple addresses", + []net.IPNet{ + { + IP: net.IPv4(10, 0, 0, 0), + Mask: net.CIDRMask(8, 32), + }, + { + IP: net.IPv4(192, 168, 2, 0), + Mask: net.CIDRMask(24, 32), + }, + }, + "10.0.0.0/8,192.168.2.0/24", + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(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: tc.allowedIPs, + ProtocolVersion: 0, + } + expectFields := map[string]interface{}{ + "persistent_keepalive_interval_ns": int64(60000000000), + "protocol_version": 0, + "allowed_ips": len(tc.allowedIPs), + "allowed_peer_cidr": tc.allowedPeerCidr, + } + _ = map[string]string{ + "device": "wg0", + "public_key": pubkey.String(), + } + + wg.gatherDevicePeerMetrics(&acc, device, peer) + acc.AssertDoesNotContainMeasurement(t, measurementDevice) + acc.AssertContainsFields(t, measurementPeer, expectFields) + }) + } +}