~garritfra/wireguard-tools

91fbeb4a926b8a75274d012a3994ef337dca51d9 — Jason A. Donenfeld 4 years ago 9a0d65e
Revert "wg-quick: wait on process substitutions"

This reverts commit 26683f6c9ad18d9914b23312c221f27fd5ecab51, which
means the old problem comes back. That's an issue. But waiting on
process substitutions is not available with commonly used bash versions:

  # wg-quick up demo
  [#] ip link add demo type wireguard
  [#] wg setconf demo /dev/fd/63
  /usr/bin/wg-quick: line 251: wait: pid 2955 is not a child of this shell
  [#] ip link delete dev demo

This means we have to wait a few years before fixing this issue. IOW,
bash limitation; can't fix.

Reported-by: Theodore Mozzo <theodore.mozzo@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
M src/wg-quick/darwin.bash => src/wg-quick/darwin.bash +14 -14
@@ 92,7 92,7 @@ detect_launchd() {
			LAUNCHED_BY_LAUNCHD=1
			break
		fi
	done < <(launchctl procinfo $$ 2>/dev/null); wait $!
	done < <(launchctl procinfo $$ 2>/dev/null)
}

read_bool() {


@@ 132,14 132,14 @@ del_routes() {
	local todelete=( ) destination gateway netif
	while read -r destination _ _ _ _ netif _; do
		[[ $netif == "$REAL_INTERFACE" ]] && todelete+=( "$destination" )
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)
	for destination in "${todelete[@]}"; do
		cmd route -q -n delete -inet "$destination" >/dev/null || true
	done
	todelete=( )
	while read -r destination gateway _ netif; do
		[[ $netif == "$REAL_INTERFACE" || ( $netif == lo* && $gateway == "$REAL_INTERFACE" ) ]] && todelete+=( "$destination" )
	done < <(netstat -nr -f inet6); wait $!
	done < <(netstat -nr -f inet6)
	for destination in "${todelete[@]}"; do
		cmd route -q -n delete -inet6 "$destination" >/dev/null || true
	done


@@ 181,7 181,7 @@ set_mtu() {
			defaultif="$netif"
			break
		fi
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)
	[[ -n $defaultif && $(ifconfig "$defaultif") =~ mtu\ ([0-9]+) ]] && mtu="${BASH_REMATCH[1]}"
	[[ $mtu -gt 0 ]] || mtu=1500
	mtu=$(( mtu - 80 ))


@@ 197,14 197,14 @@ collect_gateways() {
		[[ $destination == default ]] || continue
		GATEWAY4="$gateway"
		break
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)

	GATEWAY6=""
	while read -r destination gateway _; do
		[[ $destination == default ]] || continue
		GATEWAY6="$gateway"
		break
	done < <(netstat -nr -f inet6); wait $!
	done < <(netstat -nr -f inet6)
}

collect_endpoints() {


@@ 212,7 212,7 @@ collect_endpoints() {
	while read -r _ endpoint; do
		[[ $endpoint =~ ^\[?([a-z0-9:.]+)\]?:[0-9]+$ ]] || continue
		ENDPOINTS+=( "${BASH_REMATCH[1]}" )
	done < <(wg show "$REAL_INTERFACE" endpoints); wait $!
	done < <(wg show "$REAL_INTERFACE" endpoints)
}

declare -A SERVICE_DNS


@@ 230,7 230,7 @@ collect_new_service_dns() {
		get_response="$(cmd networksetup -getsearchdomains "$service")"
		[[ $get_response == *" "* ]] && get_response="Empty"
		[[ -n $get_response ]] && SERVICE_DNS_SEARCH["$service"]="$get_response"
	done; } < <(networksetup -listallnetworkservices); wait $!
	done; } < <(networksetup -listallnetworkservices)

	for service in "${!SERVICE_DNS[@]}"; do
		if ! [[ -n ${found_services["$service"]} ]]; then


@@ 304,7 304,7 @@ set_dns() {
			else
				cmd networksetup -setsearchdomains "$service" "${DNS_SEARCH[@]}"
			fi
		); wait $!
		)
	done
}



@@ 316,7 316,7 @@ del_dns() {
		done < <(
			cmd networksetup -setdnsservers "$service" ${SERVICE_DNS["$service"]} || true
			cmd networksetup -setsearchdomains "$service" ${SERVICE_DNS_SEARCH["$service"]} || true
		); wait $!
		)
	done
}



