101 lines
2.4 KiB
Bash
Executable file
101 lines
2.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
BASE_BRIDGE_NAME=br-q
|
|
BASE_TAP_NAME=tap-q
|
|
|
|
randstr() {
|
|
dd if=/dev/urandom count=1 bs=4 2>/dev/null | xxd -p -g 0
|
|
}
|
|
|
|
default_route() {
|
|
ip route | grep '^default' | sed -n 's/.*dev \([^ ]*\).*/\1/p'
|
|
}
|
|
|
|
find_next_subnet() {
|
|
local i
|
|
for i in {20..254}; do
|
|
if ip route | grep -q "^172\.$i\."; then
|
|
true
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
echo "172.$i"
|
|
}
|
|
|
|
create() {
|
|
local next_subnet
|
|
|
|
local bridge_name
|
|
local dhcp_subnet
|
|
local dhcp_range
|
|
local tap_name
|
|
local dnsmasq_pid
|
|
|
|
next_subnet="$(find_next_subnet)"
|
|
dhcp_subnet="$next_subnet.0.1/16"
|
|
dhcp_range="$next_subnet.0.2,$next_subnet.255.254"
|
|
|
|
bridge_name="$BASE_BRIDGE_NAME-$(randstr)"
|
|
tap_name="$BASE_TAP_NAME-$(randstr)"
|
|
|
|
echo > "$NET_CONF_FILE"
|
|
|
|
ip link add name "$bridge_name" type bridge
|
|
echo "bridge_name='$bridge_name'" >> "$NET_CONF_FILE"
|
|
ip addr add "$dhcp_subnet" dev "$bridge_name"
|
|
ip link set dev "$bridge_name" up
|
|
ip tuntap add "$tap_name" mode tap
|
|
echo "tap_name='$tap_name'" >> "$NET_CONF_FILE"
|
|
ip link set "$tap_name" up
|
|
ip link set dev "$tap_name" master "$bridge_name"
|
|
dnsmasq -k --interface="$bridge_name" --bind-interface \
|
|
--dhcp-range="$dhcp_range" &
|
|
dnsmasq_pid="$!"
|
|
echo "dnsmasq_pid='$dnsmasq_pid'" >> "$NET_CONF_FILE"
|
|
disown -h "$dnsmasq_pid"
|
|
|
|
echo "nft_ruleset='$(nft -s list ruleset)'" >> "$NET_CONF_FILE"
|
|
|
|
# dhcp
|
|
nft add rule ip filter INPUT udp dport 67 accept
|
|
nft add rule ip filter INPUT tcp dport 67 accept
|
|
# dns
|
|
nft add rule ip filter INPUT udp dport 53 accept
|
|
nft add rule ip filter INPUT tcp dport 53 accept
|
|
|
|
# forward bridge
|
|
nft add rule ip filter FORWARD iifname "$bridge_name" \
|
|
counter packets 0 bytes 0 accept
|
|
nft add rule ip filter FORWARD oifname "$bridge_name" \
|
|
counter packets 0 bytes 0 accept
|
|
nft add rule ip nat POSTROUTING oifname "$(default_route)" \
|
|
counter masquerade
|
|
}
|
|
|
|
delete() {
|
|
source "$NET_CONF_FILE"
|
|
|
|
kill "$dnsmasq_pid"
|
|
ip link del "$tap_name"
|
|
ip link del "$bridge_name"
|
|
nft flush ruleset
|
|
nft -f - <<< "$nft_ruleset"
|
|
rm "$NET_CONF_FILE"
|
|
}
|
|
|
|
if [[ -z "$NET_CONF_FILE" ]]; then
|
|
echo Please specify the configuration file path \
|
|
with NET_CONF_FILE >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "EUID" -ne 0 ]]; then
|
|
echo "Please run as root" >&2
|
|
exit 2
|
|
fi
|
|
|
|
"$@"
|