1
- #! /usr/local/ bin/bash
1
+ #! /usr/bin/env bash
2
2
# SPDX-License-Identifier: GPL-2.0
3
3
#
4
- # Copyright (C) 2015-2020 Jason A. Donenfeld <[email protected] >. All Rights Reserved.
4
+ # Copyright (C) 2015-2023 Jason A. Donenfeld <[email protected] >. All Rights Reserved.
5
5
#
6
6
7
7
set -e -o pipefail
8
8
shopt -s extglob
9
9
export LC_ALL=C
10
10
11
- exec 3>&2
12
11
SELF=" $( readlink -f " ${BASH_SOURCE[0]} " ) "
13
12
export PATH=" ${SELF%/* } :$PATH "
14
13
@@ -29,7 +28,7 @@ PROGRAM="${0##*/}"
29
28
ARGS=( " $@ " )
30
29
31
30
cmd () {
32
- echo " [#] $* " >&3
31
+ echo " [#] $* " >&2
33
32
" $@ "
34
33
}
35
34
@@ -45,7 +44,7 @@ parse_options() {
45
44
[[ -e $CONFIG_FILE ]] || die " \` $CONFIG_FILE ' does not exist"
46
45
[[ $CONFIG_FILE =~ (^| /)([a-zA-Z0-9_= +.-]{1,15})\. conf$ ]] || die " The config file must be a valid interface name, followed by .conf"
47
46
CONFIG_FILE=" $( readlink -f " $CONFIG_FILE " ) "
48
- (( ($(stat - f '0 % #p ' "$CONFIG_FILE ") & $(stat - f '0 % #p ' "${CONFIG_FILE%/* } ") & 0007 ) == 0 )) || echo " Warning: \` $CONFIG_FILE ' is world accessible" >&2
47
+ (( ($(stat - c '0 % #a ' "$CONFIG_FILE ") & $(stat - c '0 % #a ' "${CONFIG_FILE%/* } ") & 0007 ) == 0 )) || echo " Warning: \` $CONFIG_FILE ' is world accessible" >&2
49
48
INTERFACE=" ${BASH_REMATCH[2]} "
50
49
shopt -s nocasematch
51
50
while read -r line || [[ -n $line ]]; do
@@ -83,37 +82,32 @@ read_bool() {
83
82
}
84
83
85
84
auto_su () {
86
- [[ $UID == 0 ]] || exec doas -- " $BASH " -- " $SELF " " ${ARGS[@]} "
85
+ # Other platforms appear to escalate priviliges silently.
86
+ # We will just require root permissions.
87
+ [[ $UID == 0 ]] || die " must be run as root"
87
88
}
88
89
89
-
90
90
get_real_interface () {
91
- local interface line
92
- while IFS= read -r line; do
93
- if [[ $line =~ ^([a-z]+[0-9]+):\ .+ ]]; then
94
- interface=" ${BASH_REMATCH[1]} "
95
- continue
96
- fi
97
- if [[ $interface == wg* && $line =~ ^\ description:\ wg-quick:\ (.+) && ${BASH_REMATCH[1]} == " $INTERFACE " ]]; then
98
- REAL_INTERFACE=" $interface "
99
- return 0
100
- fi
101
- done < <( ifconfig)
102
- return 1
91
+ local interface diff
92
+ wg show interfaces > /dev/null
93
+ [[ -f " /var/run/wireguard/$INTERFACE .name" ]] || return 1
94
+ interface=" $( < " /var/run/wireguard/$INTERFACE .name" ) "
95
+ [[ -n $interface && -S " /var/run/wireguard/$interface .sock" ]] || return 1
96
+ diff=$(( $(stat - c % Y "/ var/ run/ wireguard/ $interface .sock" 2 >/ dev/ null || echo 200 ) - $(stat - c % Y "/ var/ run/ wireguard/ $INTERFACE .name" 2 >/ dev/ null || echo 100 ) ))
97
+ [[ $diff -ge 2 || $diff -le -2 ]] && return 1
98
+ REAL_INTERFACE=" $interface "
99
+ echo " [+] Interface for $INTERFACE is $REAL_INTERFACE " >&2
100
+ return 0
103
101
}
104
102
105
103
add_if () {
106
- while true ; do
107
- local -A existing_ifs=" ( $( wg show interfaces | sed ' s/\([^ ]*\)/[\1]=1/g' ) )"
108
- local index ret
109
- for (( index= 0 ; index <= 2147483647 ; ++ index)) ; do [[ -v existing_ifs[wg$index ] ]] || break ; done
110
- if ret=" $( cmd ifconfig wg$index create description " wg-quick: $INTERFACE " 2>&1 ) " ; then
111
- REAL_INTERFACE=" wg$index "
112
- return 0
113
- fi
114
- [[ $ret == * " ifconfig: SIOCIFCREATE: File exists" * ]] && continue
115
- echo " $ret " >&3
116
- return 1
104
+ export WG_TUN_NAME_FILE=" /var/run/wireguard/$INTERFACE .name"
105
+ mkdir -p " /var/run/wireguard/"
106
+ cmd " ${WG_QUICK_USERSPACE_IMPLEMENTATION:- wireguard-go} " tun
107
+ cmd sleep 0.1
108
+ get_real_interface
109
+ until ipadm show-if $REAL_INTERFACE 2> /dev/null | grep -q $REAL_INTERFACE ; do
110
+ cmd sleep 0.1
117
111
done
118
112
}
119
113
@@ -143,12 +137,18 @@ del_routes() {
143
137
}
144
138
145
139
del_if () {
140
+ local addr
146
141
unset_dns
147
- [[ -n $REAL_INTERFACE ]] && cmd ifconfig $REAL_INTERFACE destroy
142
+ [[ -n $REAL_INTERFACE ]] && ipadm show-addr -p -o addrobj | grep $REAL_INTERFACE / | while read addr; do
143
+ cmd ipadm delete-addr $addr
144
+ done
145
+ [[ -z $REAL_INTERFACE ]] || cmd rm -f " /var/run/wireguard/$REAL_INTERFACE .sock"
146
+ cmd rm -f " /var/run/wireguard/$INTERFACE .name"
148
147
}
149
148
150
149
up_if () {
151
- cmd ifconfig " $REAL_INTERFACE " up
150
+ # Due to illumos tun driver quirks there is nothing to do here.
151
+ true
152
152
}
153
153
154
154
add_addr () {
@@ -160,7 +160,9 @@ add_addr() {
160
160
family=inet
161
161
[[ -n $FIRSTADDR4 ]] || FIRSTADDR4=" ${1%/* } "
162
162
fi
163
- cmd ifconfig " $REAL_INTERFACE " $family " $1 " alias
163
+ # cleanup just in case
164
+ ipadm delete-addr " $REAL_INTERFACE /$2 " & > /dev/null || true
165
+ cmd ipadm create-addr -t -T static -a " local=$1 ,remote=$1 " " $REAL_INTERFACE /$2 "
164
166
}
165
167
166
168
set_mtu () {
@@ -283,25 +285,14 @@ monitor_daemon() {
283
285
284
286
set_dns () {
285
287
[[ ${# DNS[@]} -gt 0 ]] || return 0
286
-
287
- # TODO: add exclusive support for nameservers
288
- if pgrep -qx unwind; then
289
- echo " [!] WARNING: unwind will leak DNS queries" >&2
290
- elif pgrep -qx resolvd; then
291
- echo " [!] WARNING: resolvd may leak DNS queries" >&2
292
- else
293
- echo " [+] resolvd is not running, DNS will not be configured" >&2
294
- return 0
295
- fi
296
-
297
288
cmd cp /etc/resolv.conf " /etc/resolv.conf.wg-quick-backup.$INTERFACE "
298
- [[ ${# DNS_SEARCH[@]} -eq 0 ]] || cmd printf ' search %s\n' " ${DNS_SEARCH[*]} " > /etc/resolv.conf
299
- route nameserver ${REAL_INTERFACE} ${DNS[@]}
289
+ { cmd printf ' nameserver %s\n' " ${DNS[@]} "
290
+ [[ ${# DNS_SEARCH[@]} -eq 0 ]] || cmd printf ' search %s\n' " ${DNS_SEARCH[*]} "
291
+ } > /etc/resolv.conf
300
292
}
301
293
302
294
unset_dns () {
303
295
[[ -f " /etc/resolv.conf.wg-quick-backup.$INTERFACE " ]] || return 0
304
- route nameserver ${REAL_INTERFACE}
305
296
cmd mv " /etc/resolv.conf.wg-quick-backup.$INTERFACE " /etc/resolv.conf
306
297
}
307
298
@@ -415,14 +406,16 @@ cmd_usage() {
415
406
416
407
cmd_up () {
417
408
local i
409
+ local n=0
418
410
get_real_interface && die " \` $INTERFACE ' already exists as \` $REAL_INTERFACE '"
419
411
trap ' del_if; del_routes; exit' INT TERM EXIT
420
412
execute_hooks " ${PRE_UP[@]} "
421
413
add_if
422
- set_config
423
414
for i in " ${ADDRESSES[@]} " ; do
424
- add_addr " $i "
415
+ add_addr " $i " " $INTERFACE$n "
416
+ n=$(( n + 1 ))
425
417
done
418
+ set_config
426
419
set_mtu
427
420
up_if
428
421
set_dns
0 commit comments