Skip to content

Commit

Permalink
wg-quick linux: Add strip-and-eval cmd to extract keys from PostUp
Browse files Browse the repository at this point in the history
The manpage mentions the trick to use PostUp to read the PrivateKey (or
PresharedKey) from a command (or file). However, when you actually use
that you notice that this is currently not fully supported. The issue is
that

```Shell
wg syncconf wgnet0 <(wg-quick strip wgnet0)
```

from the manpage now breaks the VPN because it *removes* the private key
from the WireGuard interface. The reason is that `strip` removes PostUp
of course.

This patch tries to add full support to read WireGuard keys from files
or command outputs by evaluating PostUp using a best effort approach
(using regex). It will not work for everything but when you follow the
manpage closely, it will work.

I also propose to update the systemd template to make seamless use of
this. This is not a must because the sysadmin can easily change the
ExecReload using systemd drop-in files.

Example use of this patch:
https://github.com/ypid/ansible-wireguard/tree/prepare-for-debops

Signed-off-by: Robin Schneider <[email protected]>
  • Loading branch information
ypid committed Oct 4, 2020
1 parent 265e81a commit 9762a0b
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
9 changes: 9 additions & 0 deletions src/man/wg-quick.8
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ wg-quick - set up a WireGuard interface simply
.I save
|
.I strip
|
.I strip-and-eval
] [
.I CONFIG_FILE
|
Expand All @@ -34,6 +36,7 @@ with all
.BR wg-quick (8)-specific
options removed, suitable for use with
.BR wg (8).
Use \fIstrip-and-eval\fP in case you use `PostUp' to read PrivateKey or PresharedKey from a file or command and need them in the output.

\fICONFIG_FILE\fP is a configuration file, whose filename is the interface name
followed by `.conf'. Otherwise, \fIINTERFACE\fP is an interface name, with configuration
Expand Down Expand Up @@ -256,6 +259,12 @@ sessions:

\fB # wg syncconf wgnet0 <(wg-quick strip wgnet0)\fP

\fIstrip-and-eval\fP additionally extracts PrivateKey and PresharedKey from `PostUp` statements and translates them into configuration that
.BR wg (8)
does understand:

\fB # wg syncconf wgnet0 <(wg-quick strip-and-eval wgnet0)\fP

.SH SEE ALSO
.BR wg (8),
.BR ip (8),
Expand Down
2 changes: 1 addition & 1 deletion src/systemd/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/wg-quick up %i
ExecStop=/usr/bin/wg-quick down %i
ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip %i)'
ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip-and-eval %i)'
Environment=WG_ENDPOINT_RESOLUTION_RETRIES=infinity

[Install]
Expand Down
36 changes: 33 additions & 3 deletions src/wg-quick/linux.bash
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ die() {
}

parse_options() {
local parsing_mode part_of_command peer_pubkey
local interface_section=0 line key value stripped v
declare -A peer_pubkey_to_psk
CONFIG_FILE="$1"
parsing_mode="${2:-safe}"
[[ $CONFIG_FILE =~ ^[a-zA-Z0-9_=+.-]{1,15}$ ]] && CONFIG_FILE="/etc/wireguard/$CONFIG_FILE.conf"
[[ -e $CONFIG_FILE ]] || die "\`$CONFIG_FILE' does not exist"
[[ $CONFIG_FILE =~ (^|/)([a-zA-Z0-9_=+.-]{1,15})\.conf$ ]] || die "The config file must be a valid interface name, followed by .conf"
Expand All @@ -63,12 +66,35 @@ parse_options() {
Table) TABLE="$value"; continue ;;
PreUp) PRE_UP+=( "$value" ); continue ;;
PreDown) PRE_DOWN+=( "$value" ); continue ;;
PostUp) POST_UP+=( "$value" ); continue ;;
PostUp) POST_UP+=( "$value" );
if [[ $parsing_mode == "unsafe" ]]; then
part_of_command=""
if [[ $value =~ ^wg\ +set\ +%i\ +private-key\ +(.+)$ ]]; then
key='PrivateKey'
part_of_command="${BASH_REMATCH[1]}"
elif [[ $value =~ ^wg\ +set\ +%i\ +peer\ +(.+)\ +preshared-key\ +(.+)$ ]]; then
key='PresharedKey'
peer_pubkey="${BASH_REMATCH[1]}"
part_of_command="${BASH_REMATCH[2]}"
fi
if [[ -n "$part_of_command" ]]; then
part_of_command="${part_of_command//%i/$INTERFACE}"
value="$(eval "cat $part_of_command")"
case "$key" in
PresharedKey) peer_pubkey_to_psk["$peer_pubkey"]="$value" ;;
*) WG_CONFIG+="$key = $value"$'\n' ;;
esac
fi
fi
continue ;;
PostDown) POST_DOWN+=( "$value" ); continue ;;
SaveConfig) read_bool SAVE_CONFIG "$value"; continue ;;
esac
fi
WG_CONFIG+="$line"$'\n'
if [[ $interface_section -eq 0 && $key == 'PublicKey' && -n "${peer_pubkey_to_psk[$value]}" ]]; then
WG_CONFIG+="PresharedKey = ${peer_pubkey_to_psk[$value]}"$'\n'
fi
done < "$CONFIG_FILE"
shopt -u nocasematch
}
Expand Down Expand Up @@ -224,7 +250,7 @@ add_default() {
cmd ip $proto rule add not fwmark $table table $table
cmd ip $proto rule add table main suppress_prefixlength 0

local marker="-m comment --comment \"wg-quick(8) rule for $INTERFACE\"" restore=$'*raw\n' nftable="wg-quick-$INTERFACE" nftcmd
local marker="-m comment --comment \"wg-quick(8) rule for $INTERFACE\"" restore=$'*raw\n' nftable="wg-quick-$INTERFACE" nftcmd
printf -v nftcmd '%sadd table %s %s\n' "$nftcmd" "$pf" "$nftable"
printf -v nftcmd '%sadd chain %s %s preraw { type filter hook prerouting priority -300; }\n' "$nftcmd" "$pf" "$nftable"
printf -v nftcmd '%sadd chain %s %s premangle { type filter hook prerouting priority -150; }\n' "$nftcmd" "$pf" "$nftable"
Expand Down Expand Up @@ -298,7 +324,7 @@ execute_hooks() {

cmd_usage() {
cat >&2 <<-_EOF
Usage: $PROGRAM [ up | down | save | strip ] [ CONFIG_FILE | INTERFACE ]
Usage: $PROGRAM [ up | down | save | strip | strip-and-eval ] [ CONFIG_FILE | INTERFACE ]
CONFIG_FILE is a configuration file, whose filename is the interface name
followed by \`.conf'. Otherwise, INTERFACE is an interface name, with
Expand Down Expand Up @@ -381,6 +407,10 @@ elif [[ $# -eq 2 && $1 == strip ]]; then
auto_su
parse_options "$2"
cmd_strip
elif [[ $# -eq 2 && $1 == strip-and-eval ]]; then
auto_su
parse_options "$2" "unsafe"
cmd_strip
else
cmd_usage
exit 1
Expand Down

0 comments on commit 9762a0b

Please sign in to comment.