Skip to content

Commit

Permalink
wgpeerselector: add package
Browse files Browse the repository at this point in the history
For docs, see net/wgpeerselector/README.md.
  • Loading branch information
lemoer authored and blocktrron committed Sep 14, 2021
1 parent 0648b2d commit 0a334b8
Show file tree
Hide file tree
Showing 5 changed files with 656 additions and 0 deletions.
25 changes: 25 additions & 0 deletions net/wgpeerselector/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=wgpeerselector
PKG_VERSION:=1

include $(INCLUDE_DIR)/package.mk

define Package/wgpeerselector
SECTION:=net
CATEGORY:=Network
TITLE:=Wireguard peer selector daemon
DEPENDS:=+lua +wireguard-tools +libubox-lua +libubus-lua +luaposix
endef

define Build/Configure
endef

define Build/Compile
endef

define Package/wgpeerselector/install
$(CP) ./files/* $(1)/
endef

$(eval $(call BuildPackage,wgpeerselector))
97 changes: 97 additions & 0 deletions net/wgpeerselector/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
wgpeerselector
==============

The wireguard peer selector is a daemon allowing to connect to only one
wireguard peer of a set of N peers. It does that by randomly picking one
peer, trying to connect and on failure trying to connect to the next peer.
It is comparable to setting the "peer limit" to one in fastd. The daemon
is written in lua and hardwired to OpenWrt mechanisms.

Features:
- Status socket via UBUS.
- Routes for "Allowed IPs" are installed to the kernel.
- Synchronize time via NTP.
- Currently necessary in wireguard to reestablish a connection after
rebooting. [Reference](https://lists.zx2c4.com/pipermail/wireguard/2019-February/003850.html)
- Can change its unix group.

How does it work?
-----------------

The daemon is configured using its netifd proto `wgpeerselector`. The wireguard
interface is set up by the standard wireguard netifd proto `wireguard`.
Configuring peers via the `wireguard` proto is not necessary because this will
be done by wgpeerselector based on its uci config:

/etc/config/network:
```
config interface 'vpn'
option proto 'wireguard'
option fwmark '1'
option private_key 'YOUR_PRIVATE_KEY_GOES_HERE'
list addresses 'fe80::02a4:18ff:fe7e:a10d'
option disabled '0'
config interface 'vpn_peerselector'
option proto 'wgpeerselector'
option transitive '1'
option ifname 'vpn'
option unix_group 'YOUR_UNIX_GROUP_GOES_HERE' # this is optional
```

/etc/config/wgpeerselector:
```
config peer 'test_unknown_a'
option enabled '1'
option public_key 'mIDOdscl2R3Dq+YthxdTvvtH4D53VhawzEnmet+E7W0='
list allowed_ips 'fe80::1/128'
option ifname 'vpn'
option endpoint 'hostname.example.com:51820'
```

Status information can be obtained via ubus:
```
root@platzhalter-525400123456:~# ubus call wgpeerselector.vpn status
{
"peers": {
"test_unknown_a": false,
"test_unknown_b": false,
"test_sn07": {
"established": 1490
}
}
}
```

Algorithm:
----------

A connection is considered as "established" if the latest handshakes was
within the last 2.5 minutes.

Installing a peer:
1. Resolve its endpoint if necessary.
2. Randomly pick a remote IP.
3. Install the peer with that ip to the kernel.
4. Wait 5 seconds.
5. Check whether the connection is established.
- If not, remove the peer from the kernel again.

Main Loop:
- Wait for the interface, if it does not exist.
- Try to synchronize time via NTP, if not done yet.
- If no connection is established:
- Randomly pick a peer.
- Try to establish a connection.
- If a connection is established:
- Check every 5 seconds if the connection is still established.

Picking peers is done in such a way that all peers are tried once
before one peer is attempted for the second time. The same goes for the
DNS resolultion of the endpoints.

Warning: This algorithm only works if something is causing traffic into
the wireguard interface. This is due to the fact, that wireguard is only
doing handshakes, if it has to. While running mesh protocols on top of the
wireguard interface this is usually not a problem, since those protocols
periodically send Hello, OGM, ... packets.
Empty file.
33 changes: 33 additions & 0 deletions net/wgpeerselector/files/lib/netifd/proto/wgpeerselector.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/sh

. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"

proto_wgpeerselector_init_config() {
proto_config_add_string 'unix_group'
}

proto_wgpeerselector_setup() {
local config="$1"
local iface="$2"
local unix_group

json_get_vars unix_group

(proto_add_host_dependency "$config" '' "$iface")

proto_init_update "$iface" 1
proto_send_update "$config"

proto_run_command "$config" wgpeerselector \
-i "$iface" ${unix_group:+--group "$unix_group"}
}


proto_wgpeerselector_teardown() {
local config="$1"
proto_kill_command "$config"
}

add_protocol wgpeerselector
Loading

0 comments on commit 0a334b8

Please sign in to comment.