blob: 8762b640a9d8671509881d4bb7b9efbb3a2c9768 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
|