@@ 339,7 339,7 @@ monitor_daemon() {
			set_dns
			sleep 2 && kill -ALRM $pid 2>/dev/null &
		fi
	done < <(route -n monitor); wait $!) &
	done < <(route -n monitor)) &
	[[ -n $LAUNCHED_BY_LAUNCHD ]] || disown
}



@@ 367,7 367,7 @@ add_route() {
}

set_config() {
	cmd wg setconf "$REAL_INTERFACE" <(echo "$WG_CONFIG"); wait $!
	cmd wg setconf "$REAL_INTERFACE" <(echo "$WG_CONFIG")
}

save_config() {


@@ 375,7 375,7 @@ save_config() {
	new_config=$'[Interface]\n'
	while read -r address; do
		[[ $address =~ inet6?\ ([^ ]+) ]] && new_config+="Address = ${BASH_REMATCH[1]}"$'\n'
	done < <(ifconfig "$REAL_INTERFACE"); wait $!
	done < <(ifconfig "$REAL_INTERFACE")
	# TODO: actually determine current DNS for interface
	for address in "${DNS[@]}"; do
		new_config+="DNS = $address"$'\n'


@@ 458,7 458,7 @@ cmd_up() {
	done
	set_mtu
	up_if
	for i in $({ while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$REAL_INTERFACE" allowed-ips); wait $!; } | sort -nr -k 2 -t /); do
	for i in $(while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$REAL_INTERFACE" allowed-ips) | sort -nr -k 2 -t /); do
		add_route "$i"
	done
	[[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route

M src/wg-quick/freebsd.bash => src/wg-quick/freebsd.bash +13 -13
@@ 121,14 121,14 @@ del_routes() {
	local todelete=( ) destination gateway netif
	while read -r destination _ _ _ _ netif _; do
		[[ $netif == "$INTERFACE" ]] && todelete+=( "$destination" )
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)
	for destination in "${todelete[@]}"; do
		cmd route -q -n delete -inet "$destination" || true
	done
	todelete=( )
	while read -r destination gateway _ netif; do
		[[ $netif == "$INTERFACE" || ( $netif == lo* && $gateway == "$INTERFACE" ) ]] && todelete+=( "$destination" )
	done < <(netstat -nr -f inet6); wait $!
	done < <(netstat -nr -f inet6)
	for destination in "${todelete[@]}"; do
		cmd route -q -n delete -inet6 "$destination" || true
	done


@@ 191,9 191,9 @@ set_mtu() {
		[[ ${BASH_REMATCH[1]} == *:* ]] && family=inet6
		output="$(route -n get "-$family" "${BASH_REMATCH[1]}" || true)"
		[[ $output =~ interface:\ ([^ ]+)$'\n' && $(ifconfig "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
	done < <(wg show "$INTERFACE" endpoints); wait $!
	done < <(wg show "$INTERFACE" endpoints)
	if [[ $mtu -eq 0 ]]; then
		read -r output < <(route -n get default) || true
		read -r output < <(route -n get default || true) || true
		[[ $output =~ interface:\ ([^ ]+)$'\n' && $(ifconfig "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
	fi
	[[ $mtu -gt 0 ]] || mtu=1500


@@ 209,14 209,14 @@ collect_gateways() {
		[[ $destination == default ]] || continue
		GATEWAY4="$gateway"
		break
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)

	GATEWAY6=""
	while read -r destination gateway _; do
		[[ $destination == default ]] || continue
		GATEWAY6="$gateway"
		break
	done < <(netstat -nr -f inet6); wait $!
	done < <(netstat -nr -f inet6)
}

collect_endpoints() {


@@ 224,7 224,7 @@ collect_endpoints() {
	while read -r _ endpoint; do
		[[ $endpoint =~ ^\[?([a-z0-9:.]+)\]?:[0-9]+$ ]] || continue
		ENDPOINTS+=( "${BASH_REMATCH[1]}" )
	done < <(wg show "$INTERFACE" endpoints); wait $!
	done < <(wg show "$INTERFACE" endpoints)
}

set_endpoint_direct_route() {


@@ 294,7 294,7 @@ monitor_daemon() {
		if_exists || break
		[[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route
		# TODO: set the mtu as well, but only if up
	done < <(route -n monitor); wait $!) & disown
	done < <(route -n monitor)) & disown
}

HAVE_SET_DNS=0


@@ 335,7 335,7 @@ add_route() {
}

set_config() {
	cmd wg setconf "$INTERFACE" <(echo "$WG_CONFIG"); wait $!
	cmd wg setconf "$INTERFACE" <(echo "$WG_CONFIG")
}

save_config() {


@@ 343,13 343,13 @@ save_config() {
	new_config=$'[Interface]\n'
	{ read -r _; while read -r _ _ _ address _; do
		new_config+="Address = $address"$'\n'
	done } < <(netstat -I "$INTERFACE" -n -W -f inet); wait $!
	done } < <(netstat -I "$INTERFACE" -n -W -f inet)
	{ read -r _; while read -r _ _ _ address _; do
		new_config+="Address = $address"$'\n'
	done } < <(netstat -I "$INTERFACE" -n -W -f inet6); wait $!
	done } < <(netstat -I "$INTERFACE" -n -W -f inet6)
	while read -r address; do
		[[ $address =~ ^nameserver\ ([a-zA-Z0-9_=+:%.-]+)$ ]] && new_config+="DNS = ${BASH_REMATCH[1]}"$'\n'
	done < <(resolvconf -l "$INTERFACE" 2>/dev/null); wait $!
	done < <(resolvconf -l "$INTERFACE" 2>/dev/null)
	[[ -n $MTU ]] && new_config+="MTU = $MTU"$'\n'
	[[ -n $TABLE ]] && new_config+="Table = $TABLE"$'\n'
	[[ $SAVE_CONFIG -eq 0 ]] || new_config+=$'SaveConfig = true\n'


@@ 427,7 427,7 @@ cmd_up() {
	set_mtu
	up_if
	set_dns
	for i in $({ while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$INTERFACE" allowed-ips); wait $!; } | sort -nr -k 2 -t /); do
	for i in $(while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$INTERFACE" allowed-ips) | sort -nr -k 2 -t /); do
		add_route "$i"
	done
	[[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route

M src/wg-quick/linux.bash => src/wg-quick/linux.bash +11 -11
@@ 132,9 132,9 @@ set_mtu_up() {
		[[ $endpoint =~ ^\[?([a-z0-9:.]+)\]?:[0-9]+$ ]] || continue
		output="$(ip route get "${BASH_REMATCH[1]}" || true)"
		[[ ( $output =~ mtu\ ([0-9]+) || ( $output =~ dev\ ([^ ]+) && $(ip link show dev "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) ) ) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
	done < <(wg show "$INTERFACE" endpoints); wait $!
	done < <(wg show "$INTERFACE" endpoints)
	if [[ $mtu -eq 0 ]]; then
		read -r output < <(ip route show default) || true
		read -r output < <(ip route show default || true) || true
		[[ ( $output =~ mtu\ ([0-9]+) || ( $output =~ dev\ ([^ ]+) && $(ip link show dev "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) ) ) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
	fi
	[[ $mtu -gt 0 ]] || mtu=1500


@@ 191,8 191,8 @@ remove_firewall() {
		local table nftcmd
		while read -r table; do
			[[ $table == *" wg-quick-$INTERFACE" ]] && printf -v nftcmd '%sdelete %s\n' "$nftcmd" "$table"
		done < <(nft list tables 2>/dev/null) || true
		[[ -z $nftcmd ]] || cmd nft -f <(echo -n "$nftcmd"); wait $!
		done < <(nft list tables 2>/dev/null)
		[[ -z $nftcmd ]] || cmd nft -f <(echo -n "$nftcmd")
	fi
	if type -p iptables >/dev/null; then
		local line iptables found restore


@@ 202,7 202,7 @@ remove_firewall() {
				[[ $line == "*"* || $line == COMMIT || $line == "-A "*"-m comment --comment \"wg-quick(8) rule for $INTERFACE\""* ]] || continue
				[[ $line == "-A"* ]] && found=1
				printf -v restore '%s%s\n' "$restore" "${line/#-A/-D}"
			done < <($iptables-save 2>/dev/null) || true
			done < <($iptables-save 2>/dev/null)
			[[ $found -ne 1 ]] || echo -n "$restore" | cmd $iptables-restore -n
		done
	fi


@@ 233,22 233,22 @@ add_default() {
		[[ $line =~ .*inet6?\ ([0-9a-f:.]+)/[0-9]+.* ]] || continue
		printf -v restore '%s-I PREROUTING ! -i %s -d %s -m addrtype ! --src-type LOCAL -j DROP %s\n' "$restore" "$INTERFACE" "${BASH_REMATCH[1]}" "$marker"
		printf -v nftcmd '%sadd rule %s %s preraw iifname != "%s" %s daddr %s fib saddr type != local drop\n' "$nftcmd" "$pf" "$nftable" "$INTERFACE" "$pf" "${BASH_REMATCH[1]}"
	done < <(ip -o $proto addr show dev "$INTERFACE"); wait $!
	done < <(ip -o $proto addr show dev "$INTERFACE" 2>/dev/null)
	printf -v restore '%sCOMMIT\n*mangle\n-I POSTROUTING -m mark --mark %d -p udp -j CONNMARK --save-mark %s\n-I PREROUTING -p udp -j CONNMARK --restore-mark %s\nCOMMIT\n' "$restore" $table "$marker" "$marker"
	printf -v nftcmd '%sadd rule %s %s postmangle meta l4proto udp mark %d ct mark set mark \n' "$nftcmd" "$pf" "$nftable" $table
	printf -v nftcmd '%sadd rule %s %s premangle meta l4proto udp meta mark set ct mark \n' "$nftcmd" "$pf" "$nftable"
	[[ $proto == -4 ]] && cmd sysctl -q net.ipv4.conf.all.src_valid_mark=1
	if type -p nft >/dev/null; then
		cmd nft -f <(echo -n "$nftcmd"); wait $!
		cmd nft -f <(echo -n "$nftcmd")
	else
		echo -n "$restore" | cmd $iptables-restore -n; wait $!
		echo -n "$restore" | cmd $iptables-restore -n
	fi
	HAVE_SET_FIREWALL=1
	return 0
}

set_config() {
	cmd wg setconf "$INTERFACE" <(echo "$WG_CONFIG"); wait $!
	cmd wg setconf "$INTERFACE" <(echo "$WG_CONFIG")
}

save_config() {


@@ 260,7 260,7 @@ save_config() {
	done
	while read -r address; do
		[[ $address =~ ^nameserver\ ([a-zA-Z0-9_=+:%.-]+)$ ]] && new_config+="DNS = ${BASH_REMATCH[1]}"$'\n'
	done < <(resolvconf -l "$(resolvconf_iface_prefix)$INTERFACE" 2>/dev/null || cat "/etc/resolvconf/run/interface/$(resolvconf_iface_prefix)$INTERFACE" 2>/dev/null) || true
	done < <(resolvconf -l "$(resolvconf_iface_prefix)$INTERFACE" 2>/dev/null || cat "/etc/resolvconf/run/interface/$(resolvconf_iface_prefix)$INTERFACE" 2>/dev/null)
	[[ -n $MTU && $(ip link show dev "$INTERFACE") =~ mtu\ ([0-9]+) ]] && new_config+="MTU = ${BASH_REMATCH[1]}"$'\n'
	[[ -n $TABLE ]] && new_config+="Table = $TABLE"$'\n'
	[[ $SAVE_CONFIG -eq 0 ]] || new_config+=$'SaveConfig = true\n'


@@ 335,7 335,7 @@ cmd_up() {
	done
	set_mtu_up
	set_dns
	for i in $({ while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$INTERFACE" allowed-ips); wait $!; } | sort -nr -k 2 -t /); do
	for i in $(while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$INTERFACE" allowed-ips) | sort -nr -k 2 -t /); do
		add_route "$i"
	done
	execute_hooks "${POST_UP[@]}"

M src/wg-quick/openbsd.bash => src/wg-quick/openbsd.bash +11 -11
@@ 131,14 131,14 @@ del_routes() {
	[[ -n $REAL_INTERFACE ]] || return 0
	while read -r destination _ _ _ _ netif _; do
		[[ $netif == "$REAL_INTERFACE" ]] && todelete+=( "$destination" )
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)
	for destination in "${todelete[@]}"; do
		cmd route -q -n delete -inet "$destination" || true
	done
	todelete=( )
	while read -r destination gateway _ netif; do
		[[ $netif == "$REAL_INTERFACE" || ( $netif == lo* && $gateway == "$REAL_INTERFACE" ) ]] && todelete+=( "$destination" )
	done < <(netstat -nr -f inet6); wait $!
	done < <(netstat -nr -f inet6)
	for destination in "${todelete[@]}"; do
		cmd route -q -n delete -inet6 "$destination" || true
	done


@@ 189,9 189,9 @@ set_mtu() {
		[[ ${BASH_REMATCH[1]} == *:* ]] && family=inet6
		output="$(route -n get "-$family" "${BASH_REMATCH[1]}" || true)"
		[[ $output =~ interface:\ ([^ ]+)$'\n' && $(ifconfig "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
	done < <(wg show "$REAL_INTERFACE" endpoints); wait $!
	done < <(wg show "$REAL_INTERFACE" endpoints)
	if [[ $mtu -eq 0 ]]; then
		read -r output < <(route -n get default) || true
		read -r output < <(route -n get default || true) || true
		[[ $output =~ interface:\ ([^ ]+)$'\n' && $(ifconfig "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
	fi
	[[ $mtu -gt 0 ]] || mtu=1500


@@ 207,14 207,14 @@ collect_gateways() {
		[[ $destination == default ]] || continue
		GATEWAY4="$gateway"
		break
	done < <(netstat -nr -f inet); wait $!
	done < <(netstat -nr -f inet)

	GATEWAY6=""
	while read -r destination gateway _; do
		[[ $destination == default ]] || continue
		GATEWAY6="$gateway"
		break
	done < <(netstat -nr -f inet6); wait $!
	done < <(netstat -nr -f inet6)
}

collect_endpoints() {


@@ 222,7 222,7 @@ collect_endpoints() {
	while read -r _ endpoint; do
		[[ $endpoint =~ ^\[?([a-z0-9:.]+)\]?:[0-9]+$ ]] || continue
		ENDPOINTS+=( "${BASH_REMATCH[1]}" )
	done < <(wg show "$REAL_INTERFACE" endpoints); wait $!
	done < <(wg show "$REAL_INTERFACE" endpoints)
}

set_endpoint_direct_route() {


@@ 290,7 290,7 @@ monitor_daemon() {
		ifconfig "$REAL_INTERFACE" >/dev/null 2>&1 || break
		[[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route
		# TODO: set the mtu as well, but only if up
	done < <(route -n monitor); wait $!) & disown
	done < <(route -n monitor)) & disown
}

set_dns() {


@@ 339,7 339,7 @@ add_route() {
}

set_config() {
	cmd wg setconf "$REAL_INTERFACE" <(echo "$WG_CONFIG"); wait $!
	cmd wg setconf "$REAL_INTERFACE" <(echo "$WG_CONFIG")
}

save_config() {


@@ 347,7 347,7 @@ save_config() {
	new_config=$'[Interface]\n'
	{ read -r _; while read -r _ _ network address _; do
		[[ $network == *Link* ]] || new_config+="Address = $address"$'\n'
	done } < <(netstat -I "$REAL_INTERFACE" -n -v); wait $!
	done } < <(netstat -I "$REAL_INTERFACE" -n -v)
	# TODO: actually determine current DNS for interface
	for address in "${DNS[@]}"; do
		new_config+="DNS = $address"$'\n'


@@ 428,7 428,7 @@ cmd_up() {
	set_mtu
	up_if
	set_dns
	for i in $({ while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$REAL_INTERFACE" allowed-ips); wait $!; } | sort -nr -k 2 -t /); do
	for i in $(while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$REAL_INTERFACE" allowed-ips) | sort -nr -k 2 -t /); do
		add_route "$i"
	done
	[[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route