diff options
| author | rtk0c <[email protected]> | 2025-11-08 17:21:41 -0800 |
|---|---|---|
| committer | rtk0c <[email protected]> | 2025-11-08 17:21:41 -0800 |
| commit | 465962c79086aa810b0acf24c08662562a1265c3 (patch) | |
| tree | 80cb7baf7c08dffbf28f839e5845ece46e225871 | |
| parent | a22ec1bb09c76233a0b6edce9bfcb7b36ba191df (diff) | |
wg-reallyquick: cobbled together from wg-quick(1)
The skeleton framework came from https://www.wireguard.com/netns/#the-new-namespace-solution
The config parsing code came from wg-quick(1)
| -rw-r--r-- | wg-reallyquick | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/wg-reallyquick b/wg-reallyquick new file mode 100644 index 0000000..8762b64 --- /dev/null +++ b/wg-reallyquick @@ -0,0 +1,101 @@ +#!/bin/bash + +set -e -o pipefail +shopt -s extglob + +CONFIG_FILE="" +WG_CONFIG="" +INTERFACE="" +NETNS="" +ADDRESSES=( ) +MTU="" +DNS=( ) +DNS_SEARCH=( ) + +die() { + echo "$0: $*" >&2 + exit 1 +} + +parse_options() { + local interface_section=0 line key value stripped v + CONFIG_FILE="$1" + [[ $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" + CONFIG_FILE="$(readlink -f "$CONFIG_FILE")" + ((($(stat -c '0%#a' "$CONFIG_FILE") & $(stat -c '0%#a' "${CONFIG_FILE%/*}") & 0007) == 0)) || echo "Warning: \`$CONFIG_FILE' is world accessible" >&2 + INTERFACE="${BASH_REMATCH[2]}" + shopt -s nocasematch + while read -r line || [[ -n $line ]]; do + stripped="${line%%\#*}" + key="${stripped%%=*}"; key="${key##*([[:space:]])}"; key="${key%%*([[:space:]])}" + value="${stripped#*=}"; value="${value##*([[:space:]])}"; value="${value%%*([[:space:]])}" + [[ $key == "["* ]] && interface_section=0 + [[ $key == "[Interface]" ]] && interface_section=1 + if [[ $interface_section -eq 1 ]]; then + case "$key" in + Address) + ADDRESSES+=( ${value//,/ } ) + continue ;; + MTU) + MTU="$value" + continue ;; + DNS) + for v in ${value//,/ }; do + [[ $v =~ (^[0-9.]+$)|(^.*:.*$) ]] && DNS+=( $v ) || DNS_SEARCH+=( $v ) + done + continue ;; + esac + fi + WG_CONFIG+="$line"$'\n' + done < "$CONFIG_FILE" + shopt -u nocasematch +} + +add_addr() { + local proto=-4 + [[ $1 == *:* ]] && proto=-6 + ip -n $NETNS $proto address add "$1" dev "$INTERFACE" +} + +up() { + ip netns add $NETNS + ip link add wgvpn0 type wireguard + ip link set wgvpn0 netns $NETNS + ip netns exec $NETNS wg setconf wgvpn0 <(echo "$WG_CONFIG") + for i in "${ADDRESSES[@]}"; do + add_addr "$i" + done + if [[ -n $MTU ]]; then + ip -n $NETNS link set mtu "$MTU" up dev wgvpn0 + fi + ip -n $NETNS link set lo up + ip -n $NETNS link set wgvpn0 up + ip -n $NETNS route add default dev wgvpn0 + + mkdir -p "/etc/netns/$NETNS" + { + printf 'nameserver %s\n' "${DNS[@]}" + [[ ${#DNS_SEARCH[@]} -eq 0 ]] || printf 'search %s\n' "${DNS_SEARCH[*]}" + } | tee "/etc/netns/$NETNS/resolv.conf" > /dev/null +} + +down() { + ip -n $NETNS link del wgvpn0 + ip netns del $NETNS + + rm -rf "/etc/netns/$NETNS" +} + +COMMAND="$1" +parse_options "$2" +NETNS="${3:-$INTERFACE}" +echo "netns: $NETNS" +INTERFACE="wgvpn0" #TODO un-hardcode this + +case "$COMMAND" in + up) up "$@" ;; + down) down "$@" ;; + *) echo "Usage: $0 up|down" >&2; exit 1 ;; +esac |
