From 24a6cb276f24068934e69cef084f4c51600610dc Mon Sep 17 00:00:00 2001 From: infosave Date: Fri, 29 May 2026 15:33:11 +0300 Subject: [PATCH] fix(awg2): clamp TCP MSS on server so traffic actually flows (issue #50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Final piece of "connects but no traffic": with the reduced client MTU (1280) the upload direction fits, but full-size download packets (web pages, TLS responses) still exceeded the AmneziaWG tunnel and were dropped — handshake and small packets worked, browsing stalled. Confirmed on a live server: the client's encrypted packets reached the server but large return packets never made it back. Adding a server-side TCP MSS clamp to 1240 (= 1280 - 40) made real traffic flow (verified: 1.6 MiB transferred, FORWARD/MASQUERADE counters incrementing). - VpnClient::addClientToServer(): after applying the peer, idempotently ensure net.ipv4.ip_forward=1 and a `mangle FORWARD ... TCPMSS --set-mss 1240` rule (-C then -A). Re-applied on every client creation, so it survives container restarts/reinstalls and covers adopted native Amnezia containers. - migrations/072 + 064: add the same MSS clamp to the awg2 install script PostUp (and remove it in PostDown) for panel-installed servers. Verified end-to-end: removing the rule and creating a client via the panel re-adds it automatically; the live phone client now browses normally. Co-Authored-By: Claude Opus 4.8 (1M context) --- inc/VpnClient.php | 16 ++++++++++++ .../064_complete_awg2_original_params.sql | 4 +-- migrations/072_awg2_mss_clamp.sql | 25 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 migrations/072_awg2_mss_clamp.sql diff --git a/inc/VpnClient.php b/inc/VpnClient.php index 5dd1e59..0776e1d 100644 --- a/inc/VpnClient.php +++ b/inc/VpnClient.php @@ -1290,6 +1290,22 @@ class VpnClient // Without this, the interface uses standard WireGuard without Jc/S1/S2/H1-H4 $cmd5 = sprintf("docker exec -i %s sh -c 'ip link del %s 2>/dev/null || true; %s up %s/%s 2>&1'", $containerName, $ifaceName, $wgQuickTool, $configDir, $configFile); self::executeServerCommand($serverData, $cmd5, true); + + // 7. CRITICAL: Clamp TCP MSS so download-direction packets fit the reduced + // AmneziaWG tunnel MTU (clients use MTU 1280 -> MSS 1240). Without this the + // handshake succeeds and small packets flow, but large packets (web pages, + // TLS responses) exceed the tunnel and are silently dropped — the classic + // "connected but no traffic" symptom (issue #50). Idempotent (-C then -A), + // and ip_forward is ensured for good measure. Re-applied on every client + // creation so it survives container restarts/reinstalls. + $mssRule = "-p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1240"; + $cmd6 = sprintf( + "docker exec -i %s sh -c 'sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 || true; iptables -t mangle -C FORWARD %s 2>/dev/null || iptables -t mangle -A FORWARD %s'", + $containerName, + $mssRule, + $mssRule + ); + self::executeServerCommand($serverData, $cmd6, true); } /** diff --git a/migrations/064_complete_awg2_original_params.sql b/migrations/064_complete_awg2_original_params.sql index 0d23745..b600d29 100644 --- a/migrations/064_complete_awg2_original_params.sql +++ b/migrations/064_complete_awg2_original_params.sql @@ -145,8 +145,8 @@ echo "H2 = $H2_VAL" echo "H3 = $H3_VAL" echo "H4 = $H4_VAL" echo "I1 = $I1_VAL" -echo "PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE" -echo "PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE" +echo "PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1240" +echo "PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; iptables -t mangle -D FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1240" } > /opt/amnezia/awg2/awg0.conf echo "$PRIVATE_KEY" > /opt/amnezia/awg2/wireguard_server_private_key.key diff --git a/migrations/072_awg2_mss_clamp.sql b/migrations/072_awg2_mss_clamp.sql new file mode 100644 index 0000000..b8fcfaf --- /dev/null +++ b/migrations/072_awg2_mss_clamp.sql @@ -0,0 +1,25 @@ +-- ===================================================================== +-- Migration 072: TCP MSS clamping for AmneziaWG 2.0 (awg2) +-- +-- Issue #50: clients connect (handshake OK) but no traffic flows. With the +-- reduced tunnel MTU (clients use 1280), TCP must also negotiate a small +-- enough MSS, otherwise full-size download packets (web pages, TLS responses) +-- exceed the tunnel and are dropped — the handshake and small packets work, +-- but browsing stalls. Clamping MSS to 1240 (1280 - 40) on the server's +-- FORWARD path fixes the download direction. +-- +-- This appends the clamp to the awg2 install script's PostUp so panel-installed +-- servers get it on every interface bring-up. (Adopted native containers are +-- handled at runtime by VpnClient::addClientToServer(), which applies the same +-- rule idempotently on each client creation.) +-- ===================================================================== + +UPDATE protocols +SET install_script = REPLACE( + install_script, + 'iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE', + 'iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1240' +) +WHERE slug = 'awg2' + AND install_script LIKE '%-A POSTROUTING -o eth0 -j MASQUERADE%' + AND install_script NOT LIKE '%TCPMSS%';