iptables save/restore, attempting to fix connectivity if container restarts
Continuous Integration / docker (push) Failing after 13s

This commit is contained in:
Joe Roback
2025-11-18 07:46:50 -07:00
parent a961f64948
commit 3e4004e6b1
+44 -26
View File
@@ -2,15 +2,25 @@
set -o errexit set -o errexit
info() {
printf "I %5d %s\n" "${$}" "${*}"
}
fatal() {
printf "F %5d %s\n" "${$}" "${*}" >&2
exit 1
}
iptables-save | tee /tmp/rules.v4.$$.conf
ip6tables-save | tee /tmp/rules.v6.$$.conf
default_route_ip=$(ip route | grep '^default' | awk '{print $3}') default_route_ip=$(ip route | grep '^default' | awk '{print $3}')
if [[ -z "${default_route_ip}" ]]; then if [[ -z "${default_route_ip}" ]]; then
echo "Error: No default route configured" >&2 fatal "Error: No default route configured"
exit 1
fi fi
if [[ "$(cat /proc/sys/net/ipv4/conf/all/src_valid_mark)" != "1" ]]; then if [[ "$(cat /proc/sys/net/ipv4/conf/all/src_valid_mark)" != "1" ]]; then
echo "Error: sysctl net.ipv4.conf.all.src_valid_mark=1 is not set" >&2 fatal "Error: sysctl net.ipv4.conf.all.src_valid_mark=1 is not set"
exit 1
fi fi
# sysctl is set by container, wg-quick will then error # sysctl is set by container, wg-quick will then error
@@ -19,19 +29,21 @@ sed -i "s:sysctl -q net.ipv4.conf.all.src_valid_mark=1:echo Skipping setting net
WIREGUARD_INTERFACE="${WIREGUARD_INTERFACE:-wg0}" WIREGUARD_INTERFACE="${WIREGUARD_INTERFACE:-wg0}"
if [ ! -f "/etc/wireguard/${WIREGUARD_INTERFACE}.conf" ]; then if [ ! -f "/etc/wireguard/${WIREGUARD_INTERFACE}.conf" ]; then
echo "Error: Configuration file /etc/wireguard/${WIREGUARD_INTERFACE}.conf does not exist" >&2 fatal "Error: Configuration file /etc/wireguard/${WIREGUARD_INTERFACE}.conf does not exist"
exit 1
fi fi
echo "Bringing up wireguard interface: ${WIREGUARD_INTERFACE}..." info "Bringing up wireguard interface: ${WIREGUARD_INTERFACE}..."
wg-quick up ${WIREGUARD_INTERFACE} wg-quick up ${WIREGUARD_INTERFACE}
shutdown () { shutdown () {
info "shutting down wireguard interface: ${WIREGUARD_INTERFACE}..."
wg-quick down ${WIREGUARD_INTERFACE} wg-quick down ${WIREGUARD_INTERFACE}
exit 0 info "restoring iptables..."
iptables-restore -n < /tmp/rules.v4.$$.conf
info "restoring ip6tables..."
ip6tables-restore -n < /tmp/rules.v6.$$.conf
} }
trap shutdown EXIT
trap shutdown SIGTERM SIGINT SIGQUIT
wg show wg show
WIREGUARD_FWMARK=$(wg show ${WIREGUARD_INTERFACE} fwmark) WIREGUARD_FWMARK=$(wg show ${WIREGUARD_INTERFACE} fwmark)
@@ -39,37 +51,40 @@ WIREGUARD_FWMARK=$(wg show ${WIREGUARD_INTERFACE} fwmark)
# allow connections from container subnets # allow connections from container subnets
for container_subnet in $(ip -o addr show | awk '/^(\d)+: eth(.+)inet / {print $4}') for container_subnet in $(ip -o addr show | awk '/^(\d)+: eth(.+)inet / {print $4}')
do do
iptables -A INPUT -s ${container_subnet} -j ACCEPT iptables -I INPUT -s ${container_subnet} -j ACCEPT
iptables -A OUTPUT -d ${container_subnet} -j ACCEPT iptables -I OUTPUT -d ${container_subnet} -j ACCEPT
done done
# allow connections to local subnets specified by user, need to add routes since wireguard interface has 0.0.0.0/0 allowed ips # allow connections to local subnets specified by user, need to add routes since wireguard interface has 0.0.0.0/0 allowed ips
for local_subnet in ${LOCAL_IPV4_SUBNETS//,/$IFS} for local_subnet in ${LOCAL_IPV4_SUBNETS//,/$IFS}
do do
iptables -A INPUT -s ${local_subnet} -j ACCEPT iptables -I INPUT -s ${local_subnet} -j ACCEPT
iptables -A OUTPUT -d ${local_subnet} -j ACCEPT iptables -I OUTPUT -d ${local_subnet} -j ACCEPT
ip route add ${local_subnet} via ${default_route_ip} ip route add ${local_subnet} via ${default_route_ip}
done done
# established connections # established connections
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -I INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -I OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# kill switches for ipv4 -- @see wg-quick(8) # kill switches for ipv4 -- @see wg-quick(8)
iptables -A OUTPUT ! -o ${WIREGUARD_INTERFACE} -m mark ! --mark ${WIREGUARD_FWMARK} -m addrtype ! --dst-type LOCAL -j REJECT iptables -A OUTPUT ! -o ${WIREGUARD_INTERFACE} -m mark ! --mark ${WIREGUARD_FWMARK} -m addrtype ! --dst-type LOCAL -j REJECT --reject-with icmp-admin-prohibited
for container_subnet in $(ip -o addr show | awk '/^(\d)+: eth(.+)inet6 / {print $4}') for container_subnet in $(ip -o addr show | awk '/^(\d)+: eth(.+)inet6 / {print $4}')
do do
ip6tables -A INPUT -s ${container_subnet} -j ACCEPT ip6tables -I INPUT -s ${container_subnet} -j ACCEPT
ip6tables -A OUTPUT -d ${container_subnet} -j ACCEPT ip6tables -I OUTPUT -d ${container_subnet} -j ACCEPT
done done
# established connections # established connections
ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ip6tables -I INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ip6tables -I OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# kill switches for ipv6 -- @see wg-quick(8) # kill switches for ipv6 -- @see wg-quick(8)
ip6tables -I OUTPUT ! -o ${WIREGUARD_INTERFACE} -m mark ! --mark ${WIREGUARD_FWMARK} -m addrtype ! --dst-type LOCAL -j REJECT ip6tables -A OUTPUT ! -o ${WIREGUARD_INTERFACE} -m mark ! --mark ${WIREGUARD_FWMARK} -m addrtype ! --dst-type LOCAL -j REJECT --reject-with icmp6-adm-prohibited
iptables-save | tee /tmp/rules.v4.${WIREGUARD_INTERFACE}.$$.conf
ip6tables-save | tee /tmp/rules.v6.${WIREGUARD_INTERFACE}.$$.conf
sleep 8 & sleep 8 &
wait ${!} wait ${!}
@@ -84,6 +99,9 @@ wait ${!}
# qbittorrent webui host # qbittorrent webui host
WEBUI_HOST="${WEBUI_HOST:-http://localhost:8080}" WEBUI_HOST="${WEBUI_HOST:-http://localhost:8080}"
# from this point on, its best effort, so just keep going and don't fail the container
set +o errexit
# loop now forever keeping port forward up to date (protonvpn) # loop now forever keeping port forward up to date (protonvpn)
# https://protonvpn.com/support/port-forwarding-manual-setup # https://protonvpn.com/support/port-forwarding-manual-setup
while true; do while true; do
@@ -94,14 +112,14 @@ while true; do
udp_port=$(echo "${udp_output}" | sed -n 's/.*Mapped public port \([0-9]\+\).*/\1/p') udp_port=$(echo "${udp_output}" | sed -n 's/.*Mapped public port \([0-9]\+\).*/\1/p')
if [[ "${tcp_port}" -ne "${udp_port}" ]]; then if [[ "${tcp_port}" -ne "${udp_port}" ]]; then
echo "Warning: tcp_port (${tcp_port}) and udp_port (${udp_port}) are different" info "Warning: tcp_port (${tcp_port}) and udp_port (${udp_port}) are different"
fi fi
# failure to connect to webui, we don't want to fail the loop, just log the error and try again # failure to connect to webui, we don't want to fail the loop, just log the error and try again
current_port=$(curl --silent --header "Referer: ${WEBUI_HOST}" "${WEBUI_HOST}/api/v2/app/preferences" | jq .listen_port || true) current_port=$(curl --silent --header "Referer: ${WEBUI_HOST}" "${WEBUI_HOST}/api/v2/app/preferences" | jq .listen_port || true)
if [[ "${tcp_port}" -ne "${current_port}" ]]; then if [[ "${tcp_port}" -ne "${current_port}" ]]; then
echo "Port changed from '${current_port}' to '${tcp_port}'. Updating app preferences..." info "Port changed from '${current_port}' to '${tcp_port}'. Updating app preferences..."
curl \ curl \
--silent \ --silent \
@@ -111,9 +129,9 @@ while true; do
"${WEBUI_HOST}/api/v2/app/setPreferences" || true "${WEBUI_HOST}/api/v2/app/setPreferences" || true
fi fi
sleep 30 & sleep 45 &
wait ${!} wait ${!}
done done
echo "exiting" info "exiting."
exit 0 exit 0