#507·wstunnel

PowerShell 客户端 -> 公司代理 -> nginx -> wstunnel 服务器场景问题

作者: istvanmate创建于 2026年5月8日更新于 2026年8月31日
标签help wanted

Describe the goal

Trying to tunnel into

wstunnel.exe server --restrict-http-upgrade-path-prefix "/wsproxy" ws://0.0.0.0:5000

with a powershell script as a client, through nginx listening on wss://sitename/wsproxy, config:

nginx
        location /wsproxy {
            proxy_pass http://127.0.0.1:5000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

Describe what does not work

With proxy_pass http://127.0.0.1:5000; I get

←[2m2026-05-08T10:07:00.552967Z←[0m ←[33m WARN←[0m ←[1mcnx←[0m←[1m{←[0m←[3mpeer←[0m←[2m=←[0m"127.0.0.1:49809"←[1m}←[0m←[2m:←[0m←[1mtunnel←[0m←[1m{←[0m←[3mforwarded_for←[0m←[2m=←[0m"remote IP"←[1m}←[0m←[2m:←[0m ←[2mwstunnel::tunnel::server::server←[0m←[2m:←[0m Rejecting connection with bad upgrade request: /wsproxy

with proxy_pass http://127.0.0.1:5000/;

←[2m2026-05-08T10:07:00.552967Z←[0m ←[33m WARN←[0m ←[1mcnx←[0m←[1m{←[0m←[3mpeer←[0m←[2m=←[0m"127.0.0.1:49809"←[1m}←[0m←[2m:←[0m←[1mtunnel←[0m←[1m{←[0m←[3mforwarded_for←[0m←[2m=←[0m"remote IP"←[1m}←[0m←[2m:←[0m ←[2mwstunnel::tunnel::server::server←[0m←[2m:←[0m Rejecting connection with bad upgrade request: /

PS script used:

powershell
# ==========================================
# CONFIGURATION
# ==========================================
$localPort   = 8080
$targetUri   = "wss://sitename/wsproxy"

# 1. Compile the Header Injector (Essential for bypass)
if (-not ([System.Management.Automation.PSTypeName]'WSInjector').Type) {
    Add-Type -TypeDefinition @"
    using System;
    using System.Net;
    using System.Reflection;
    using System.Net.WebSockets;
    public class WSInjector {
        public static void SetOptions(ClientWebSocket ws, IWebProxy proxy) {
            var options = ws.Options;
            // Native .NET Core 3.1+ approach used by the module
            // On PS 5.1, we use reflection to set the internal proxy if the property is missing
            try {
                typeof(ClientWebSocketOptions).GetProperty("Proxy").SetValue(options, proxy);
            } catch {
                FieldInfo field = typeof(ClientWebSocketOptions).GetField("_proxy", BindingFlags.NonPublic | BindingFlags.Instance);
                if (field != null) field.SetValue(options, proxy);
            }
        }
    }
"@
}

# 2. Setup System Proxy with Credentials
$systemProxy = [System.Net.WebRequest]::GetSystemWebProxy()
$systemProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials

# 3. Initialize WebSocket Client (Module Logic)
$wsClient = New-Object System.Net.WebSockets.ClientWebSocket
[WSInjector]::SetOptions($wsClient, $systemProxy)

# 4. Connect to Nginx
$cts = New-Object