Refactor cleanup process in iptables setup script for improved robustness and clarity

This commit is contained in:
2025-12-27 16:53:07 +03:00
parent fed8153553
commit 54296bf161

View File

@@ -5,12 +5,11 @@ set -euo pipefail
# Config # Config
# ---------------------------- # ----------------------------
MIHOMO_UID="mihomo" MIHOMO_UID="mihomo"
REDIR_PORT="7892" # mihomo redir-port (NAT REDIRECT for TCP) REDIR_PORT="7892" # TCP Redirect
TPROXY_PORT="7893" # mihomo tproxy-port (TPROXY for TCP/UDP) TPROXY_PORT="7893" # UDP/TCP TProxy
FW_MARK="0x1" FW_MARK="0x1"
ROUTE_TABLE="100" ROUTE_TABLE="100"
# Interfaces to EXCLUDE completely from interception
EXCLUDE_IFACES=("tun0" "wg0") EXCLUDE_IFACES=("tun0" "wg0")
# ---------------------------- # ----------------------------
@@ -18,131 +17,115 @@ EXCLUDE_IFACES=("tun0" "wg0")
# ---------------------------- # ----------------------------
ipt() { iptables "$@"; } ipt() { iptables "$@"; }
# Функция для удаления правил по комментарию # Надежная функция удаления: Пытается удалить правило, пока iptables не скажет "нет такого правила"
cleanup_rules() { # $1=table, $2=chain, $3=args (часть правила для матчинга)
local table="$1" del_loop() {
local chain="$2" local table=$1
local comment="$3" local chain=$2
shift 2
# Добавлено "|| true" к grep, чтобы скрипт не падал, если правил нет (пустой grep возвращает 1) local rule_args="$@"
iptables -t "$table" -nL "$chain" --line-numbers 2>/dev/null | \
grep "$comment" || true | \ # Пока проверка (-C) успешна, делаем удаление (-D)
sort -r | \ while iptables -t "$table" -C "$chain" $rule_args 2>/dev/null; do
awk '{print $1}' | \ echo "Deleting from $table/$chain: $rule_args"
while read -r line; do iptables -t "$table" -D "$chain" $rule_args
# Проверка на пустую строку, на случай если grep ничего не нашел
if [[ -n "$line" ]]; then
echo "Deleting rule $line from $table/$chain..."
iptables -t "$table" -D "$chain" "$line"
fi
done done
} }
ensure_ip_rule() { ensure_ip_rule() {
# Clean up ip rules first
while ip rule list | grep -q "fwmark ${FW_MARK} lookup ${ROUTE_TABLE}"; do while ip rule list | grep -q "fwmark ${FW_MARK} lookup ${ROUTE_TABLE}"; do
ip rule del fwmark ${FW_MARK} lookup ${ROUTE_TABLE} || true ip rule del fwmark ${FW_MARK} lookup ${ROUTE_TABLE} || true
done done
ip rule add fwmark ${FW_MARK} lookup ${ROUTE_TABLE} ip rule add fwmark ${FW_MARK} lookup ${ROUTE_TABLE}
# Route table entry, forced
ip route replace local 0.0.0.0/0 dev lo table ${ROUTE_TABLE} ip route replace local 0.0.0.0/0 dev lo table ${ROUTE_TABLE}
} }
# ---------------------------- # ----------------------------
# CLEANUP PHASE # CLEANUP PHASE
# ---------------------------- # ----------------------------
echo "Cleaning up old rules..." echo "--- Cleaning up old rules (Robust Mode) ---"
# 1. Clean MANGLE references # 1. Удаляем ссылки (JUMP) на наши цепочки
cleanup_rules mangle OUTPUT "MIHOMO-MARK" del_loop nat OUTPUT -p tcp -m comment --comment "MIHOMO-JUMP" -j MIHOMO_REDIR
cleanup_rules mangle OUTPUT "MIHOMO-EXCLUDE" del_loop nat PREROUTING -i wt0 -p tcp -m comment --comment "MIHOMO-REDIRECT" -j REDIRECT --to-port "${REDIR_PORT}"
cleanup_rules mangle PREROUTING "MIHOMO-JUMP" del_loop mangle PREROUTING -i wt0 -m comment --comment "MIHOMO-JUMP" -j MIHOMO_TPROXY
cleanup_rules mangle PREROUTING "MIHOMO-EXCLUDE"
# 2. Clean NAT references # 2. Удаляем исключения (EXCLUDE) и маркеры (MARK)
cleanup_rules nat OUTPUT "MIHOMO-JUMP" # Mangle OUTPUT
cleanup_rules nat OUTPUT "MIHOMO-EXCLUDE" del_loop mangle OUTPUT -p tcp -m comment --comment "MIHOMO-MARK" -j MARK --set-mark "${FW_MARK}"
cleanup_rules nat PREROUTING "MIHOMO-REDIRECT" del_loop mangle OUTPUT -p udp -m comment --comment "MIHOMO-MARK" -j MARK --set-mark "${FW_MARK}"
# 3. Flush and Delete Chains for IFACE in "${EXCLUDE_IFACES[@]}"; do
del_loop mangle OUTPUT -o "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
del_loop mangle PREROUTING -i "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
del_loop nat OUTPUT -o "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
done
del_loop mangle OUTPUT -m owner --uid-owner "${MIHOMO_UID}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
del_loop nat OUTPUT -m owner --uid-owner "${MIHOMO_UID}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
# 3. Теперь, когда ссылок нет, можно безопасно удалить цепочки
# Сначала сбрасываем содержимое (-F), потом удаляем саму цепочку (-X)
ipt -t mangle -F MIHOMO_TPROXY 2>/dev/null || true ipt -t mangle -F MIHOMO_TPROXY 2>/dev/null || true
ipt -t mangle -X MIHOMO_TPROXY 2>/dev/null || true ipt -t mangle -X MIHOMO_TPROXY 2>/dev/null || true
ipt -t nat -F MIHOMO_REDIR 2>/dev/null || true ipt -t nat -F MIHOMO_REDIR 2>/dev/null || true
ipt -t nat -X MIHOMO_REDIR 2>/dev/null || true ipt -t nat -X MIHOMO_REDIR 2>/dev/null || true
# ---------------------------- echo "--- Cleanup finished. Applying new rules ---"
# NAT (REDIRECT) part (TCP only)
# ----------------------------
echo "Applying NAT rules..."
# ----------------------------
# NAT (REDIRECT) - TCP
# ----------------------------
ipt -t nat -N MIHOMO_REDIR ipt -t nat -N MIHOMO_REDIR
# Exclude private networks # Local exclusions inside chain
ipt -t nat -A MIHOMO_REDIR -d 192.168.0.0/16 -j RETURN ipt -t nat -A MIHOMO_REDIR -d 192.168.0.0/16 -j RETURN
ipt -t nat -A MIHOMO_REDIR -d 10.0.0.0/8 -j RETURN ipt -t nat -A MIHOMO_REDIR -d 10.0.0.0/8 -j RETURN
ipt -t nat -A MIHOMO_REDIR -d 172.16.0.0/12 -j RETURN ipt -t nat -A MIHOMO_REDIR -d 172.16.0.0/12 -j RETURN
ipt -t nat -A MIHOMO_REDIR -d 127.0.0.0/8 -j RETURN ipt -t nat -A MIHOMO_REDIR -d 127.0.0.0/8 -j RETURN
# Everything else TCP -> REDIRECT
ipt -t nat -A MIHOMO_REDIR -p tcp -j REDIRECT --to-ports "${REDIR_PORT}" ipt -t nat -A MIHOMO_REDIR -p tcp -j REDIRECT --to-ports "${REDIR_PORT}"
# --- APPLY TO OUTPUT (Local Traffic) --- # Apply to OUTPUT (Local)
# Exclude traffic going via tunnels (tun0/wg0)
for IFACE in "${EXCLUDE_IFACES[@]}"; do for IFACE in "${EXCLUDE_IFACES[@]}"; do
ipt -t nat -A OUTPUT -o "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN ipt -t nat -A OUTPUT -o "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
done done
# Exclude mihomo user
ipt -t nat -A OUTPUT -m owner --uid-owner "${MIHOMO_UID}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN ipt -t nat -A OUTPUT -m owner --uid-owner "${MIHOMO_UID}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
# Redirect remaining TCP
ipt -t nat -A OUTPUT -p tcp -m comment --comment "MIHOMO-JUMP" -j MIHOMO_REDIR ipt -t nat -A OUTPUT -p tcp -m comment --comment "MIHOMO-JUMP" -j MIHOMO_REDIR
# --- APPLY TO INGRESS (wt0) --- # Apply to PREROUTING (wt0 Ingress) - Force Redir
ipt -t nat -A PREROUTING -i wt0 -p tcp -m comment --comment "MIHOMO-REDIRECT" -j REDIRECT --to-port "${REDIR_PORT}" ipt -t nat -A PREROUTING -i wt0 -p tcp -m comment --comment "MIHOMO-REDIRECT" -j REDIRECT --to-port "${REDIR_PORT}"
# ---------------------------- # ----------------------------
# MANGLE (TPROXY) part (TCP+UDP) # MANGLE (TPROXY) - UDP/TCP
# ---------------------------- # ----------------------------
echo "Applying TPROXY rules..."
ensure_ip_rule ensure_ip_rule
ipt -t mangle -N MIHOMO_TPROXY ipt -t mangle -N MIHOMO_TPROXY
# Exclude private networks # Local exclusions inside chain
ipt -t mangle -A MIHOMO_TPROXY -d 192.168.0.0/16 -j RETURN ipt -t mangle -A MIHOMO_TPROXY -d 192.168.0.0/16 -j RETURN
ipt -t mangle -A MIHOMO_TPROXY -d 10.0.0.0/8 -j RETURN ipt -t mangle -A MIHOMO_TPROXY -d 10.0.0.0/8 -j RETURN
ipt -t mangle -A MIHOMO_TPROXY -d 172.16.0.0/12 -j RETURN ipt -t mangle -A MIHOMO_TPROXY -d 172.16.0.0/12 -j RETURN
ipt -t mangle -A MIHOMO_TPROXY -d 127.0.0.0/8 -j RETURN ipt -t mangle -A MIHOMO_TPROXY -d 127.0.0.0/8 -j RETURN
# TPROXY Target # TProxy Targets
ipt -t mangle -A MIHOMO_TPROXY -p tcp -j TPROXY --on-port "${TPROXY_PORT}" --tproxy-mark "${FW_MARK}/${FW_MARK}" ipt -t mangle -A MIHOMO_TPROXY -p tcp -j TPROXY --on-port "${TPROXY_PORT}" --tproxy-mark "${FW_MARK}/${FW_MARK}"
ipt -t mangle -A MIHOMO_TPROXY -p udp -j TPROXY --on-port "${TPROXY_PORT}" --tproxy-mark "${FW_MARK}/${FW_MARK}" ipt -t mangle -A MIHOMO_TPROXY -p udp -j TPROXY --on-port "${TPROXY_PORT}" --tproxy-mark "${FW_MARK}/${FW_MARK}"
# --- APPLY TO OUTPUT (Local Traffic) --- # Apply to OUTPUT (Local)
# Exclude tunnels
for IFACE in "${EXCLUDE_IFACES[@]}"; do for IFACE in "${EXCLUDE_IFACES[@]}"; do
ipt -t mangle -A OUTPUT -o "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN ipt -t mangle -A OUTPUT -o "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
done done
# Exclude mihomo user
ipt -t mangle -A OUTPUT -m owner --uid-owner "${MIHOMO_UID}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN ipt -t mangle -A OUTPUT -m owner --uid-owner "${MIHOMO_UID}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
# Mark remaining traffic for Policy Routing # Mark packets
ipt -t mangle -A OUTPUT -p tcp -m comment --comment "MIHOMO-MARK" -j MARK --set-mark "${FW_MARK}" ipt -t mangle -A OUTPUT -p tcp -m comment --comment "MIHOMO-MARK" -j MARK --set-mark "${FW_MARK}"
ipt -t mangle -A OUTPUT -p udp -m comment --comment "MIHOMO-MARK" -j MARK --set-mark "${FW_MARK}" ipt -t mangle -A OUTPUT -p udp -m comment --comment "MIHOMO-MARK" -j MARK --set-mark "${FW_MARK}"
# --- APPLY TO INGRESS (wt0) --- # Apply to PREROUTING (wt0 Ingress)
# Exclude tunnels (ingress logic)
for IFACE in "${EXCLUDE_IFACES[@]}"; do for IFACE in "${EXCLUDE_IFACES[@]}"; do
ipt -t mangle -A PREROUTING -i "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN ipt -t mangle -A PREROUTING -i "${IFACE}" -m comment --comment "MIHOMO-EXCLUDE" -j RETURN
done done
# Jump wt0 traffic to TPROXY chain
ipt -t mangle -A PREROUTING -i wt0 -m comment --comment "MIHOMO-JUMP" -j MIHOMO_TPROXY ipt -t mangle -A PREROUTING -i wt0 -m comment --comment "MIHOMO-JUMP" -j MIHOMO_TPROXY
echo "Done." echo "Done."