summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2025-11-08 17:21:41 -0800
committerrtk0c <[email protected]>2025-11-08 17:21:41 -0800
commit465962c79086aa810b0acf24c08662562a1265c3 (patch)
tree80cb7baf7c08dffbf28f839e5845ece46e225871
parenta22ec1bb09c76233a0b6edce9bfcb7b36ba191df (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-reallyquick101
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