1- #! /usr/local/ bin/bash
1+ #! /usr/bin/env bash
22# SPDX-License-Identifier: GPL-2.0
33#
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.55#
66
77set -e -o pipefail
88shopt -s extglob
99export LC_ALL=C
1010
11- exec 3>&2
1211SELF=" $( readlink -f " ${BASH_SOURCE[0]} " ) "
1312export PATH=" ${SELF%/* } :$PATH "
1413
@@ -29,7 +28,7 @@ PROGRAM="${0##*/}"
2928ARGS=( " $@ " )
3029
3130cmd () {
32- echo " [#] $* " >&3
31+ echo " [#] $* " >&2
3332 " $@ "
3433}
3534
@@ -45,7 +44,7 @@ parse_options() {
4544 [[ -e $CONFIG_FILE ]] || die " \` $CONFIG_FILE ' does not exist"
4645 [[ $CONFIG_FILE =~ (^| /)([a-zA-Z0-9_= +.-]{1,15})\. conf$ ]] || die " The config file must be a valid interface name, followed by .conf"
4746 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
4948 INTERFACE=" ${BASH_REMATCH[2]} "
5049 shopt -s nocasematch
5150 while read -r line || [[ -n $line ]]; do
@@ -83,37 +82,32 @@ read_bool() {
8382}
8483
8584auto_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"
8788}
8889
89-
9090get_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
103101}
104102
105103add_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
117111 done
118112}
119113
@@ -143,12 +137,18 @@ del_routes() {
143137}
144138
145139del_if () {
140+ local addr
146141 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"
148147}
149148
150149up_if () {
151- cmd ifconfig " $REAL_INTERFACE " up
150+ # Due to illumos tun driver quirks there is nothing to do here.
151+ true
152152}
153153
154154add_addr () {
@@ -160,7 +160,9 @@ add_addr() {
160160 family=inet
161161 [[ -n $FIRSTADDR4 ]] || FIRSTADDR4=" ${1%/* } "
162162 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 "
164166}
165167
166168set_mtu () {
@@ -283,25 +285,14 @@ monitor_daemon() {
283285
284286set_dns () {
285287 [[ ${# 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-
297288 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
300292}
301293
302294unset_dns () {
303295 [[ -f " /etc/resolv.conf.wg-quick-backup.$INTERFACE " ]] || return 0
304- route nameserver ${REAL_INTERFACE}
305296 cmd mv " /etc/resolv.conf.wg-quick-backup.$INTERFACE " /etc/resolv.conf
306297}
307298
@@ -415,14 +406,16 @@ cmd_usage() {
415406
416407cmd_up () {
417408 local i
409+ local n=0
418410 get_real_interface && die " \` $INTERFACE ' already exists as \` $REAL_INTERFACE '"
419411 trap ' del_if; del_routes; exit' INT TERM EXIT
420412 execute_hooks " ${PRE_UP[@]} "
421413 add_if
422- set_config
423414 for i in " ${ADDRESSES[@]} " ; do
424- add_addr " $i "
415+ add_addr " $i " " $INTERFACE$n "
416+ n=$(( n + 1 ))
425417 done
418+ set_config
426419 set_mtu
427420 up_if
428421 set_dns
0 commit comments