diff options
author | Linus Nordberg <linus@nordberg.se> | 2019-09-30 09:17:16 +0200 |
---|---|---|
committer | Linus Nordberg <linus@nordberg.se> | 2019-10-11 15:29:04 +0200 |
commit | d8ec36b7ef3a54652fa59492159b615896fef2f3 (patch) | |
tree | 0fd71f90578ee3dc0720d5b60b0c787dc032a122 | |
parent | [server] Make leasetime a commandline option (diff) | |
download | wg-dynamic-d8ec36b7ef3a54652fa59492159b615896fef2f3.tar.xz wg-dynamic-d8ec36b7ef3a54652fa59492159b615896fef2f3.zip |
[server] Restore leases from allowedips at startup
-rwxr-xr-x | tests/restore-leases.bash | 162 | ||||
-rw-r--r-- | wg-dynamic-server.c | 30 |
2 files changed, 191 insertions, 1 deletions
diff --git a/tests/restore-leases.bash b/tests/restore-leases.bash new file mode 100755 index 0000000..43e4737 --- /dev/null +++ b/tests/restore-leases.bash @@ -0,0 +1,162 @@ +set -e +exec 3>&1 + +export WG_HIDE_KEYS=never +netnsn() { echo wg-test-$$-$1; } +pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; } +pp() { pretty "" "$*"; "$@"; } +maybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; } +nn() { local netns=$(netnsn $1) n=$1; shift; pretty $n "$*"; maybe_exec ip netns exec $netns "$@"; } +ipn() { local netns=$(netnsn $1) n=$1; shift; pretty $n "ip $*"; ip -n $netns "$@"; } + +ns="0 1 2" + +cleanup() { + set +e + exec 2>/dev/null + + for n in $ns; do ipn $n link del dev wg0; done + + local to_kill="$(for n in $ns; do $(ip netns pids $(netnsn $n)); done)" + [[ -n $to_kill ]] && kill $to_kill + + for n in $ns; do pp ip netns del $(netnsn $n); done + + exit +} + +trap cleanup EXIT + +pp ip netns add $(netnsn 0) +pp ip netns add $(netnsn 1) +pp ip netns add $(netnsn 2) +ipn 0 link set up dev lo + +ipn 0 link add dev wg0 type wireguard +ipn 0 link set wg0 netns $(netnsn 1) +ipn 0 link add dev wg0 type wireguard +ipn 0 link set wg0 netns $(netnsn 2) +server_private=$(wg genkey) +server_public=$(wg pubkey <<< $server_private) +client_private=$(wg genkey) +client_public=$(wg pubkey <<< $client_private) + +configure_peers() { + ipn 1 addr add fe80::/64 dev wg0 + ipn 2 addr add fe80::badc:0ffe:e0dd:f00d/128 dev wg0 + + nn 1 wg set wg0 \ + private-key <(echo $server_private) \ + listen-port 1 \ + peer $client_public \ + allowed-ips fe80::badc:0ffe:e0dd:f00d/128 + + nn 2 wg set wg0 \ + private-key <(echo $client_private) \ + listen-port 2 \ + peer $server_public \ + allowed-ips 0.0.0.0/0,::/0 + + ipn 1 link set up dev wg0 + ipn 2 link set up dev wg0 + + ipn 2 route add fe80::/128 dev wg0 + ipn 1 route add 192.168.4.0/28 dev wg0 + ipn 1 route add 192.168.73.0/27 dev wg0 + ipn 1 route add 2001:db8:1234::/124 dev wg0 + ipn 1 route add 2001:db8:7777::/124 dev wg0 +} +configure_peers + +nn 1 wg set wg0 peer "$client_public" endpoint [::1]:2 +nn 2 wg set wg0 peer "$server_public" endpoint [::1]:1 +nn 2 ping6 -c 10 -f -W 1 fe80::%wg0 +nn 1 ping6 -c 10 -f -W 1 fe80::badc:0ffe:e0dd:f00d%wg0 + +pretty "" "clientsh.bash can be run with the following arguments:" +echo +echo wg-test-$$ $server_public +echo + +## Start server in the background with 30s lease time +exec 4< <(nn 1 ./wg-dynamic-server --leasetime 30 wg0) +server_pid=$! +pretty "" "server_pid: $server_pid" + +## Get a lease +send_cmd() { + local n=$1; shift + local REQ="$1"; shift + + eval $( + printf $REQ | nn $n ncat -v -p 970 fe80::%wg0 970 | + while read -r line; do + key="${line%%=*}" + value="${line#*=}" + case "$key" in + ipv4) echo IPV4[$n]="$value"; continue ;; + ipv6) echo IPV6[$n]="$value"; continue ;; + leasestart) echo LEASESTART[$n]="$value"; continue ;; + leasetime) echo LEASETIME[$n]="$value"; continue ;; + errno) echo ERRNO[$n]="$value"; continue ;; + esac + done + ) +} +check_alowedips() { + local pubkey="$1"; shift + local ip="$1"; shift + + [[ -z "$ip" ]] && return 0 + + nn 1 wg show wg0 allowed-ips | + while read -r _pubkey _ips; do + [[ "$_pubkey" = "$pubkey" ]] || continue + for _ip in $_ips; do + [[ "$_ip" = "$ip" ]] && return 0 + done + done && return 0 + + pretty "" "Missing $ip in allowedips" + return 1 +} +declare -a IPV4 +declare -a IPV6 +declare -a LEASESTART +declare -a LEASETIME +declare -a ERRNO + +send_cmd 2 "request_ip=1\n\n" +check_alowedips "$client_public" "${IPV4[2]}" +check_alowedips "$client_public" "${IPV6[2]}" + +## Restart server with 10s leasetime +nn 1 kill $server_pid +sleep 1 +exec 4< <(nn 1 ./wg-dynamic-server --leasetime 3 wg0) || { pretty "" $?; false; } +server_pid=$! +pretty "" "server_pid 2: $server_pid" + +## Verify that the lease has been restored +check_alowedips "$client_public" "${IPV4[2]}" +check_alowedips "$client_public" "${IPV6[2]}" + +## Wait for the lease to expire +pp sleep 4 + +## Restart server +nn 1 kill $server_pid +sleep 1 +exec 4< <(nn 1 ./wg-dynamic-server wg0) + +## Verify that the lease has not reappeared +notlladdr='192.168.*/32|2001:.*/128' +nn 1 wg show wg0 allowed-ips | + while read -r _pubkey _ips; do + [[ "$_pubkey" = "$client_public" ]] || continue + for _ip in $_ips; do + [[ "$_ip" =~ $notlladdr ]] && { pretty "" "FAIL: $_ip"; false; } + done + done && true + +pretty "" "SUCCESS\n" diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c index cf5e860..27f4054 100644 --- a/wg-dynamic-server.c +++ b/wg-dynamic-server.c @@ -398,6 +398,33 @@ static void cleanup() } } +static void init_leaess_from_peers() +{ + wg_peer *peer; + + wg_for_each_peer (device, peer) { + wg_allowedip *allowedip; + struct in6_addr *lladdr = NULL; + struct in_addr *ipv4 = NULL; + struct in6_addr *ipv6 = NULL; + wg_for_each_allowedip (peer, allowedip) { + if (allowedip->family == AF_INET6 && + IN6_IS_ADDR_LINKLOCAL(&allowedip->ip6)) + lladdr = &allowedip->ip6; + else if (allowedip->family == AF_INET && !ipv4) + ipv4 = &allowedip->ip4; + else if (allowedip->family == AF_INET6 && !ipv6) + ipv6 = &allowedip->ip6; + } + + if (!ipv4 && !ipv6) + continue; + + set_lease(wg_interface, peer->public_key, leasetime, lladdr, + ipv4, ipv6); + } +} + static void setup() { if (inet_pton(AF_INET6, WG_DYNAMIC_ADDR, &well_known) != 1) @@ -423,7 +450,8 @@ static void setup() wg_interface); setup_sockets(); - leases_init("leases_file", nlsock); + leases_init(NULL, nlsock); + init_leaess_from_peers(); } static int get_avail_request() |