mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2026-08-28 11:56:03 +00:00
feat: Improve NAT networking (#1300)
This commit is contained in:
+89
-12
@@ -325,10 +325,9 @@ natGuestIP() {
|
||||
|
||||
local ip="$1"
|
||||
local start="" guest="" subnet=""
|
||||
local second="" third="" fourth="" rc=""
|
||||
local second="" third="" rc=""
|
||||
|
||||
third=$(cut -d. -f3 <<< "$ip")
|
||||
fourth=$(cut -d. -f4 <<< "$ip")
|
||||
|
||||
if [[ "$ip" == "172.30."* ]]; then
|
||||
start="31"
|
||||
@@ -336,11 +335,8 @@ natGuestIP() {
|
||||
start="30"
|
||||
fi
|
||||
|
||||
guest=$(guestIP "172.$start.$third.$fourth" 2)
|
||||
fourth="${guest##*.}"
|
||||
|
||||
for (( second=start; second<=254; second++ )); do
|
||||
guest="172.$second.$third.$fourth"
|
||||
guest=$(guestIP "172.$second.$third.0" 2)
|
||||
subnet=$(networkCIDR "$guest") || return 1
|
||||
|
||||
if subnetInUse "$subnet"; then
|
||||
@@ -355,7 +351,7 @@ natGuestIP() {
|
||||
done
|
||||
|
||||
for (( second=30; second<start; second++ )); do
|
||||
guest="172.$second.$third.$fourth"
|
||||
guest=$(guestIP "172.$second.$third.0" 2)
|
||||
subnet=$(networkCIDR "$guest") || return 1
|
||||
|
||||
if subnetInUse "$subnet"; then
|
||||
@@ -1031,13 +1027,16 @@ checkExistingTables() {
|
||||
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
||||
|
||||
rules=$(
|
||||
iptables -t nat -S PREROUTING 2>/dev/null |
|
||||
{
|
||||
iptables -t nat -S PREROUTING 2>/dev/null || true
|
||||
iptables -t nat -S OUTPUT 2>/dev/null || true
|
||||
} |
|
||||
awk '$1 == "-A"' |
|
||||
grep -Ev -- "$own_rule" || true
|
||||
)
|
||||
|
||||
conflicts=$(grep -E -- \
|
||||
'^-A PREROUTING .*(-j DNAT|-j REDIRECT)( |$)' \
|
||||
'^-A (PREROUTING|OUTPUT) .*(-j DNAT|-j REDIRECT)( |$)' \
|
||||
<<< "$rules" || true)
|
||||
|
||||
if [ -n "$conflicts" ]; then
|
||||
@@ -1071,6 +1070,7 @@ checkExistingTables() {
|
||||
fi
|
||||
|
||||
showRules nat PREROUTING "NAT PREROUTING" "$rule_tag"
|
||||
showRules nat OUTPUT "NAT OUTPUT" "$rule_tag"
|
||||
showRules filter FORWARD "filter FORWARD" "$rule_tag"
|
||||
showRules nat POSTROUTING "NAT POSTROUTING" "$rule_tag"
|
||||
|
||||
@@ -1217,6 +1217,17 @@ applyTables() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Process locally generated traffic addressed to the container uplink.
|
||||
if ! runTableRule "$silent" table_error \
|
||||
iptables -t nat -A OUTPUT \
|
||||
-d "$UPLINK" \
|
||||
-m addrtype --dst-type LOCAL \
|
||||
-m comment --comment "$rule_tag" \
|
||||
-j "$dnat_chain"; then
|
||||
tableError "$silent" "$table_error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Hack for guest VMs complaining about "bad udp checksums in 5 packets".
|
||||
runTableRule "Y" table_error \
|
||||
iptables -t mangle -A POSTROUTING \
|
||||
@@ -1369,12 +1380,34 @@ clearTables() {
|
||||
return 0
|
||||
}
|
||||
|
||||
hasTaggedRules() {
|
||||
|
||||
local save="$1"
|
||||
local rules=""
|
||||
local dnat_chain="QEMU_DNAT"
|
||||
local rule_tag="$dnat_chain"
|
||||
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
||||
local tagged_rule="^:${dnat_chain}[[:space:]]|$own_rule"
|
||||
|
||||
# Return 2 when the backend cannot be inspected.
|
||||
if ! rules=$("$save" 2>/dev/null); then
|
||||
return 2
|
||||
fi
|
||||
|
||||
if grep -Eq -- "$tagged_rule" <<< "$rules"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
configureTables() {
|
||||
|
||||
local ip="$1"
|
||||
local subnet="$2"
|
||||
local preferred=""
|
||||
local alternate="" rc=0
|
||||
local alternate=""
|
||||
local alternate_save=""
|
||||
local preferred_clean="N"
|
||||
local alternate_dirty="N"
|
||||
|
||||
@@ -1393,6 +1426,50 @@ configureTables() {
|
||||
return 1 ;;
|
||||
esac
|
||||
|
||||
# Inspect the alternate backend without changing the active alternative.
|
||||
alternate_save=$(command -v "iptables-$alternate-save" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$alternate_save" ]; then
|
||||
|
||||
if hasTaggedRules "$alternate_save"; then
|
||||
|
||||
# Only switch backends when stale QEMU rules were positively found.
|
||||
if ! setTables "$alternate"; then
|
||||
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
||||
warn "failed to select the $alternate IP tables backend for cleanup!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! clearTables; then
|
||||
alternate_dirty="Y"
|
||||
fi
|
||||
|
||||
# Always restore the originally selected backend after cleanup.
|
||||
if ! setTables "$preferred"; then
|
||||
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
||||
warn "failed to restore the preferred $preferred IP tables backend!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if enabled "$alternate_dirty"; then
|
||||
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
||||
warn "failed to clean up the existing $alternate IP tables configuration!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
local rc=$?
|
||||
|
||||
# An unavailable alternate backend does not affect normal startup.
|
||||
if (( rc == 2 )) && enabled "$DEBUG"; then
|
||||
warn "failed to inspect the $alternate IP tables backend!"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# Try the preferred backend first.
|
||||
if clearTables; then
|
||||
|
||||
@@ -1413,7 +1490,7 @@ configureTables() {
|
||||
|
||||
else
|
||||
|
||||
rc=$?
|
||||
local rc=$?
|
||||
|
||||
# The preferred backend was accessible, but its rules could not be removed.
|
||||
# Do not switch while partial or stale rules may still be active.
|
||||
@@ -1460,7 +1537,7 @@ configureTables() {
|
||||
|
||||
else
|
||||
|
||||
rc=$?
|
||||
local rc=$?
|
||||
|
||||
# Only mark the alternate backend dirty when it was accessible but cleanup failed.
|
||||
if (( rc == 1 )); then
|
||||
|
||||
Reference in New Issue
Block a user