mirror of
https://github.com/dockur/proxmox.git
synced 2026-07-27 16:54:51 +07:00
feat: Refactor network code (#74)
This commit is contained in:
+188
-131
@@ -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
|
||||
# ######################################
|
||||
|
||||
Reference in New Issue
Block a user