z2k/mtproxy-client/main.go
Necronicle 2184b9b413 Revert: roll tunnel and worker back to e688fb1
Today's rewrite (e729560) introduced two independent regressions that
compounded into a total outage:

1. worker.js added `await socket.opened` before sending CONNECT_OK. On
   Cloudflare Workers, `socket.opened` runs an HTTP-based-service heuristic
   that pre-emptively rejects with "proxy request failed ... consider using
   fetch instead" for destinations that look HTTPS-ish (port 443 with
   TLS-like framing) — even when a plain read/write on the same socket
   would have worked. Every Telegram DC hit this path and the tunnel
   returned 100% CONNECT_FAIL.

2. The N-parallel-session + voluntary TTL-rotation architecture in the
   rewritten tunnel.go killed in-flight TCP streams every rotation cycle,
   so Telegram MTProto couldn't finish a single handshake before its
   session got rotated out. Staggering + longer TTLs didn't help enough.

Reverted tunnel.go, main.go, listener.go, worker.js, wrangler.toml and all
9 prebuilt binaries to e688fb1 (the last commit known to work for three
days straight). lib/install.sh keeps the iptables -I PREROUTING 1 fix from
today (unrelated to the tunnel rewrite, real bug) but drops the
--parallel/--session-ttl flags since the reverted binary doesn't know them.

The Roblox work from a6c607d stays: files/lua/z2k-modern-core.lua still
contains z2k_game_udp, lib/config_official.sh still wires it into the game
strategies. That part works and is orthogonal to the tunnel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 00:58:03 +03:00

50 lines
1.4 KiB
Go

package main
import (
"flag"
"log"
"sync"
"time"
"github.com/gorilla/websocket"
)
var (
listenAddr = flag.String("listen", ":1443", "Local listen address")
tunnelURL = flag.String("tunnel-url", "wss://z2k-tunnel.necronicle.workers.dev/ws", "Cloudflare Worker WebSocket URL")
tunnelSecret = flag.String("tunnel-secret", "d01f72f9543b29da4e3724b1530c0d11cb30a6f8db15bc0adfe8f2d37b5844b2", "Shared secret for tunnel auth")
verbose = flag.Bool("v", false, "Verbose logging")
connTimeout = flag.Duration("timeout", 5*time.Minute, "Idle connection timeout")
maxConns = flag.Int("max-conns", 1024, "Maximum concurrent connections")
)
// connSemaphore limits concurrent connections
var connSemaphore chan struct{}
// wsWriter serializes all writes to a WebSocket connection.
// gorilla/websocket supports only one concurrent writer.
type wsWriter struct {
ws *websocket.Conn
mu sync.Mutex
}
func (w *wsWriter) WriteMessage(messageType int, data []byte) error {
w.mu.Lock()
defer w.mu.Unlock()
w.ws.SetWriteDeadline(time.Now().Add(10 * time.Second))
return w.ws.WriteMessage(messageType, data)
}
func (w *wsWriter) WriteControl(messageType int, data []byte, deadline time.Time) error {
w.mu.Lock()
defer w.mu.Unlock()
return w.ws.WriteControl(messageType, data, deadline)
}
func main() {
flag.Parse()
if err := runTunnel(); err != nil {
log.Fatal(err)
}
}