Documentation
¶
Index ¶
- type AccessLogger
- func (al *AccessLogger) Close()
- func (al *AccessLogger) EndTCPSession(sessionID string)
- func (al *AccessLogger) EndUDPSession(sessionID string)
- func (al *AccessLogger) SetSendFunc(fn SendFunc)
- func (al *AccessLogger) StartTCPSession(resourceID int, srcAddr, dstAddr string) string
- func (al *AccessLogger) TrackUDPSession(resourceID int, srcAddr, dstAddr string) string
- type AccessSession
- type HTTPHandler
- type HTTPRequestLog
- type HTTPRequestLogger
- type HTTPTarget
- type ICMPHandler
- type Net
- func (net *Net) AddProxySubnetRule(rule SubnetRule)
- func (tnet *Net) Dial(network, address string) (net.Conn, error)
- func (tnet *Net) DialContext(ctx context.Context, network, address string) (net.Conn, error)
- func (net *Net) DialContextTCP(ctx context.Context, addr *net.TCPAddr) (*gonet.TCPConn, error)
- func (net *Net) DialContextTCPAddrPort(ctx context.Context, addr netip.AddrPort) (*gonet.TCPConn, error)
- func (net *Net) DialPing(laddr, raddr *PingAddr) (*PingConn, error)
- func (net *Net) DialPingAddr(laddr, raddr netip.Addr) (*PingConn, error)
- func (net *Net) DialTCP(addr *net.TCPAddr) (*gonet.TCPConn, error)
- func (net *Net) DialTCPAddrPort(addr netip.AddrPort) (*gonet.TCPConn, error)
- func (net *Net) DialUDP(laddr, raddr *net.UDPAddr) (*gonet.UDPConn, error)
- func (net *Net) DialUDPAddrPort(laddr, raddr netip.AddrPort) (*gonet.UDPConn, error)
- func (net *Net) GetProxyHandler() *ProxyHandler
- func (net *Net) GetProxySubnetRules() []SubnetRule
- func (net *Net) ListenPing(laddr *PingAddr) (*PingConn, error)
- func (net *Net) ListenPingAddr(laddr netip.Addr) (*PingConn, error)
- func (net *Net) ListenTCP(addr *net.TCPAddr) (*gonet.TCPListener, error)
- func (net *Net) ListenTCPAddrPort(addr netip.AddrPort) (*gonet.TCPListener, error)
- func (net *Net) ListenUDP(laddr *net.UDPAddr) (*gonet.UDPConn, error)
- func (net *Net) ListenUDPAddrPort(laddr netip.AddrPort) (*gonet.UDPConn, error)
- func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string, error)
- func (net *Net) LookupHost(host string) (addrs []string, err error)
- func (net *Net) RemoveProxySubnetRule(sourcePrefix, destPrefix netip.Prefix)
- func (net *Net) SetAccessLogSender(fn SendFunc)
- func (net *Net) SetHTTPRequestLogSender(fn SendFunc)
- type NetTunOptions
- type PingAddr
- type PingConn
- func (pc *PingConn) Close() error
- func (pc *PingConn) LocalAddr() net.Addr
- func (pc *PingConn) Read(p []byte) (n int, err error)
- func (pc *PingConn) ReadFrom(p []byte) (n int, addr net.Addr, err error)
- func (pc *PingConn) RemoteAddr() net.Addr
- func (pc *PingConn) SetDeadline(t time.Time) error
- func (pc *PingConn) SetReadDeadline(t time.Time) error
- func (pc *PingConn) SetWriteDeadline(t time.Time) error
- func (pc *PingConn) Write(p []byte) (n int, err error)
- func (pc *PingConn) WriteTo(p []byte, addr net.Addr) (n int, err error)
- type PortRange
- type ProxyHandler
- func (p *ProxyHandler) AddSubnetRule(rule SubnetRule)
- func (p *ProxyHandler) Close() error
- func (p *ProxyHandler) GetAccessLogger() *AccessLogger
- func (p *ProxyHandler) GetAllRules() []SubnetRule
- func (p *ProxyHandler) GetHTTPRequestLogger() *HTTPRequestLogger
- func (p *ProxyHandler) HandleIncomingPacket(packet []byte) bool
- func (p *ProxyHandler) Initialize(notifiable channel.Notification) error
- func (p *ProxyHandler) LookupDestinationRewrite(srcIP, dstIP string, dstPort uint16, proto uint8) (netip.Addr, bool)
- func (p *ProxyHandler) LookupResourceId(srcIP, dstIP string, dstPort uint16, proto uint8) int
- func (p *ProxyHandler) QueueICMPReply(packet []byte) bool
- func (p *ProxyHandler) ReadOutgoingPacket() *buffer.View
- func (p *ProxyHandler) RemoveSubnetRule(sourcePrefix, destPrefix netip.Prefix)
- func (p *ProxyHandler) SetAccessLogSender(fn SendFunc)
- func (p *ProxyHandler) SetHTTPRequestLogSender(fn SendFunc)
- type ProxyHandlerOptions
- type SendFunc
- type SubnetLookup
- type SubnetRule
- type TCPHandler
- type UDPHandler
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AccessLogger ¶ added in v1.11.0
type AccessLogger struct {
// contains filtered or unexported fields
}
AccessLogger tracks access sessions for resources and periodically flushes completed sessions to the server via a configurable SendFunc.
func NewAccessLogger ¶ added in v1.11.0
func NewAccessLogger(udpTimeout time.Duration) *AccessLogger
NewAccessLogger creates a new access logger. udpTimeout controls how long a UDP session is kept alive without traffic before being ended.
func (*AccessLogger) Close ¶ added in v1.11.0
func (al *AccessLogger) Close()
Close shuts down the background loop, ends all active sessions, and performs one final flush to send everything to the server.
func (*AccessLogger) EndTCPSession ¶ added in v1.11.0
func (al *AccessLogger) EndTCPSession(sessionID string)
EndTCPSession logs the end of a TCP session and queues it for sending.
func (*AccessLogger) EndUDPSession ¶ added in v1.11.0
func (al *AccessLogger) EndUDPSession(sessionID string)
EndUDPSession ends a UDP session and queues it for sending.
func (*AccessLogger) SetSendFunc ¶ added in v1.11.0
func (al *AccessLogger) SetSendFunc(fn SendFunc)
SetSendFunc sets the callback used to send compressed access log batches to the server. This can be called after construction once the websocket client is available.
func (*AccessLogger) StartTCPSession ¶ added in v1.11.0
func (al *AccessLogger) StartTCPSession(resourceID int, srcAddr, dstAddr string) string
StartTCPSession logs the start of a TCP session and returns a session ID.
func (*AccessLogger) TrackUDPSession ¶ added in v1.11.0
func (al *AccessLogger) TrackUDPSession(resourceID int, srcAddr, dstAddr string) string
TrackUDPSession starts or returns an existing UDP session. Returns the session ID.
type AccessSession ¶ added in v1.11.0
type AccessSession struct {
SessionID string `json:"sessionId"`
ResourceID int `json:"resourceId"`
SourceAddr string `json:"sourceAddr"`
DestAddr string `json:"destAddr"`
Protocol string `json:"protocol"`
StartedAt time.Time `json:"startedAt"`
EndedAt time.Time `json:"endedAt,omitempty"`
BytesTx int64 `json:"bytesTx"`
BytesRx int64 `json:"bytesRx"`
ConnectionCount int `json:"connectionCount,omitempty"` // number of raw connections merged into this session (0 or 1 = single)
}
AccessSession represents a tracked access session through the proxy
type HTTPHandler ¶
type HTTPHandler struct {
// contains filtered or unexported fields
}
HTTPHandler intercepts TCP connections from the netstack forwarder on ports 80 and 443 and services them as HTTP or HTTPS, reverse-proxying each request to downstream targets specified by the matching SubnetRule.
HTTP and raw TCP are fully separate: a connection is only routed here when its SubnetRule has Protocol set ("http" or "https"). All other connections on those ports fall through to the normal raw-TCP path.
Incoming TLS termination (Protocol == "https") is performed per-connection using the certificate and key stored in the rule, so different subnet rules can present different certificates without sharing any state.
Outbound connections to downstream targets honour HTTPTarget.UseHTTPS independently of the incoming protocol.
func NewHTTPHandler ¶
func NewHTTPHandler(s *stack.Stack, ph *ProxyHandler) *HTTPHandler
NewHTTPHandler creates an HTTPHandler attached to the given stack and ProxyHandler. Call Start to begin serving connections.
func (*HTTPHandler) Close ¶
func (h *HTTPHandler) Close() error
Close gracefully shuts down the HTTP server and the underlying channel listener, causing the goroutine started in Start to exit.
func (*HTTPHandler) HandleConn ¶
func (h *HTTPHandler) HandleConn(conn net.Conn, rule *SubnetRule)
HandleConn accepts a TCP connection from the netstack forwarder together with the SubnetRule that matched it. The HTTP handler takes full ownership of the connection's lifecycle; the caller must NOT close conn after this call.
When rule.Protocol is "https", TLS termination is performed on conn using the certificate and key stored in rule.TLSCert and rule.TLSKey before the connection is passed to the HTTP server. The HTTP server itself is always plain-HTTP; TLS is fully unwrapped at this layer.
func (*HTTPHandler) SetRequestLogger ¶
func (h *HTTPHandler) SetRequestLogger(rl *HTTPRequestLogger)
SetRequestLogger attaches an HTTPRequestLogger so that every proxied request is recorded and periodically shipped to the server.
func (*HTTPHandler) Start ¶
func (h *HTTPHandler) Start() error
Start launches the internal http.Server that services connections delivered via HandleConn. The server runs for the lifetime of the HTTPHandler; call Close to stop it.
type HTTPRequestLog ¶
type HTTPRequestLog struct {
RequestID string `json:"requestId"`
ResourceID int `json:"resourceId"`
Timestamp time.Time `json:"timestamp"`
Method string `json:"method"`
Scheme string `json:"scheme"`
Host string `json:"host"`
Path string `json:"path"`
RawQuery string `json:"rawQuery,omitempty"`
UserAgent string `json:"userAgent,omitempty"`
SourceAddr string `json:"sourceAddr"`
TLS bool `json:"tls"`
}
HTTPRequestLog represents a single HTTP/HTTPS request proxied through the handler.
type HTTPRequestLogger ¶
type HTTPRequestLogger struct {
// contains filtered or unexported fields
}
HTTPRequestLogger buffers HTTP request logs and periodically flushes them to the server via a configurable SendFunc.
func NewHTTPRequestLogger ¶
func NewHTTPRequestLogger() *HTTPRequestLogger
NewHTTPRequestLogger creates a new HTTPRequestLogger and starts its background flush loop.
func (*HTTPRequestLogger) Close ¶
func (rl *HTTPRequestLogger) Close()
Close shuts down the background loop and performs one final flush to send any remaining buffered requests to the server.
func (*HTTPRequestLogger) LogRequest ¶
func (rl *HTTPRequestLogger) LogRequest(log HTTPRequestLog)
LogRequest adds an HTTP request log entry to the buffer. If the buffer reaches maxBufferedSessions entries a flush is triggered immediately.
func (*HTTPRequestLogger) SetSendFunc ¶
func (rl *HTTPRequestLogger) SetSendFunc(fn SendFunc)
SetSendFunc sets the callback used to send compressed HTTP request log batches to the server. This can be called after construction once the websocket client is available.
type HTTPTarget ¶
type HTTPTarget struct {
DestAddr string `json:"destAddr"` // IP address or hostname of the downstream service
DestPort uint16 `json:"destPort"` // TCP port of the downstream service
Scheme string `json:"scheme"` // When true the outbound leg uses HTTPS
}
HTTPTarget describes a single downstream HTTP or HTTPS service that the proxy should forward requests to.
type ICMPHandler ¶
type ICMPHandler struct {
// contains filtered or unexported fields
}
ICMPHandler handles ICMP packets from netstack
func NewICMPHandler ¶
func NewICMPHandler(s *stack.Stack, ph *ProxyHandler) *ICMPHandler
NewICMPHandler creates a new ICMP handler
func (*ICMPHandler) InstallICMPHandler ¶
func (h *ICMPHandler) InstallICMPHandler() error
InstallICMPHandler installs the ICMP handler on the stack
type Net ¶
type Net netTun
func CreateNetTUN ¶
CreateNetTUN creates a new TUN device with netstack without proxying
func CreateNetTUNWithOptions ¶
func CreateNetTUNWithOptions(localAddresses, dnsServers []netip.Addr, mtu int, options NetTunOptions) (tun.Device, *Net, error)
CreateNetTUNWithOptions creates a new TUN device with netstack and optional TCP/UDP proxying
func (*Net) AddProxySubnetRule ¶
func (net *Net) AddProxySubnetRule(rule SubnetRule)
AddProxySubnetRule adds a subnet rule to the proxy handler. HTTP proxy behaviour is configured via rule.Protocol, rule.HTTPTargets, rule.TLSCert, and rule.TLSKey; leave Protocol empty for raw TCP/UDP.
func (*Net) DialContext ¶
func (*Net) DialContextTCP ¶
func (*Net) DialContextTCPAddrPort ¶
func (*Net) DialTCPAddrPort ¶
func (*Net) DialUDPAddrPort ¶
func (*Net) GetProxyHandler ¶
func (net *Net) GetProxyHandler() *ProxyHandler
GetProxyHandler returns the proxy handler (for advanced use cases) Returns nil if proxy is not enabled
func (*Net) GetProxySubnetRules ¶ added in v1.11.0
func (net *Net) GetProxySubnetRules() []SubnetRule
GetProxySubnetRules returns all subnet rules from the proxy handler
func (*Net) ListenTCPAddrPort ¶
func (*Net) ListenUDPAddrPort ¶
func (*Net) LookupContextHost ¶
func (*Net) RemoveProxySubnetRule ¶
RemoveProxySubnetRule removes a subnet rule from the proxy handler
func (*Net) SetAccessLogSender ¶ added in v1.11.0
SetAccessLogSender configures the function used to send compressed access log batches to the server. This should be called once the websocket client is available.
func (*Net) SetHTTPRequestLogSender ¶
SetHTTPRequestLogSender configures the function used to send compressed HTTP request log batches to the server. This should be called once the websocket client is available.
type NetTunOptions ¶
NetTunOptions contains options for creating a NetTUN device
type PingAddr ¶
type PingAddr struct {
// contains filtered or unexported fields
}
func PingAddrFromAddr ¶
type PingConn ¶
type PingConn struct {
// contains filtered or unexported fields
}
func (*PingConn) RemoteAddr ¶
type PortRange ¶
PortRange represents an allowed range of ports (inclusive) with optional protocol filtering Protocol can be "tcp", "udp", or "" (empty string means both protocols)
type ProxyHandler ¶
type ProxyHandler struct {
// contains filtered or unexported fields
}
ProxyHandler handles packet injection and extraction for promiscuous mode
func NewProxyHandler ¶
func NewProxyHandler(options ProxyHandlerOptions) (*ProxyHandler, error)
NewProxyHandler creates a new proxy handler for promiscuous mode
func (*ProxyHandler) AddSubnetRule ¶
func (p *ProxyHandler) AddSubnetRule(rule SubnetRule)
AddSubnetRule adds a subnet rule to the proxy handler. HTTP proxy behaviour is configured via rule.Protocol, rule.HTTPTargets, rule.TLSCert, and rule.TLSKey; leave Protocol empty for raw TCP/UDP.
func (*ProxyHandler) Close ¶
func (p *ProxyHandler) Close() error
Close cleans up the proxy handler resources
func (*ProxyHandler) GetAccessLogger ¶ added in v1.11.0
func (p *ProxyHandler) GetAccessLogger() *AccessLogger
GetAccessLogger returns the access logger for session tracking
func (*ProxyHandler) GetAllRules ¶ added in v1.11.0
func (p *ProxyHandler) GetAllRules() []SubnetRule
GetAllRules returns all subnet rules from the proxy handler
func (*ProxyHandler) GetHTTPRequestLogger ¶
func (p *ProxyHandler) GetHTTPRequestLogger() *HTTPRequestLogger
GetHTTPRequestLogger returns the HTTP request logger.
func (*ProxyHandler) HandleIncomingPacket ¶
func (p *ProxyHandler) HandleIncomingPacket(packet []byte) bool
HandleIncomingPacket processes incoming packets and determines if they should be injected into the proxy stack
func (*ProxyHandler) Initialize ¶
func (p *ProxyHandler) Initialize(notifiable channel.Notification) error
Initialize sets up the promiscuous NIC with the netTun's notification system
func (*ProxyHandler) LookupDestinationRewrite ¶
func (p *ProxyHandler) LookupDestinationRewrite(srcIP, dstIP string, dstPort uint16, proto uint8) (netip.Addr, bool)
LookupDestinationRewrite looks up the rewritten destination for a connection This is used by TCP/UDP handlers to find the actual target address
func (*ProxyHandler) LookupResourceId ¶ added in v1.11.0
func (p *ProxyHandler) LookupResourceId(srcIP, dstIP string, dstPort uint16, proto uint8) int
LookupResourceId looks up the resource ID for a connection Returns 0 if no resource ID is associated with this connection
func (*ProxyHandler) QueueICMPReply ¶
func (p *ProxyHandler) QueueICMPReply(packet []byte) bool
QueueICMPReply queues an ICMP reply packet to be sent back through the tunnel
func (*ProxyHandler) ReadOutgoingPacket ¶
func (p *ProxyHandler) ReadOutgoingPacket() *buffer.View
ReadOutgoingPacket reads packets from the proxy stack that need to be sent back through the tunnel
func (*ProxyHandler) RemoveSubnetRule ¶
func (p *ProxyHandler) RemoveSubnetRule(sourcePrefix, destPrefix netip.Prefix)
RemoveSubnetRule removes a subnet from the proxy handler
func (*ProxyHandler) SetAccessLogSender ¶ added in v1.11.0
func (p *ProxyHandler) SetAccessLogSender(fn SendFunc)
SetAccessLogSender configures the function used to send compressed access log batches to the server. This should be called once the websocket client is available.
func (*ProxyHandler) SetHTTPRequestLogSender ¶
func (p *ProxyHandler) SetHTTPRequestLogSender(fn SendFunc)
SetHTTPRequestLogSender configures the function used to send compressed HTTP request log batches to the server. This should be called once the websocket client is available.
type ProxyHandlerOptions ¶
ProxyHandlerOptions configures the proxy handler
type SendFunc ¶ added in v1.11.0
SendFunc is a callback that sends compressed access log data to the server. The data is a base64-encoded zlib-compressed JSON array of AccessSession objects.
type SubnetLookup ¶
type SubnetLookup struct {
// contains filtered or unexported fields
}
SubnetLookup provides fast IP subnet and port matching using BART (Binary Aggregated Range Tree) This uses BART Table for O(log n) prefix matching with Supernets() for efficient lookups
Architecture: - Two-level BART structure for matching both source AND destination prefixes - Level 1: Source prefix -> Level 2 (destination prefix -> rules) - This reduces search space: only check destination prefixes for matching source prefixes
func NewSubnetLookup ¶
func NewSubnetLookup() *SubnetLookup
NewSubnetLookup creates a new subnet lookup table using BART
func (*SubnetLookup) AddSubnet ¶
func (sl *SubnetLookup) AddSubnet(rule SubnetRule)
AddSubnet adds a subnet rule to the lookup table. If rule.PortRanges is nil or empty, all ports are allowed. rule.RewriteTo can be either an IP/CIDR (e.g., "192.168.1.1/32") or a domain name (e.g., "example.com"). HTTP proxy behaviour is driven by rule.Protocol, rule.HTTPTargets, rule.TLSCert, and rule.TLSKey.
func (*SubnetLookup) GetAllRules ¶ added in v1.11.0
func (sl *SubnetLookup) GetAllRules() []SubnetRule
GetAllRules returns a copy of all subnet rules
func (*SubnetLookup) Match ¶
func (sl *SubnetLookup) Match(srcIP, dstIP netip.Addr, port uint16, proto tcpip.TransportProtocolNumber) *SubnetRule
Match checks if a source IP, destination IP, port, and protocol match any subnet rule Returns the matched rule if ALL of these conditions are met:
- The source IP is in the rule's source prefix
- The destination IP is in the rule's destination prefix
- The port is in an allowed range (or no port restrictions exist)
- The protocol matches (or the port range allows both protocols)
proto should be header.TCPProtocolNumber, header.UDPProtocolNumber, or header.ICMPv4ProtocolNumber Returns nil if no rule matches This uses BART's Supernets() for O(log n) prefix matching instead of O(n) iteration
func (*SubnetLookup) RemoveSubnet ¶
func (sl *SubnetLookup) RemoveSubnet(sourcePrefix, destPrefix netip.Prefix)
RemoveSubnet removes a subnet rule from the lookup table
type SubnetRule ¶
type SubnetRule struct {
SourcePrefix netip.Prefix // Source IP prefix (who is sending)
DestPrefix netip.Prefix // Destination IP prefix (where it's going)
DisableIcmp bool // If true, ICMP traffic is blocked for this subnet
RewriteTo string // Optional rewrite address for DNAT - can be IP/CIDR or domain name
PortRanges []PortRange // empty slice means all ports allowed
ResourceId int // Optional resource ID from the server for access logging
// HTTP proxy configuration (optional).
// When Protocol is non-empty the TCP connection is handled by HTTPHandler
// instead of the raw TCP forwarder.
Protocol string // "", "http", or "https" — controls the incoming (client-facing) protocol
HTTPTargets []HTTPTarget // downstream services to proxy requests to
TLSCert string // PEM-encoded certificate for incoming HTTPS termination
TLSKey string // PEM-encoded private key for incoming HTTPS termination
}
SubnetRule represents a subnet with optional port restrictions and source address When RewriteTo is set, DNAT (Destination Network Address Translation) is performed:
- Incoming packets: destination IP is rewritten to the resolved RewriteTo address
- Outgoing packets: source IP is rewritten back to the original destination
RewriteTo can be either:
- An IP address with CIDR notation (e.g., "192.168.1.1/32")
- A domain name (e.g., "example.com") which will be resolved at request time
This allows transparent proxying where traffic appears to come from the rewritten address
type TCPHandler ¶
type TCPHandler struct {
// contains filtered or unexported fields
}
TCPHandler handles TCP connections from netstack
func NewTCPHandler ¶
func NewTCPHandler(s *stack.Stack, ph *ProxyHandler) *TCPHandler
NewTCPHandler creates a new TCP handler
func (*TCPHandler) InstallTCPHandler ¶
func (h *TCPHandler) InstallTCPHandler() error
InstallTCPHandler installs the TCP forwarder on the stack
type UDPHandler ¶
type UDPHandler struct {
// contains filtered or unexported fields
}
UDPHandler handles UDP connections from netstack
func NewUDPHandler ¶
func NewUDPHandler(s *stack.Stack, ph *ProxyHandler) *UDPHandler
NewUDPHandler creates a new UDP handler
func (*UDPHandler) InstallUDPHandler ¶
func (h *UDPHandler) InstallUDPHandler() error
InstallUDPHandler installs the UDP forwarder on the stack