As a developer who relies heavily on ChatGPT Plus for cross-language open-source project research, my recent experience with the web version could only be described as a disaster: the page spun forever, and pressing F12 to open the developer tools revealed a Network panel packed with red errors for rqstr?k=client-sY... (NS_BINDING_ABORTED). A full page load took as long as 39.42 seconds.
My network architecture is 本地 Ubuntu 26.04 -> Clash Verge Rev (TUN 模式) -> Wstunnel Client -> ZgoCloud 洛杉矶 VPS -> Wstunnel Server -> WireGuard Server. This setup is excellent at disguising traffic as TLS to evade DPI blocking, but its “TCP-over-UDP” structure is highly prone to head-of-line blocking on poor networks.
Tackling this pain point took two distinct stages of troubleshooting and tuning. Today I’m writing up a complete retrospective of both.
Stage One: Initial Mitigation and Locating the Bottleneck
In my earlier troubleshooting (see: “A Troubleshooting Record of Slow ChatGPT Web Page Loading”), I had already confirmed that packet loss at the underlying layer was caused by maintenance on the ZgoCloud host, and I made some initial optimizations:
- Used
Wstunnel --connection-min-idle 10to enable a long-lived connection pool and cut down on TLS handshake overhead. - Restricted the WireGuard peer’s MTU in Clash’s
proxies, and strictly aligned the Clash Verge TUN virtual adapter’s MTU to 1280, eliminating local packet fragmentation. - Used
iperf3to confirm the key fact: bandwidth was sufficient, but TCP retransmissions were extremely high.
Stage-one tuning improved the experience somewhat, but during daytime peak hours the page still froze. This showed that parameter tweaks at the software layer alone could not fully offset the damage inflicted by the underlying TCP-over-TCP architecture.
![[Figure 1: After stage-one tuning, the screen still shows some red errors everywhere, with a load time of 39.42 seconds]](https://media.shuijingwanwq.com/2026/11/1-1-1024x550.png)
Technical analysis: As soon as the underlying physical link drops a packet, Wstunnel’s TCP retransmissions get amplified further by WireGuard’s UDP retransmissions. The frontend waits for data that never arrives, times out, and cuts the connection to reconnect—producing a screen full of red errors.
Stage Two: “Surgical” Tuning from Server to Client
To eliminate the lag once and for all, I moved into the second stage of deep tuning. This time the focus was on squeezing the server’s network stack and locking in the local startup method.
1. Server Side: Component Upgrade and Kernel Network Stack
First, I upgraded the server-side Wstunnel to v11.0.0. The new version brings major improvements in underlying read throughput and long-lived connection stability.
![[Figure 2: Server-side wstunnel-cli 11.0.0 upgraded successfully]](https://media.shuijingwanwq.com/2026/11/2-1.png)
I also forced the server-side WireGuard MTU to 1400 to complement the local 1280, leaving headroom for the WebSocket encapsulation overhead.
![[Figure 3: MTU in the server-side wg0.conf changed to 1400]](https://media.shuijingwanwq.com/2026/11/3-1.png)
To make the Linux kernel more resilient under the high latency and packet loss of cross-border links, I aggressively tuned the kernel network stack via /etc/sysctl.d/:
- Enabled the BBR congestion control algorithm.
- Enlarged the TCP receive/send buffers to 4MB (the system auto-expanded them to 16MB).
- Enabled TCP window scaling and Fast Open.
![[Figure 4: Writing BBR and TCP buffer parameters on the server]](https://media.shuijingwanwq.com/2026/11/4-1.png)
2. Local Side: No More Typing Commands by Hand—Locking It in as a Systemd Service
In stage one I had used nohup to keep Wstunnel running in the background temporarily, which broke on every reboot. This time I wrote the Wstunnel client—with its long-connection-pool parameters—into a startup script and configured it as a Systemd user-level service, achieving enabled auto-start on boot.
![[Figure 5: Local nohup startup log with lots of TLS handshake messages]](https://media.shuijingwanwq.com/2026/11/5-1-1024x452.png)
![[Figure 7: systemctl --user status wstunnel.service showing active]](https://media.shuijingwanwq.com/2026/11/7-1-1024x333.png)
Real Results: A Qualitative Leap from “Unusable” to “Usable”
After completing all of stage two’s configuration, I restarted the Clash core and opened the ChatGPT web page again. First-paint time dropped straight to 2.38 seconds—the UI rendered instantly and the input box responded in a flash!
![[Figure 9: After tuning, the page loads instantly; a few red X marks remain in the Network panel]](https://media.shuijingwanwq.com/2026/11/9-1-1024x674.png)
About the remaining “red X marks”:
As a developer, I have to record this objectively: at this point the Network panel still shows a small number of NS_BINDING_ABORTED. But this is fundamentally different from the earlier full-screen deadlock:
these are the browser proactively triggering its abort-and-retry mechanism when the ChatGPT frontend encounters tiny delays on non-core endpoints (such as rgstr heartbeat packets). They no longer block the page’s main rendering or the input box’s responsiveness.
Takeaways and Reflections
Looking back across both stages of troubleshooting, I came away with two important realizations:
- Bandwidth ≠ stability: For streaming long-lived connections (like ChatGPT), TCP retransmission rate is far deadlier than peak bandwidth. Stage one’s MTU alignment prevented fragmentation, while stage two’s server-side kernel tuning (BBR) made the TCP stack far more composed in the face of packet loss.
- The architecture’s ceiling:
Wstunnelcan disguise traffic as TLS, but the underlyingTCP-over-TCParchitecture is inherently vulnerable to packet loss. Whenever the network experiences even minor jitter, it still cannot achieve 100% error-free operation.
With this two-stage tuning, the current configuration has pulled the experience back above the passing line of “usable day to day.” If the network deteriorates again during daytime hours in the future, the ultimate solution will be to abandon the TCP tunnel entirely and migrate to Hysteria2, a protocol built on QUIC (UDP) that is inherently packet-loss resistant.

![[Figure 1: After stage-one tuning, the screen still shows some red errors everywhere, with a load time of 39.42 seconds]](https://media.shuijingwanwq.com/2026/11/1-1.png)