feat: Refactor network code (#74)

This commit is contained in:
Kroese
2026-07-05 19:58:54 +02:00
committed by GitHub
parent 8748bbbfac
commit 0a776f9465
+188 -131
View File
@@ -13,9 +13,19 @@ set -Eeuo pipefail
ADD_ERR="Please add the following setting to your container:"
# ######################################
# Functions
# Generic helpers
# ######################################
isNAT() {
case "${NETWORK,,}" in
"tap" | "tun" | "tuntap" | "y" | "" )
return 0 ;;
*)
return 1 ;;
esac
}
getMTU() {
local dev="$1"
@@ -74,6 +84,10 @@ disableIPv6() {
return 0
}
# ######################################
# DNS / interface helpers
# ######################################
configureDNS() {
local fa="$1"
@@ -92,7 +106,7 @@ configureDNS() {
fi
# Avoid returning IPv6 records when the active network mode is IPv4-only.
if [[ "${NETWORK,,}" == "tap" || "${NETWORK,,}" == "tun" || "${NETWORK,,}" == "tuntap" || "${NETWORK,,}" == "y" || -z "$IP6" ]]; then
if isNAT || [ -z "$IP6" ]; then
filter_dns="filter-AAAA"
fi
@@ -189,38 +203,129 @@ EOF
return 0
}
clearTables() {
local table="" line rules
# ######################################
# Network mode setup
# ######################################
# Choose between iptables or nftables
if command -v iptables-nft >/dev/null 2>&1 && iptables-nft -V >/dev/null 2>&1; then
update-alternatives --set iptables /usr/sbin/iptables-nft > /dev/null
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft > /dev/null
else
update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null
createBridge() {
local gateway="$1"
local broadcast="$2"
local rc
# Create a bridge with a static IP for the VM LAN
{ ip link add dev "$BRIDGE" type bridge; rc=$?; } || :
if (( rc != 0 )); then
error "failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
fi
# Store the current iptables ruleset
! rules=$(iptables-save 2> /dev/null) && return 0
[ -z "$rules" ] && return 0
if [[ "$LAN_MTU" != "0" ]]; then
setMTU "$BRIDGE" "$LAN_MTU"
fi
# Delete every rule tagged with our unique identifier, leaving all other rules intact.
while IFS= read -r line; do
case "$line" in
\*nat) table="nat" ;;
\*filter) table="filter" ;;
\*mangle) table="mangle" ;;
\*raw) table="raw" ;;
esac
if [[ "$line" == -A* ]]; then
local re="--comment[[:space:]]+\"?remove\"?([[:space:]]|\$)"
if [[ "$line" =~ $re ]]; then
read -ra args <<< "${line/-A /-D }"
iptables -t "$table" "${args[@]}" &> /dev/null || :
fi
fi
done <<< "$rules"
if ! ip address add "$gateway/24" broadcast "$broadcast" dev "$BRIDGE"; then
error "failed to add IP address pool!" && return 1
fi
while ! ip link set "$BRIDGE" up; do
info "Waiting for IP address to become available..."
sleep 2
done
# NAT networking is IPv4-only; disable IPv6 on the VM bridge if possible.
disableIPv6 "$BRIDGE"
return 0
}
createTap() {
local tuntap="$1"
# Set tap to the bridge created
if ! ip tuntap add dev "$TAP" mode tap; then
error "$tuntap" && return 1
fi
if [[ "$LAN_MTU" != "0" ]]; then
setMTU "$TAP" "$LAN_MTU"
fi
if ! ip link set dev "$TAP" address "$GATEWAY_MAC"; then
warn "failed to set gateway MAC address."
fi
while ! ip link set "$TAP" up promisc on; do
info "Waiting for TAP to become available..."
sleep 2
done
# NAT networking is IPv4-only; disable IPv6 on the VM tap if possible.
disableIPv6 "$TAP"
if ! ip link set dev "$TAP" master "$BRIDGE"; then
error "failed to set master bridge!" && return 1
fi
return 0
}
configureTables() {
local subnet="$1"
local rule_tag="remove"
local tables_err="failed to configure IP tables!"
local tables="the 'ip_tables' kernel module is not loaded. Try this command: sudo modprobe ip_tables iptable_nat"
clearTables
# NAT traffic from bridge subnet to Docker uplink
if ! iptables -t nat -A POSTROUTING \
-o "$DEV" \
-s "$subnet" \
! -d "$subnet" \
-m comment --comment "$rule_tag" \
-j MASQUERADE; then
error "$tables" && return 1
fi
if (( KERNEL > 4 )); then
# Hack for guest VMs complaining about "bad udp checksums in 5 packets"
iptables -t mangle -A POSTROUTING \
-s "$subnet" \
-p udp \
--dport bootpc \
-m comment --comment "$rule_tag" \
-j CHECKSUM --checksum-fill > /dev/null 2>&1 || true
fi
# Clamp TCP MSS to avoid subtle MTU blackholes when the outer path has a smaller MTU.
iptables -t mangle -A FORWARD \
-s "$subnet" \
-p tcp \
--tcp-flags SYN,RST SYN \
-m comment --comment "$rule_tag" \
-j TCPMSS --clamp-mss-to-pmtu > /dev/null 2>&1 || true
# Allow outbound traffic from the Proxmox VM subnet to the Docker uplink.
if ! iptables -A FORWARD \
-s "$subnet" \
-o "$DEV" \
-m comment --comment "$rule_tag" \
-j ACCEPT; then
error "$tables_err" && return 1
fi
# Allow return traffic from the Docker uplink back to the Proxmox VM subnet.
if ! iptables -A FORWARD \
-d "$subnet" \
-i "$DEV" \
-m conntrack --ctstate RELATED,ESTABLISHED \
-m comment --comment "$rule_tag" \
-j ACCEPT; then
error "$tables_err" && return 1
fi
return 0
}
@@ -228,7 +333,7 @@ clearTables() {
configureNAT() {
local tuntap="TUN device is missing. $ADD_ERR --device /dev/net/tun"
local tables="the 'ip_tables' kernel module is not loaded. Try this command: sudo modprobe ip_tables iptable_nat"
local rc
[[ "$DEBUG" == [Yy1]* ]] && echo "Configuring NAT networking..."
@@ -270,108 +375,15 @@ configureNAT() {
local subnet="${ip%.*}.0/24"
local broadcast="${ip%.*}.255"
# Create a bridge with a static IP for the VM LAN
{ ip link add dev "$BRIDGE" type bridge; rc=$?; } || :
if (( rc != 0 )); then
error "failed to create bridge. $ADD_ERR --cap-add NET_ADMIN" && return 1
fi
if [[ "$LAN_MTU" != "0" ]]; then
setMTU "$BRIDGE" "$LAN_MTU"
fi
if ! ip address add "$gateway/24" broadcast "$broadcast" dev "$BRIDGE"; then
error "failed to add IP address pool!" && return 1
fi
while ! ip link set "$BRIDGE" up; do
info "Waiting for IP address to become available..."
sleep 2
done
# NAT networking is IPv4-only; disable IPv6 on the VM bridge if possible.
disableIPv6 "$BRIDGE"
# Set tap to the bridge created
if ! ip tuntap add dev "$TAP" mode tap; then
error "$tuntap" && return 1
fi
if [[ "$LAN_MTU" != "0" ]]; then
setMTU "$TAP" "$LAN_MTU"
fi
if ! ip link set dev "$TAP" address "$GATEWAY_MAC"; then
warn "failed to set gateway MAC address."
fi
while ! ip link set "$TAP" up promisc on; do
info "Waiting for TAP to become available..."
sleep 2
done
# NAT networking is IPv4-only; disable IPv6 on the VM tap if possible.
disableIPv6 "$TAP"
if ! ip link set dev "$TAP" master "$BRIDGE"; then
error "failed to set master bridge!" && return 1
fi
createBridge "$gateway" "$broadcast" || return 1
createTap "$tuntap" || return 1
# Use the lowest effective VM-LAN MTU, without mutating the parent/uplink MTU.
if [[ "$LAN_MTU" != "0" ]]; then
LAN_MTU=$(minMTU "$LAN_MTU" "$(getMTU "$BRIDGE")" "$(getMTU "$TAP")")
fi
# Flush existing tables
clearTables
# NAT traffic from bridge subnet to Docker uplink
if ! iptables -t nat -A POSTROUTING \
-o "$DEV" \
-s "$subnet" \
! -d "$subnet" \
-m comment --comment "remove" \
-j MASQUERADE; then
error "$tables" && return 1
fi
if (( KERNEL > 4 )); then
# Hack for guest VMs complaining about "bad udp checksums in 5 packets"
iptables -t mangle -A POSTROUTING \
-s "$subnet" \
-p udp \
--dport bootpc \
-m comment --comment "remove" \
-j CHECKSUM --checksum-fill > /dev/null 2>&1 || true
fi
# Clamp TCP MSS to avoid subtle MTU blackholes when the outer path has a smaller MTU.
iptables -t mangle -A FORWARD \
-s "$subnet" \
-p tcp \
--tcp-flags SYN,RST SYN \
-m comment --comment "remove" \
-j TCPMSS --clamp-mss-to-pmtu > /dev/null 2>&1 || true
# Allow outbound traffic from the Proxmox VM subnet to the Docker uplink.
if ! iptables -A FORWARD \
-s "$subnet" \
-o "$DEV" \
-m comment --comment "remove" \
-j ACCEPT; then
error "failed to configure IP tables!" && return 1
fi
# Allow return traffic from the Docker uplink back to the Proxmox VM subnet.
if ! iptables -A FORWARD \
-d "$subnet" \
-i "$DEV" \
-m conntrack --ctstate RELATED,ESTABLISHED \
-m comment --comment "remove" \
-j ACCEPT; then
error "failed to configure IP tables!" && return 1
fi
configureTables "$subnet" || return 1
setInterfaces "$BRIDGE" "$TAP" "$gateway" || return 1
configureDNS "$BRIDGE" "$ip" "$MASK" "$gateway" || return 1
@@ -379,11 +391,43 @@ configureNAT() {
return 0
}
blockLicense() {
# ######################################
# Cleanup
# ######################################
# Block connection attempts to license server
sed -i -E '/^[[:space:]]*[^#]*[[:space:]]shop\.maurer-it\.com([[:space:]]|$)/d' /etc/hosts 2>/dev/null || true
printf '%s\n' '127.0.0.1 shop.maurer-it.com' '::1 shop.maurer-it.com' >> /etc/hosts 2>/dev/null || true
clearTables() {
local table="" line rules
local rule_tag="remove"
local re="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
# Choose between iptables or nftables
if command -v iptables-nft >/dev/null 2>&1 && iptables-nft -V >/dev/null 2>&1; then
update-alternatives --set iptables /usr/sbin/iptables-nft > /dev/null
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft > /dev/null
else
update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null
fi
# Store the current iptables ruleset
! rules=$(iptables-save 2> /dev/null) && return 0
[ -z "$rules" ] && return 0
# Delete every rule tagged with our unique identifier, leaving all other rules intact.
while IFS= read -r line; do
case "$line" in
\*nat) table="nat" ;;
\*filter) table="filter" ;;
\*mangle) table="mangle" ;;
\*raw) table="raw" ;;
esac
if [[ "$line" == -A* ]]; then
if [[ "$line" =~ $re ]]; then
read -ra args <<< "${line/-A /-D }"
iptables -t "$table" "${args[@]}" &> /dev/null || :
fi
fi
done <<< "$rules"
return 0
}
@@ -400,6 +444,10 @@ closeBridge() {
return 0
}
# ######################################
# Detection
# ######################################
getInfo() {
if [ -z "$DEV" ]; then
@@ -479,6 +527,15 @@ getInfo() {
return 0
}
blockLicense() {
# Block connection attempts to license server
sed -i -E '/^[[:space:]]*[^#]*[[:space:]]shop\.maurer-it\.com([[:space:]]|$)/d' /etc/hosts 2>/dev/null || true
printf '%s\n' '127.0.0.1 shop.maurer-it.com' '::1 shop.maurer-it.com' >> /etc/hosts 2>/dev/null || true
return 0
}
# ######################################
# Configure Network
# ######################################