Skip to content

Commit 14aadb4

Browse files
committed
fix: handle multiple bridges and improve IP extraction for netns reuse
- Use per-bridge priority ranges (BRIDGE_PRIO_BASE) to avoid conflicts when running multiple bridges simultaneously - Extract actual IPv4/IPv6 from existing netns instead of relying on stale NET_PREFIX variables after find_free_subnet() - Change VPN/WIFI/MOBILE_PRIO to offsets instead of absolute values - Add 'from' selector to ip rule del in android_custom_routing to avoid accidentally deleting rules for other containers
1 parent b858be0 commit 14aadb4

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

nspawn

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ VERSION="1.0.1"
8989
#set -x # debug flag
9090
set -eu
9191

92-
# Android routing priority
92+
# Android routing priority offsets
9393
# Default: VPN > WiFi > Mobile data
94-
# Lower number = higher priority
95-
VPN_PRIO=7777
96-
WIFI_PRIO=8888
97-
MOBILE_PRIO=9999
94+
# Lower number = higher priority (1-3000)
95+
VPN_PRIO=100
96+
WIFI_PRIO=200
97+
MOBILE_PRIO=300
9898

9999
NET_PREFIX="10.11.0"
100100
SUBNET="/24"
@@ -304,7 +304,7 @@ add_ipt_rule() {
304304

305305
get_next_ip() {
306306
count=2
307-
for ns in "$NETNS_DIR"/$BRIDGE-*; do
307+
for ns in "$NETNS_DIR"/"$BRIDGE"-*; do
308308
[ -e "$ns" ] && count=$((count + 1))
309309
done
310310
echo "${NET_PREFIX}.${count}"
@@ -441,28 +441,28 @@ setup_android_routing() {
441441
ip -6 route replace "$BRIDGE_SUBNET6" dev "$BRIDGE" table local_network
442442

443443
# Ensure hotspot clients can reach container directly
444-
ip_rule_add local_network 6666
444+
ip_rule_add local_network "$BRIDGE_PRIO_BASE"
445445

446446
# VPN tunnels
447447
for table in $vpn; do
448-
check_ip_rule "lookup $table" && ip_rule_add "$table" "$VPN_PRIO"
448+
check_ip_rule "lookup $table" && ip_rule_add "$table" "$(($BRIDGE_PRIO_BASE + $VPN_PRIO))"
449449
done
450450

451451
# Wifi or ethernet
452452
for table in wlan0 eth0; do
453-
check_ip_rule "lookup $table" && ip_rule_add "$table" "$WIFI_PRIO"
453+
check_ip_rule "lookup $table" && ip_rule_add "$table" "$(($BRIDGE_PRIO_BASE + $WIFI_PRIO))"
454454
done
455455

456456
# Cellular
457457
for table in $cellular; do
458458
if check_ip_rule "lookup $table"; then
459-
ip_rule_add "$table" "$MOBILE_PRIO"
459+
ip_rule_add "$table" "$(($BRIDGE_PRIO_BASE + $MOBILE_PRIO))"
460460
fi
461461
done
462462

463463
# The approach above is more effective, keep this here for future reference
464464
# for iface in $vpn wlan0 eth0 $cellular; do
465-
# if check_ip_rule "lookup $interface"; then
465+
# if check_ip_rule "lookup $iface"; then
466466
# ndc ipfwd remove "$BRIDGE" "$iface" >/dev/null
467467
# ndc ipfwd add "$BRIDGE" "$iface" >/dev/null
468468
# fi
@@ -476,24 +476,30 @@ setup_android_routing() {
476476
# falls through to the next rule. Free failover, zero code.
477477
android_custom_routing() {
478478
[ -z "${ROUTE_VIA:-}" ] && return 0
479-
480479
if ! check_ip_rule "lookup $ROUTE_VIA"; then
481480
die "--route-via $ROUTE_VIA: no routing table found (interface down?)"
482481
fi
483-
484482
ct_ip4="$1"
485-
ct_ip6="${NET6_PREFIX}${ct_ip4##*.}"
486483

487-
prio=5000
488-
octet="${ct_ip4##*.}"
489-
prio=$((prio + octet))
484+
if [ -n "${CT_IP6:-}" ]; then
485+
ct_ip6="$CT_IP6"
486+
else
487+
ct_ip6="${NET6_PREFIX}${ct_ip4##*.}"
488+
fi
489+
490+
# Extract the last two octets
491+
last_two="${ct_ip4#*.*.}"
492+
third_octet="${last_two%%.*}"
493+
fourth_octet="${last_two##*.}"
490494

491-
ip rule add from "$ct_ip4" lookup "$ROUTE_VIA" priority "$prio" 2>/dev/null || true
492-
ip -6 rule add from "$ct_ip6" lookup "$ROUTE_VIA" priority "$prio" 2>/dev/null || true
495+
prio=$((5000 + (third_octet * 10) + fourth_octet))
493496

497+
ip rule del from "$ct_ip4" priority "$prio" 2>/dev/null || true
498+
ip rule add from "$ct_ip4" lookup "$ROUTE_VIA" priority "$prio"
499+
ip -6 rule del from "$ct_ip6" priority "$prio" 2>/dev/null || true
500+
ip -6 rule add from "$ct_ip6" lookup "$ROUTE_VIA" priority "$prio"
494501
mkdir -p "$RT_DIR"
495502
echo "$prio $ct_ip4 $ct_ip6 $ROUTE_VIA" >> "$RT_DIR/custom_routes"
496-
497503
info "Routing $ct_ip4 ($ct_ip6) via $ROUTE_VIA"
498504
}
499505

@@ -597,8 +603,8 @@ if [ "${USE_NETNS:-}" = "1" ]; then
597603
fi
598604

599605
HASH_TOOL=$(command -v md5sum || echo cksum)
600-
601606
BRIDGE_HASH=$(printf '%s' "$BRIDGE" | $HASH_TOOL | awk '{print $1}')
607+
BRIDGE_PRIO_BASE=$((6000 + 0x${BRIDGE_HASH%%????????????????????????} % 1000))
602608
NETNS_NAME="$BRIDGE-$(printf '%s' "$BRIDGE_HASH$ROOTFS" | $HASH_TOOL | awk '{print substr($1,1,8)}')"
603609
VETH_NAME="$(printf '%s' "$BRIDGE_HASH$NETNS_NAME" | $HASH_TOOL | awk '{print substr($1,1,8)}')"
604610

@@ -619,8 +625,12 @@ if [ "${USE_NETNS:-}" = "1" ]; then
619625
[ "${ANDROID:-}" = "1" ] && setup_android_routing
620626

621627
if [ -e "$NETNS_DIR/$NETNS_NAME" ]; then
622-
CT_IP=$(ip netns exec "$NETNS_NAME" ip addr show "eth0_${VETH_NAME}" 2>/dev/null | \
623-
grep -oE "${NET_PREFIX}\.[0-9]+" | head -1)
628+
CT_IP=$(ip netns exec "$NETNS_NAME" ip -4 addr show "eth0_${VETH_NAME}" 2>/dev/null | \
629+
awk '/inet / {print $2}' | cut -d/ -f1 | head -1)
630+
631+
CT_IP6=$(ip netns exec "$NETNS_NAME" ip -6 addr show "eth0_${VETH_NAME}" 2>/dev/null | \
632+
awk '/inet6 / && !/fe80/ {print $2}' | cut -d/ -f1 | head -1)
633+
624634
[ -z "$CT_IP" ] && CT_IP=$(get_next_ip)
625635
else
626636
CT_IP=$(get_next_ip)

0 commit comments

Comments
 (0)