Documentation
¶
Overview ¶
Package udpbara provides userspace UDP relay through SOCKS5 proxies.
It enables QUIC/HTTP3 and other UDP protocols to work through SOCKS5 proxies that require hostname-based authentication, without requiring root access, TUN interfaces, or system-wide routing changes.
Each tunnel maintains a single SOCKS5 UDP ASSOCIATE session and can multiplex multiple target destinations through the same proxy connection. Connections expose a real *net.UDPConn for full compatibility with quic-go (OOB/ECN support).
Basic usage:
conn, err := udpbara.Dial("socks5h://user:pass@proxy:10000", "target.com:443")
if err != nil { log.Fatal(err) }
defer conn.Close()
transport := &quic.Transport{Conn: conn.PacketConn()}
quicConn, err := transport.Dial(ctx, conn.RelayAddr(), tlsConfig, quicConfig)
Index ¶
- func ParseProxyURL(proxyURL string) (addr, user, pass string, err error)
- type Config
- type Connection
- type Logger
- type Manager
- func (m *Manager) AddTunnel(name, proxyURL string) (*Tunnel, error)
- func (m *Manager) AddTunnelContext(ctx context.Context, name, proxyURL string) (*Tunnel, error)
- func (m *Manager) CloseAll()
- func (m *Manager) Dial(name, proxyURL, target string) (*Connection, error)
- func (m *Manager) DialContext(ctx context.Context, name, proxyURL, target string) (*Connection, error)
- func (m *Manager) GetTunnel(name string) (*Tunnel, error)
- func (m *Manager) List() []string
- func (m *Manager) RemoveTunnel(name string) error
- type Stats
- type Tunnel
- func (t *Tunnel) Close() error
- func (t *Tunnel) Connect() error
- func (t *Tunnel) ConnectContext(ctx context.Context) error
- func (t *Tunnel) Dial(target string) (*Connection, error)
- func (t *Tunnel) DialContext(ctx context.Context, target string) (*Connection, error)
- func (t *Tunnel) Stats() TunnelStats
- type TunnelStats
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseProxyURL ¶
ParseProxyURL parses a SOCKS5 proxy URL and returns its components. Accepted formats:
socks5://user:pass@host:port socks5h://user:pass@host:port socks5://host:port (no auth)
Both socks5 and socks5h schemes are accepted (udpbara always preserves hostnames in SOCKS5 UDP headers regardless of scheme).
Types ¶
type Config ¶
type Config struct {
// ReadBufferSize is the UDP socket read buffer size in bytes.
// Default: 7MB (recommended for QUIC).
ReadBufferSize int
// WriteBufferSize is the UDP socket write buffer size in bytes.
// Default: 7MB (recommended for QUIC).
WriteBufferSize int
// TCPKeepAlive enables TCP keepalive on the SOCKS5 control connection.
// Default: true.
TCPKeepAlive bool
// TCPKeepAlivePeriod is the interval between TCP keepalive probes in seconds.
// Default: 30.
TCPKeepAlivePeriod int
// ConnectTimeout is the timeout for connecting to the SOCKS5 proxy in seconds.
// Default: 10.
ConnectTimeout int
// AutoReconnect enables automatic reconnection when the TCP control drops.
// Default: true.
AutoReconnect bool
// Logger is an optional logger for tunnel events.
// If nil, no logging is performed. Default: nil.
Logger Logger
}
Config holds configuration for a tunnel. All fields have sensible defaults via DefaultConfig(). Zero-value fields will not override defaults when passed to NewTunnel or Dial — use DefaultConfig() and modify specific fields instead.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with sensible defaults.
type Connection ¶
type Connection struct {
// contains filtered or unexported fields
}
Connection holds the resources for a single target connection through a tunnel. Use PacketConn() to get the *net.UDPConn for quic-go, and RelayAddr() for the address to pass to quic.Transport.Dial().
func Dial ¶
func Dial(proxyURL, target string, config ...Config) (*Connection, error)
Dial is a convenience function that creates a tunnel and dials a target in one call. Returns a *Connection with a real *net.UDPConn for quic-go compatibility. The caller must close the returned Connection when done.
Example:
conn, err := udpbara.Dial("socks5h://user:pass@proxy.com:10000", "target.com:443")
if err != nil { ... }
defer conn.Close()
func DialContext ¶
func DialContext(ctx context.Context, proxyURL, target string, config ...Config) (*Connection, error)
DialContext is a convenience function like Dial but respects context cancellation. The context is used for both the proxy connection and target DNS resolution.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() conn, err := udpbara.DialContext(ctx, "socks5h://user:pass@proxy:10000", "target.com:443")
func (*Connection) Close ¶
func (c *Connection) Close() error
Close shuts down this connection. If this Connection was created by the top-level Dial() function, it also closes the underlying tunnel.
func (*Connection) PacketConn ¶
func (c *Connection) PacketConn() *net.UDPConn
PacketConn returns the real *net.UDPConn for use with quic-go.
func (*Connection) RelayAddr ¶
func (c *Connection) RelayAddr() *net.UDPAddr
RelayAddr returns the address that QUIC should dial to.
func (*Connection) Stats ¶
func (c *Connection) Stats() Stats
Stats returns per-connection packet and byte counters.
func (*Connection) Target ¶
func (c *Connection) Target() string
Target returns the target address this connection was dialed to (e.g., "example.com:443").
func (*Connection) Tunnel ¶
func (c *Connection) Tunnel() *Tunnel
Tunnel returns the underlying Tunnel this connection belongs to. Useful for accessing tunnel-level Stats() on connections created via the top-level Dial().
type Logger ¶
type Logger interface {
// Debug logs a debug-level message (packet dispatch, connection registration).
Debug(msg string, args ...any)
// Info logs an info-level message (connect, disconnect, reconnect).
Info(msg string, args ...any)
// Error logs an error-level message (connection failures, protocol errors).
Error(msg string, args ...any)
}
Logger is an optional logging interface for tunnel events. Implement this to integrate with your application's logging framework.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages multiple named tunnels through different SOCKS5 proxies. It provides a higher-level API for applications that need to maintain connections through multiple proxy endpoints simultaneously. All methods are safe for concurrent use.
func NewManager ¶
NewManager creates a new tunnel manager with optional configuration. If no config is provided, DefaultConfig() is used for all tunnels.
func (*Manager) AddTunnel ¶
AddTunnel creates and connects a named tunnel through a SOCKS5 proxy. Returns an error if a tunnel with the same name already exists.
func (*Manager) AddTunnelContext ¶
AddTunnelContext is like AddTunnel but respects context cancellation.
func (*Manager) CloseAll ¶
func (m *Manager) CloseAll()
CloseAll stops and removes all tunnels managed by this Manager. All connections through all tunnels are closed.
func (*Manager) Dial ¶
func (m *Manager) Dial(name, proxyURL, target string) (*Connection, error)
Dial creates a connection through a named tunnel to a target. If the tunnel doesn't exist, it creates and connects one using the given proxyURL. If the tunnel already exists, proxyURL is ignored.
func (*Manager) DialContext ¶
func (m *Manager) DialContext(ctx context.Context, name, proxyURL, target string) (*Connection, error)
DialContext is like Dial but respects context cancellation.
func (*Manager) RemoveTunnel ¶
RemoveTunnel stops and removes a named tunnel. All connections through the tunnel are closed. Returns an error if the tunnel is not found.
type Stats ¶
Stats contains packet and byte counters. Used for both tunnel-level and connection-level statistics.
type Tunnel ¶
type Tunnel struct {
// contains filtered or unexported fields
}
Tunnel maintains a SOCKS5 UDP ASSOCIATE session through a single proxy. It can create multiple connections for different targets, all sharing the same proxy connection and UDP relay.
A Tunnel handles the full SOCKS5 lifecycle: TCP control connection, authentication, UDP relay setup, packet dispatch, and automatic reconnection. Use NewTunnel() to create, Connect() to establish, and Dial() to create connections.
func NewTunnel ¶
NewTunnel creates a new tunnel through a SOCKS5 proxy. Call Connect() to establish the SOCKS5 session, then Dial() to create connections.
func (*Tunnel) Connect ¶
Connect establishes the SOCKS5 UDP ASSOCIATE session with the proxy. This performs the TCP connection, SOCKS5 handshake, and UDP relay setup. It is safe to call multiple times — subsequent calls are no-ops if already connected. After Connect returns, call Dial() to create connections to targets.
func (*Tunnel) ConnectContext ¶
ConnectContext is like Connect but respects context cancellation and deadlines. Returns context.DeadlineExceeded or context.Canceled if the context expires before the connection is established.
func (*Tunnel) Dial ¶
func (t *Tunnel) Dial(target string) (*Connection, error)
Dial creates a new connection through this tunnel to the specified target. Returns a Connection with a real *net.UDPConn (fully compatible with quic-go).
The target format is "host:port" (e.g., "www.example.com:443"). Hostnames are preserved in the SOCKS5 UDP header for proxy-side DNS resolution and auth. The connection is also registered under resolved IP keys for response dispatch.
Multiple connections to different targets can share the same tunnel.
func (*Tunnel) DialContext ¶
DialContext is like Dial but respects context cancellation. The context is used for DNS resolution of the target hostname.
type TunnelStats ¶
type TunnelStats = Stats
TunnelStats is an alias for Stats for backward compatibility.