Documentation
¶
Overview ¶
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Package apis exposes the Sudoku tunnel (HTTP mask + Sudoku obfuscation + AEAD) as a small Go API. It supports both pure Sudoku downlink and the bandwidth-optimized packed downlink, plus UDP-over-TCP (UoT), so the same primitives used by the CLI can be embedded by other projects.
Key entry points:
- ProtocolConfig / DefaultConfig: describe all required parameters.
- Dial: client-side helper that connects to a Sudoku server and sends the target address.
- DialUDPOverTCP: client-side helper that primes a UoT tunnel.
- ServerHandshake: server-side helper that upgrades an accepted TCP connection and returns the decrypted tunnel plus the requested target address (TCP mode).
- ServerHandshakeFlexible: server-side helper that upgrades connections and lets callers detect UoT or read the target address themselves.
- HandshakeError: wraps errors while preserving bytes already consumed so callers can gracefully fall back to raw TCP/HTTP handling if desired.
The configuration mirrors the CLI behavior: build a Sudoku table via sudoku.NewTable(seed, "prefer_ascii"|"prefer_entropy") or sudoku.NewTableWithCustom (third arg: custom X/P/V pattern such as "xpxvvpvv"), pick an AEAD (chacha20-poly1305 is the default), keep the key and padding settings consistent across client/server, and apply an optional handshake timeout on the server side.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Copyright (C) 2026 by saba <contact me via issue>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association with this application without prior consent.
Index ¶
- func Dial(ctx context.Context, cfg *ProtocolConfig) (net.Conn, error)
- func DialBase(ctx context.Context, cfg *ProtocolConfig) (net.Conn, error)
- func DialReverseClientSession(ctx context.Context, cfg *ProtocolConfig, clientID string, ...) error
- func DialUDPOverTCP(ctx context.Context, cfg *ProtocolConfig) (net.Conn, error)
- func HandleMuxServer(conn net.Conn, onConnect func(targetAddr string)) error
- func HandleMuxWithDialer(conn net.Conn, onConnect func(targetAddr string), ...) error
- func HandleUoT(conn net.Conn) error
- func NewPreBufferedConn(conn net.Conn, preRead []byte) net.Conn
- func ReadTargetAddress(r io.Reader) (string, error)
- func ReadUoTDatagram(r io.Reader) (string, []byte, error)
- func ServeReverseClientSession(conn net.Conn, clientID string, routes []ReverseRoute) error
- func ServerHandshake(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, string, error)
- func ServerHandshakeAuto(rawConn net.Conn, cfg *ProtocolConfig) (conn net.Conn, targetAddr string, isUoT bool, err error)
- func ServerHandshakeAutoWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (conn net.Conn, targetAddr string, isUoT bool, userHash string, err error)
- func ServerHandshakeFlexible(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, func(error) error, error)
- func ServerHandshakeFlexibleWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, string, func(error) error, error)
- func ServerHandshakeWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, string, string, error)
- func WriteTargetAddress(w io.Writer, addr string) error
- func WriteUoTDatagram(w io.Writer, addr string, payload []byte) error
- type HTTPMaskTunnelServer
- func (s *HTTPMaskTunnelServer) HandleConn(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, handled bool, err error)
- func (s *HTTPMaskTunnelServer) HandleConnAuto(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, isUoT bool, handled bool, err error)
- func (s *HTTPMaskTunnelServer) HandleConnAutoWithUserHash(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, isUoT bool, userHash string, ...)
- func (s *HTTPMaskTunnelServer) HandleConnWithUserHash(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, userHash string, handled bool, ...)
- type HandshakeError
- type HandshakeResult
- type MuxClient
- type ProtocolConfig
- type ReverseManager
- type ReverseRoute
- type SessionKind
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DialBase ¶
DialBase opens a Sudoku tunnel to cfg.ServerAddress and completes the handshake, but does not send a target address.
This is useful for higher-level protocols built on top of the tunnel (e.g. mux sessions, reverse proxy sessions).
func DialReverseClientSession ¶
func DialReverseClientSession(ctx context.Context, cfg *ProtocolConfig, clientID string, routes []ReverseRoute) error
DialReverseClientSession dials the server and runs a reverse registration session until it ends. Reverse sessions use packed uplink by default; normal proxy sessions remain pure-uplink.
This function returns when the reverse session ends; callers usually want to reconnect with backoff.
func DialUDPOverTCP ¶
DialUDPOverTCP bootstraps a UDP-over-TCP tunnel using the standard Dial flow.
func HandleMuxServer ¶
HandleMuxServer runs a "single tunnel, multi-target" mux session on an upgraded tunnel connection.
func HandleMuxWithDialer ¶
func HandleMuxWithDialer(conn net.Conn, onConnect func(targetAddr string), dialTarget func(targetAddr string) (net.Conn, error)) error
HandleMuxWithDialer is like HandleMuxServer but allows the caller to control how targets are dialed.
func NewPreBufferedConn ¶
NewPreBufferedConn returns a net.Conn that replays preRead before reading from conn.
This is useful when you need to peek some bytes (e.g. to detect an HTTP tunnel header or probe tables) and still keep the stream consumable by the next parser.
func ReadTargetAddress ¶
ReadTargetAddress parses a single SOCKS5-style target address frame (host:port) from r.
func ServeReverseClientSession ¶
func ServeReverseClientSession(conn net.Conn, clientID string, routes []ReverseRoute) error
ServeReverseClientSession registers routes to the server and serves reverse mux streams until the session ends.
The provided conn must be an upgraded Sudoku tunnel connection (handshake completed).
func ServerHandshake ¶
ServerHandshake performs the Sudoku server-side handshake.
It completes the full handshake pipeline (HTTP mask → Sudoku decoding → AEAD decryption → timestamp verification) and then reads the target address from the tunnel.
On failure, the returned error may be a *HandshakeError containing raw data for fallback handling.
func ServerHandshakeAuto ¶
func ServerHandshakeAuto(rawConn net.Conn, cfg *ProtocolConfig) (conn net.Conn, targetAddr string, isUoT bool, err error)
ServerHandshakeAuto upgrades the connection and detects whether it is a UoT (UDP-over-TCP) session.
Returns:
- conn: the upgraded tunnel connection
- targetAddr: valid only when isUoT=false
- isUoT=true: caller should run HandleUoT(conn) instead of reading a target address
func ServerHandshakeAutoWithUserHash ¶
func ServerHandshakeAutoWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (conn net.Conn, targetAddr string, isUoT bool, userHash string, err error)
ServerHandshakeAutoWithUserHash is like ServerHandshakeAuto but also returns the per-user handshake identifier.
func ServerHandshakeFlexible ¶
func ServerHandshakeFlexible(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, func(error) error, error)
ServerHandshakeFlexible upgrades the connection and leaves payload parsing (address or UoT) to the caller. The returned fail function wraps errors into HandshakeError with recorded data for fallback handling.
func ServerHandshakeFlexibleWithUserHash ¶
func ServerHandshakeFlexibleWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, string, func(error) error, error)
ServerHandshakeFlexibleWithUserHash is like ServerHandshakeFlexible but also returns the per-user handshake identifier.
func ServerHandshakeWithUserHash ¶
func ServerHandshakeWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, string, string, error)
ServerHandshakeWithUserHash is like ServerHandshake but also returns a stable per-user identifier extracted from the client handshake: hex(sha256(privateKey)[:8]) for official clients using split private keys.
func WriteTargetAddress ¶
WriteTargetAddress writes a single SOCKS5-style target address frame (host:port) to w.
Types ¶
type HTTPMaskTunnelServer ¶
type HTTPMaskTunnelServer struct {
// contains filtered or unexported fields
}
HTTPMaskTunnelServer bridges raw TCP accepts with the optional CDN-capable HTTP tunnel transports (stream/poll).
Typical usage:
srv := apis.NewHTTPMaskTunnelServer(serverCfg)
for {
c, _ := ln.Accept()
go func(raw net.Conn) {
defer raw.Close()
tunnel, target, handled, err := srv.HandleConn(raw)
if err != nil || !handled || tunnel == nil {
return
}
defer tunnel.Close()
io.Copy(tunnel, tunnel)
}(c)
}
func NewHTTPMaskTunnelServer ¶
func NewHTTPMaskTunnelServer(cfg *ProtocolConfig) *HTTPMaskTunnelServer
func (*HTTPMaskTunnelServer) HandleConn ¶
func (s *HTTPMaskTunnelServer) HandleConn(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, handled bool, err error)
HandleConn handles a single accepted TCP connection.
Returns:
- tunnelConn/targetAddr if a Sudoku tunnel handshake has been completed (handled=true and tunnelConn != nil)
- handled=true, tunnelConn=nil for HTTP tunnel control requests (e.g., poll push/pull)
- handled=false if this server is not configured to handle HTTP tunnel transports (legacy-only)
func (*HTTPMaskTunnelServer) HandleConnAuto ¶
func (s *HTTPMaskTunnelServer) HandleConnAuto(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, isUoT bool, handled bool, err error)
HandleConnAuto handles a single accepted TCP connection, and supports both TCP target connections and UoT (UDP-over-TCP) sessions.
Returns:
- tunnelConn/targetAddr if a TCP target address has been read (handled=true, isUoT=false)
- tunnelConn with isUoT=true if this is a UoT session (caller should run HandleUoT)
- handled=true, tunnelConn=nil for HTTP tunnel control requests (e.g., poll push/pull)
func (*HTTPMaskTunnelServer) HandleConnAutoWithUserHash ¶
func (s *HTTPMaskTunnelServer) HandleConnAutoWithUserHash(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, isUoT bool, userHash string, handled bool, err error)
HandleConnAutoWithUserHash is like HandleConnAuto but also returns the per-user handshake identifier when a Sudoku tunnel handshake has been completed.
func (*HTTPMaskTunnelServer) HandleConnWithUserHash ¶
func (s *HTTPMaskTunnelServer) HandleConnWithUserHash(rawConn net.Conn) (tunnelConn net.Conn, targetAddr string, userHash string, handled bool, err error)
HandleConnWithUserHash is like HandleConn but also returns the per-user handshake identifier when a Sudoku tunnel handshake has been completed.
type HandshakeError ¶
type HandshakeError struct {
Err error
RawConn net.Conn
HTTPHeaderData []byte // Header data from the HTTP mask layer
ReadData []byte // Data already read by the Sudoku layer
}
HandshakeError wraps errors that occur during the handshake process. When this error is returned, the caller may perform fallback handling using RawConn, HTTPHeaderData, and ReadData.
Fields:
- Err: Original error describing why the handshake failed.
- RawConn: The raw TCP connection, available for fallback.
- HTTPHeaderData: Header bytes read during the HTTP mask phase (ConsumeHeader stage).
- ReadData: Bytes read and recorded during the Sudoku decoding phase.
Data replay order for fallback:
- Write HTTPHeaderData first (if non-empty)
- Then write ReadData (if non-empty)
- Finally forward remaining data from RawConn
Example usage:
conn, target, err := apis.ServerHandshake(rawConn, cfg)
if err != nil {
var hsErr *apis.HandshakeError
if errors.As(err, &hsErr) {
// Perform fallback handling
fallbackConn, _ := net.Dial("tcp", fallbackAddr)
fallbackConn.Write(hsErr.HTTPHeaderData)
fallbackConn.Write(hsErr.ReadData)
io.Copy(fallbackConn, hsErr.RawConn)
io.Copy(hsErr.RawConn, fallbackConn)
}
return
}
func (*HandshakeError) Error ¶
func (e *HandshakeError) Error() string
func (*HandshakeError) Unwrap ¶
func (e *HandshakeError) Unwrap() error
type HandshakeResult ¶
type HandshakeResult struct {
Conn net.Conn // Upgraded tunnel connection (decrypted / de-obfuscated).
UserHash string // Stable per-user identifier (hex, 16 chars). May be empty.
Fail func(error) error // Wraps an error into HandshakeError with recorded data for fallback.
}
HandshakeResult bundles all outputs from the server-side handshake into a single struct so that callers can pick the fields they need without multiple function variants.
func ServerHandshakeCore ¶
func ServerHandshakeCore(rawConn net.Conn, cfg *ProtocolConfig) (*HandshakeResult, error)
ServerHandshakeCore performs the full server-side handshake and returns a HandshakeResult. It does NOT read the target address — the caller decides what to do with the tunnel.
type MuxClient ¶
type MuxClient struct {
// contains filtered or unexported fields
}
MuxClient opens multiple target connections over a single Sudoku tunnel (single tunnel, multi-target).
This avoids paying the HTTP tunnel + Sudoku handshake RTT for every target connection when HTTPMask tunnel modes are enabled.
func NewMuxClient ¶
func NewMuxClient(cfg *ProtocolConfig) (*MuxClient, error)
type ProtocolConfig ¶
type ProtocolConfig struct {
// ServerAddress is the server address (client-side only).
// Format: "host:port" or "ip:port"
// Example: "example.com:443" or "1.2.3.4:8080"
ServerAddress string
// Key is the pre-shared key used for AEAD encryption.
// Both sides must agree on this value; use "./sudoku -keygen" to generate one.
Key string
// AEADMethod specifies the AEAD cipher.
// Valid values:
// - "aes-128-gcm": AES-128-GCM (fast, good hardware acceleration)
// - "chacha20-poly1305": ChaCha20-Poly1305 (good pure-software performance)
// - "none": no encryption (testing only, never use in production)
AEADMethod string
// Table is the Sudoku encoding map (must be identical on client and server).
// Create with sudoku.NewTable(seed, "prefer_ascii"|"prefer_entropy") or
// sudoku.NewTableWithCustom(seed, "prefer_entropy", "<xpxvvpvv>").
// Must not be nil (unless Tables is set).
Table *sudoku.Table
// Tables is an optional candidate set for table rotation.
// If provided (len>0), the client will pick one table per connection and the server will
// identify which one was used by probing the handshake uplink and, when needed, using the
// KIP client-hello table hint for shared-uplink directional modes.
// When Tables is set, Table may be nil.
Tables []*sudoku.Table
// PaddingMin is the minimum padding rate (0-100).
// Minimum probability (%) of inserting a padding byte during encoding.
PaddingMin int
// PaddingMax is the maximum padding rate (0-100).
// Maximum probability (%) of inserting a padding byte during encoding.
// Must be >= PaddingMin.
PaddingMax int
// EnablePureDownlink controls downlink encoding.
// When false, bandwidth-optimized 6-bit packed downlink is used.
EnablePureDownlink bool
// TargetAddress is the final destination the client wants to reach (client-side only).
// Format: "host:port"
// Example: "google.com:443" or "1.1.1.1:53"
TargetAddress string
// HandshakeTimeoutSeconds is the handshake timeout in seconds (server-side only).
// Recommended: 5-10.
// Too small may cause failures on slow networks.
// Too large may make the server vulnerable to slowloris attacks.
HandshakeTimeoutSeconds int
// DisableHTTPMask disables the HTTP mask layer.
// Default false (mask enabled).
// When true, the client does not send a mask header and the server does not check for one.
// Note: the server supports auto-detection, so even with this set to false it can handle
// clients without a mask header (as long as the first bytes don't look like an HTTP method).
DisableHTTPMask bool
// HTTPMaskMode controls how the "HTTP mask" behaves:
// - "legacy": write a fake HTTP/1.1 header then switch to raw stream (default, not CDN-compatible)
// - "stream": real HTTP tunnel (split-stream), CDN-compatible
// - "poll": plain HTTP tunnel (authorize/push/pull), strong restricted-network pass-through
// - "auto": try stream then fall back to poll
// - "ws": WebSocket tunnel (ws:// or wss://)
HTTPMaskMode string
// HTTPMaskTLSEnabled enables HTTPS for HTTP tunnel modes (client-side).
// When false, HTTP tunnel modes use plain HTTP (no port-based TLS inference).
HTTPMaskTLSEnabled bool
// HTTPMaskHost optionally overrides the HTTP Host header / SNI host for HTTP tunnel modes (client-side).
// When empty, it is derived from ServerAddress.
HTTPMaskHost string
// HTTPMaskPathRoot optionally prefixes all HTTP mask paths with a first-level segment.
// Example: "aabbcc" => "/aabbcc/session", "/aabbcc/api/v1/upload", ...
HTTPMaskPathRoot string
// HTTPMaskMultiplex controls multiplex behavior when HTTPMask tunnel modes are enabled:
// - "off": disable reuse; each Dial establishes its own HTTPMask tunnel
// - "auto": reuse underlying HTTP connections across multiple tunnel dials (HTTP/1.1 keep-alive / HTTP/2)
// - "on": enable "single tunnel, multi-target" mux when using apis.NewMuxClient (Dial behaves like "auto")
HTTPMaskMultiplex string
}
ProtocolConfig defines all parameters required by the Sudoku protocol stack.
The Sudoku protocol is a multi-layer encrypted tunnel:
- HTTP mask layer: disguises traffic as HTTP POST requests
- Sudoku obfuscation layer: encodes data using Sudoku puzzle patterns
- AEAD encryption layer: provides confidentiality and integrity
- Protocol layer: handles handshake, address transfer, etc.
func DefaultConfig ¶
func DefaultConfig() *ProtocolConfig
DefaultConfig returns a safe default configuration. Note: the returned config still requires Key, Table, ServerAddress (client) or TargetAddress (server).
func (*ProtocolConfig) Validate ¶
func (c *ProtocolConfig) Validate() error
Validate checks the configuration for correctness. Returns the first error found, or nil if the configuration is valid.
func (*ProtocolConfig) ValidateClient ¶
func (c *ProtocolConfig) ValidateClient() error
ValidateClient ensures the config carries the required client-side fields.
type ReverseManager ¶
type ReverseManager struct {
// contains filtered or unexported fields
}
ReverseManager is a server-side reverse registry + http.Handler.
A reverse client registers routes over a Sudoku tunnel; this manager then exposes them via HTTP path prefixes.
func NewReverseManager ¶
func NewReverseManager() *ReverseManager
func (*ReverseManager) HandleServerSession ¶
func (m *ReverseManager) HandleServerSession(conn net.Conn, userHash string, helloPayload []byte) error
HandleServerSession handles a reverse client registration connection.
helloPayload is the JSON registration payload from the control plane.
func (*ReverseManager) ServeEntry ¶
func (m *ReverseManager) ServeEntry(listenAddr string) error
ServeEntry listens on listenAddr and serves both HTTP reverse proxy requests (path-based routing) and raw TCP reverse forwarding (requires a route with Path=="") on the same port.
func (*ReverseManager) ServeHTTP ¶
func (m *ReverseManager) ServeHTTP(w http.ResponseWriter, r *http.Request)
type ReverseRoute ¶
type ReverseRoute struct {
Path string `json:"path"`
Target string `json:"target"`
StripPrefix *bool `json:"strip_prefix,omitempty"`
HostHeader string `json:"host_header,omitempty"`
}
ReverseRoute maps a public HTTP path prefix (or a raw TCP entry) to a client-side TCP target.
When Path is empty, the route becomes a raw TCP reverse mapping on the server entry (no HTTP). Only one TCP route is supported per entry.
type SessionKind ¶
type SessionKind uint8
SessionKind describes the payload type carried by a Sudoku tunnel connection after the handshake.
The first control-plane message selects the session mode.
const ( // SessionForward means the client will send a target address and then proxy TCP streams. SessionForward SessionKind = iota // SessionUoT means the tunnel carries UDP-over-TCP frames. SessionUoT // SessionMux means the tunnel carries a multiplexed stream session (single tunnel, multi-target). SessionMux // SessionReverse means the tunnel is used to register reverse proxy routes (server exposes client services). SessionReverse )
func ServerHandshakeSessionAuto ¶
func ServerHandshakeSessionAuto(rawConn net.Conn, cfg *ProtocolConfig) (net.Conn, SessionKind, string, error)
ServerHandshakeSessionAuto is like ServerHandshakeSessionAutoWithUserHash but omits the user hash.
func ServerHandshakeSessionAutoWithUserHash ¶
func ServerHandshakeSessionAutoWithUserHash(rawConn net.Conn, cfg *ProtocolConfig) (conn net.Conn, session SessionKind, targetAddr string, userHash string, sessionPayload []byte, err error)
ServerHandshakeSessionAutoWithUserHash upgrades the connection and auto-detects the session kind.
Returns:
- conn: the upgraded tunnel connection. The control-plane message is always consumed.
- session: the detected session kind
- targetAddr: valid only when session==SessionForward
- userHash: per-user handshake identifier (if available)
- sessionPayload: valid only when session==SessionReverse (the JSON registration payload)