app

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: MIT Imports: 57 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AppVersion = "dev"

AppVersion is set by the api package at init time.

Functions

func CheckCapability added in v1.0.4

func CheckCapability() (bool, string)

func CheckHostNetwork

func CheckHostNetwork() bool

CheckHostNetwork returns true if the container appears to be running with --network host.

func CheckL2TPCapability

func CheckL2TPCapability() (bool, string)

CheckL2TPCapability tests if the runtime has NET_ADMIN and /dev/ppp. Returns (ok, reason).

func GenerateWireGuardClientConfig added in v1.1.0

func GenerateWireGuardClientConfig(serverCfg WireGuardConfig, peer WireGuardPeer, endpoint, dns string) string

GenerateWireGuardClientConfig generates a .conf file for a WireGuard peer.

func GenerateWireGuardKey added in v1.1.0

func GenerateWireGuardKey() (string, string)

GenerateWireGuardKey returns (privateKey, publicKey) base64.

func IsBondStream added in v1.2.0

func IsBondStream(addr string) bool

IsBondStream returns true if the address is a bond stream.

func PublicKeyFromPrivate added in v1.1.0

func PublicKeyFromPrivate(privB64 string) (string, error)

PublicKeyFromPrivate derives public key from base64 private key.

func RuleEngineAvailable added in v1.1.3

func RuleEngineAvailable() bool

RuleEngineAvailable returns true if the rule engine can operate.

func StopWireGuard added in v1.1.0

func StopWireGuard()

StopWireGuard stops the running WireGuard instance.

func TunCaptureActive added in v1.1.2

func TunCaptureActive() bool

TunCaptureActive returns true if TUN capture mode is in use.

func ValidateExitMode added in v1.2.0

func ValidateExitMode(exitVia, exitMode string) error

dialExit routes traffic through an exit path, stripping the local node name prefix. dialExitWithMode routes traffic with the specified exit mode. mode: "" = direct, "stability" = adaptive failover, "speed" = load balance ValidateExitMode checks exit_mode is only set for simple (non-path) exit_via.

func WGAddPeer added in v1.1.1

func WGAddPeer(peer WireGuardPeer) error

WGAddPeer adds a peer to the running WireGuard device without restarting.

func WGRemovePeer added in v1.1.1

func WGRemovePeer(publicKey string) error

WGRemovePeer removes a peer from the running WireGuard device without restarting.

func WGUpdatePeer added in v1.1.1

func WGUpdatePeer(peer WireGuardPeer) error

WGUpdatePeer updates a peer's WG-level config without restarting the device.

func WireGuardConnectedCount added in v1.1.0

func WireGuardConnectedCount() int

WireGuardConnectedCount returns the number of WG peers with active connections.

func WireGuardRunning added in v1.1.0

func WireGuardRunning() bool

WireGuardRunning returns true if WireGuard is active.

Types

type App

type App struct {
	Sessions *SessionManager
	// contains filtered or unexported fields
}

func New

func New(dataDir string) (*App, error)

func (*App) AddClient

func (a *App) AddClient(cl ClientEntry) error

func (*App) AddProxy

func (a *App) AddProxy(pc ProxyConfig) error

func (*App) AddRule added in v1.1.3

func (a *App) AddRule(r RoutingRule)

func (*App) AddUser

func (a *App) AddUser(u UserConfig) error

func (*App) ApplyRule added in v1.1.3

func (a *App) ApplyRule(r RoutingRule)

ApplyRule enables a routing rule (adds iptables + proxy mapping).

func (*App) DataDir added in v1.2.0

func (a *App) DataDir() string

func (*App) DeleteRule added in v1.1.3

func (a *App) DeleteRule(id string)

func (*App) FlushTraffic

func (a *App) FlushTraffic()

FlushTraffic persists dirty traffic counters to config.

func (*App) GetConfig added in v1.0.3

func (a *App) GetConfig() Config

func (*App) LookupUser

func (a *App) LookupUser(username, password string) (*UserConfig, error)

func (*App) Node

func (a *App) Node() *relay.Node

func (*App) PersistNodeID

func (a *App) PersistNodeID(id string)

PersistNodeID writes the node ID to the persistent file.

func (*App) ReconnectAll

func (a *App) ReconnectAll()

ReconnectAll stops and restarts all connections (outbound + hy2 server) after ID change. Restarting the server disconnects all inbound peers, forcing them to reconnect and see the new ID.

func (*App) RecordTraffic

func (a *App) RecordTraffic(username string, bytes int64)

func (*App) RemoveClient

func (a *App) RemoveClient(name string) error

func (*App) RemoveProxy

func (a *App) RemoveProxy(id string) error

func (*App) RemoveRule added in v1.1.3

func (a *App) RemoveRule(id string)

RemoveRule disables a routing rule (removes iptables + proxy mapping).

func (*App) RemoveUser

func (a *App) RemoveUser(id string) error

func (*App) ResetUserTraffic

func (a *App) ResetUserTraffic(id string) error

func (*App) RestartIKEv2 added in v1.1.3

func (a *App) RestartIKEv2() error

RestartIKEv2 stops and restarts the IKEv2 service with current config.

func (*App) RestartL2TP added in v1.1.3

func (a *App) RestartL2TP() error

RestartL2TP stops and restarts L2TP with current config.

func (*App) RestartSS

func (a *App) RestartSS()

RestartSS stops and restarts the SS server with current config.

func (*App) RestartServer added in v1.1.2

func (a *App) RestartServer()

RestartServer is the public wrapper for restartServer.

func (*App) Run

func (a *App) Run(ctx context.Context) error

func (*App) SetClientDisabled

func (a *App) SetClientDisabled(name string, disabled bool) error

func (*App) SetNested

func (a *App) SetNested(peer string, enabled bool) error

func (*App) StartClient

func (a *App) StartClient(cl ClientEntry)

func (*App) StartIKEv2

func (a *App) StartIKEv2(cfg IKEv2Config) error

StartIKEv2 configures and starts IKEv2/IPsec VPN.

func (*App) StartL2TP

func (a *App) StartL2TP(cfg L2TPConfig) error

StartL2TP sets up xl2tpd, strongswan, iptables, and the transparent proxy.

func (*App) StartProxy

func (a *App) StartProxy(pc ProxyConfig)

func (*App) StartRuleEngine added in v1.1.3

func (a *App) StartRuleEngine()

StartRuleEngine initializes the rule engine if in host network mode.

func (*App) StartSS

func (a *App) StartSS(cfg SSConfig)

StartSS starts the Shadowsocks server.

func (*App) StartTrafficFlusher

func (a *App) StartTrafficFlusher(ctx context.Context)

StartTrafficFlusher runs a background goroutine to periodically flush traffic.

func (*App) StartWireGuard added in v1.1.0

func (a *App) StartWireGuard(cfg WireGuardConfig) error

StartWireGuard starts userspace WireGuard with full traffic forwarding.

func (*App) StopClient

func (a *App) StopClient(name string)

func (*App) StopIKEv2 added in v1.1.3

func (a *App) StopIKEv2()

StopIKEv2 stops the IKEv2 service (kills strongswan connections, removes configs).

func (*App) StopL2TP added in v1.1.3

func (a *App) StopL2TP()

StopL2TP stops the L2TP service.

func (*App) StopProxy

func (a *App) StopProxy(id string)

func (*App) StopRuleEngine added in v1.1.3

func (a *App) StopRuleEngine()

StopRuleEngine removes all rules and stops the proxy.

func (*App) Store

func (a *App) Store() *ConfigStore

func (*App) TLS

func (a *App) TLS() *TLSStore

func (*App) ToggleRule added in v1.1.3

func (a *App) ToggleRule(id string, enabled bool)

func (*App) ToggleUser

func (a *App) ToggleUser(id string, enabled bool) error

func (*App) UpdateClient

func (a *App) UpdateClient(cl ClientEntry) error

func (*App) UpdateClientByAddr

func (a *App) UpdateClientByAddr(oldName string, cl ClientEntry) error

UpdateClientByAddr finds a client by oldName (name or addr) and replaces it.

func (*App) UpdateProxy

func (a *App) UpdateProxy(pc ProxyConfig) error

func (*App) UpdateRule added in v1.1.3

func (a *App) UpdateRule(id string, r RoutingRule)

func (*App) UpdateUser

func (a *App) UpdateUser(id string, u UserConfig) error

func (*App) UpdateWebCredentials added in v1.0.3

func (a *App) UpdateWebCredentials(username, passHash string)

type CertInfo

type CertInfo struct {
	ID         string `json:"id"`
	Name       string `json:"name"`
	Subject    string `json:"subject"`
	Issuer     string `json:"issuer"`
	NotAfter   string `json:"not_after"`
	IsCA       bool   `json:"is_ca"`
	KeyFile    string `json:"key_file,omitempty"`
	CertFile   string `json:"cert_file,omitempty"`
	CAParentID string `json:"ca_parent_id,omitempty"`
}

CertInfo describes a stored certificate.

type ClientEntry

type ClientEntry struct {
	Name     string   `yaml:"name" json:"name"`
	Addr     string   `yaml:"addr" json:"addr"`                       // primary address (backward compat)
	Addrs    []string `yaml:"addrs,omitempty" json:"addrs,omitempty"` // all addresses (including primary)
	Password string   `yaml:"password" json:"password"`

	// TLS
	SNI      string `yaml:"sni,omitempty" json:"sni"`
	Insecure bool   `yaml:"insecure" json:"insecure"`
	CA       string `yaml:"ca,omitempty" json:"ca"` // PEM content or path

	// Bandwidth (bytes/sec)
	MaxTx int `yaml:"max_tx,omitempty" json:"max_tx"`
	MaxRx int `yaml:"max_rx,omitempty" json:"max_rx"`

	// QUIC
	InitStreamWindow int `yaml:"init_stream_window,omitempty" json:"init_stream_window"`
	MaxStreamWindow  int `yaml:"max_stream_window,omitempty" json:"max_stream_window"`
	InitConnWindow   int `yaml:"init_conn_window,omitempty" json:"init_conn_window"`
	MaxConnWindow    int `yaml:"max_conn_window,omitempty" json:"max_conn_window"`

	// Connection mode for multi-IP: "" = direct (single IP), "stability", "speed"
	ConnMode string `yaml:"conn_mode,omitempty" json:"conn_mode,omitempty"`

	// Misc
	FastOpen bool `yaml:"fast_open,omitempty" json:"fast_open"`
	Disabled bool `yaml:"disabled,omitempty" json:"disabled"`
}

func (ClientEntry) AllAddrs added in v1.2.0

func (c ClientEntry) AllAddrs() []string

AllAddrs returns the effective address list. If Addrs is populated, returns it. Otherwise falls back to the single Addr field for backward compatibility.

func (ClientEntry) PrimaryAddr added in v1.2.0

func (c ClientEntry) PrimaryAddr() string

PrimaryAddr returns the first address (used as stable key and default connection).

type Config

type Config struct {
	NodeID          string                `yaml:"node_id" json:"node_id"`
	Name            string                `yaml:"name" json:"name"`
	ExitNode        bool                  `yaml:"exit_node" json:"exit_node"`
	Hy2UserAuth     bool                  `yaml:"hy2_user_auth,omitempty" json:"hy2_user_auth"`
	Server          *ServerConfig         `yaml:"server" json:"server"`
	Clients         []ClientEntry         `yaml:"clients" json:"clients"`
	Peers           map[string]PeerConfig `yaml:"peers" json:"peers"`
	SOCKS5          *SOCKS5Config         `yaml:"socks5,omitempty" json:"-"`
	Users           []UserConfig          `yaml:"users" json:"users"`
	Proxies         []ProxyConfig         `yaml:"proxies" json:"proxies"`
	SS              *SSConfig             `yaml:"ss,omitempty" json:"ss,omitempty"`
	L2TP            *L2TPConfig           `yaml:"l2tp,omitempty" json:"l2tp,omitempty"`
	IKEv2           *IKEv2Config          `yaml:"ikev2,omitempty" json:"ikev2,omitempty"`
	WireGuard       *WireGuardConfig      `yaml:"wireguard,omitempty" json:"wireguard,omitempty"`
	Rules           []RoutingRule         `yaml:"rules,omitempty" json:"rules,omitempty"`
	UIListen        string                `yaml:"ui_listen,omitempty" json:"ui_listen,omitempty"`
	UIBasePath      string                `yaml:"ui_base_path,omitempty" json:"ui_base_path,omitempty"`
	WebUsername     string                `yaml:"web_username,omitempty" json:"web_username,omitempty"`
	WebPassword     string                `yaml:"web_password,omitempty" json:"web_password,omitempty"`
	DNS             string                `yaml:"dns,omitempty" json:"dns,omitempty"`
	ForceHTTPS      bool                  `yaml:"force_https,omitempty" json:"force_https,omitempty"`
	HTTPSCertID     string                `yaml:"https_cert_id,omitempty" json:"https_cert_id,omitempty"`
	SessionTimeoutH int                   `yaml:"session_timeout_h,omitempty" json:"session_timeout_h,omitempty"` // hours, default 12
}

func LoadOrInitConfig

func LoadOrInitConfig(dataDir string) (Config, error)

LoadOrInitConfig loads persisted config from dataDir/config.yaml. If it doesn't exist, creates a fresh default config.

type ConfigStore

type ConfigStore struct {
	// contains filtered or unexported fields
}

ConfigStore manages dynamic configuration with persistence.

func NewConfigStore

func NewConfigStore(cfg Config, persistPath string) *ConfigStore

func (*ConfigStore) Get

func (s *ConfigStore) Get() Config

func (*ConfigStore) Update

func (s *ConfigStore) Update(fn func(*Config)) error

type Device added in v1.1.0

type Device struct {
	Key       string // username|ip|protocol
	Username  string
	RemoteIP  string
	Protocol  string // "socks5", "ss", "hy2", "l2tp", "ikev2"
	ConnectAt time.Time
	ConnCount atomic.Int32 // number of active TCP connections
	TxBytes   atomic.Int64
	RxBytes   atomic.Int64
	// contains filtered or unexported fields
}

Device represents an active client device, aggregated by (username, IP, protocol). Multiple TCP connections from the same device are counted, not listed separately.

type DeviceJSON added in v1.1.0

type DeviceJSON struct {
	Key       string `json:"key"`
	Username  string `json:"username"`
	RemoteIP  string `json:"remote_ip"`
	Protocol  string `json:"protocol"`
	ConnectAt int64  `json:"connect_at"`
	Duration  int    `json:"duration"`
	ConnCount int    `json:"conn_count"`
	TxBytes   int64  `json:"tx_bytes"`
	RxBytes   int64  `json:"rx_bytes"`
}

type IKEv2Config

type IKEv2Config struct {
	Enabled         bool   `yaml:"enabled" json:"enabled"`
	Mode            string `yaml:"mode" json:"mode"`                                               // "mschapv2" or "psk"
	Pool            string `yaml:"pool" json:"pool"`                                               // e.g. "10.10.10.1/24"
	CertID          string `yaml:"cert_id" json:"cert_id"`                                         // TLS cert ID (for mschapv2)
	PSK             string `yaml:"psk" json:"psk"`                                                 // pre-shared key (for psk mode)
	LocalID         string `yaml:"local_id" json:"local_id"`                                       // server identity (leftid), default = node ID
	RemoteID        string `yaml:"remote_id" json:"remote_id"`                                     // client identity (rightid), default = %any
	PSKUserMode     bool   `yaml:"psk_user_mode" json:"psk_user_mode"`                             // PSK: require user auth
	DefaultExit     string `yaml:"default_exit" json:"default_exit"`                               // exit_via when user mode off
	DefaultExitMode string `yaml:"default_exit_mode,omitempty" json:"default_exit_mode,omitempty"` // ""|"stability"|"speed"
	DNS             string `yaml:"dns" json:"dns"`                                                 // DNS servers, default "8.8.8.8 8.8.4.4"
	ProxyPort       int    `yaml:"proxy_port" json:"proxy_port"`                                   // transparent proxy port, default 12350
	MTU             int    `yaml:"mtu" json:"mtu"`                                                 // tunnel MTU, default 1400
}

IKEv2Config holds IKEv2/IPsec VPN configuration.

type L2TPConfig

type L2TPConfig struct {
	Listen    string `yaml:"listen" json:"listen"` // UDP port, e.g. "1701"
	Enabled   bool   `yaml:"enabled" json:"enabled"`
	Pool      string `yaml:"pool" json:"pool"`             // e.g. "192.168.25.1/24"
	PSK       string `yaml:"psk" json:"psk"`               // IPsec pre-shared key
	ProxyPort int    `yaml:"proxy_port" json:"proxy_port"` // transparent proxy port, default 12345
	MTU       int    `yaml:"mtu" json:"mtu"`               // PPP MTU, default 1280
}

L2TPConfig holds L2TP/IPsec server configuration.

type PeerConfig

type PeerConfig struct {
	Nested bool `yaml:"nested" json:"nested"`
}

type PortConflict added in v1.1.1

type PortConflict struct {
	Port  int    `json:"port"`
	Proto string `json:"proto"` // "tcp" or "udp"
	Desc  string `json:"desc"`  // what's using it
}

PortConflict describes a port that is already in use.

func CheckPorts added in v1.1.1

func CheckPorts(ports []PortConflict) []PortConflict

CheckPorts tests if the given ports are available. Returns a list of conflicts (empty if all available).

type ProxyConfig

type ProxyConfig struct {
	ID       string `yaml:"id" json:"id"`
	Protocol string `yaml:"protocol" json:"protocol"` // "socks5"
	Listen   string `yaml:"listen" json:"listen"`
	Enabled  bool   `yaml:"enabled" json:"enabled"`
	ExitVia  string `yaml:"exit_via,omitempty" json:"exit_via,omitempty"`
	ExitMode string `yaml:"exit_mode,omitempty" json:"exit_mode,omitempty"`
}

ProxyConfig defines a protocol listener.

type RoutingRule added in v1.1.3

type RoutingRule struct {
	ID       string   `yaml:"id" json:"id"`
	Name     string   `yaml:"name" json:"name"`
	Type     string   `yaml:"type" json:"type"`       // "ip" or "domain"
	Targets  []string `yaml:"targets" json:"targets"` // IPs/CIDRs/ranges or domains
	ExitVia  string   `yaml:"exit_via" json:"exit_via"`
	ExitMode string   `yaml:"exit_mode,omitempty" json:"exit_mode,omitempty"` // ""|"stability"|"speed"
	Enabled  bool     `yaml:"enabled" json:"enabled"`
}

RoutingRule defines a traffic routing rule (IP or domain based).

type SOCKS5Config

type SOCKS5Config struct {
	Listen  string `yaml:"listen"`
	ExitVia string `yaml:"exit_via"`
}

type SSConfig

type SSConfig struct {
	Listen  string `yaml:"listen" json:"listen"`
	Enabled bool   `yaml:"enabled" json:"enabled"`
	Method  string `yaml:"method" json:"method"` // aes-128-gcm, aes-256-gcm, chacha20-ietf-poly1305
}

SSConfig holds Shadowsocks server configuration.

type ServerConfig

type ServerConfig struct {
	Listen   string `yaml:"listen" json:"listen"`
	Password string `yaml:"password" json:"password"`
	TLSCert  string `yaml:"tls_cert" json:"tls_cert"`
	TLSKey   string `yaml:"tls_key" json:"tls_key"`
}

type SessionManager added in v1.1.0

type SessionManager struct {
	// contains filtered or unexported fields
}

SessionManager tracks active devices across proxy protocols. WireGuard is excluded — it has its own peer management.

func NewSessionManager added in v1.1.0

func NewSessionManager() *SessionManager

func (*SessionManager) Connect added in v1.1.0

func (m *SessionManager) Connect(username, remoteIP, protocol string, cancel func()) string

Connect registers a new connection from a device. Returns a connID for Disconnect. Returns empty string if blocked.

func (*SessionManager) Count added in v1.1.0

func (m *SessionManager) Count() int

Count returns total active devices.

func (*SessionManager) Disconnect added in v1.1.0

func (m *SessionManager) Disconnect(sessionID string, txBytes, rxBytes int64)

Disconnect removes a connection. If the device has no more connections, it's removed.

func (*SessionManager) IsBlocked added in v1.1.0

func (m *SessionManager) IsBlocked(username, remoteIP, protocol string) bool

IsBlocked checks if a device is temporarily blocked (kicked).

func (*SessionManager) Kick added in v1.1.0

func (m *SessionManager) Kick(key string) bool

Kick disconnects all connections for a device and blocks reconnection for 60s.

func (*SessionManager) List added in v1.1.0

func (m *SessionManager) List() []DeviceJSON

List returns all active devices.

type TLSStore

type TLSStore struct {
	// contains filtered or unexported fields
}

TLSStore manages certificates in the data directory.

func NewTLSStore

func NewTLSStore(dataDir string) *TLSStore

func (*TLSStore) CAParent added in v1.1.3

func (s *TLSStore) CAParent(id string) string

CAParent returns the CA ID that signed this cert, or empty string.

func (*TLSStore) CertPath

func (s *TLSStore) CertPath(id string) string

CertPath returns the file path for a cert (for hy2 server config).

func (*TLSStore) Delete

func (s *TLSStore) Delete(id string) error

Delete removes a certificate.

func (*TLSStore) Generate

func (s *TLSStore) Generate(id, name string, domains []string, days int) error

Generate creates a self-signed certificate.

func (*TLSStore) Get

func (s *TLSStore) Get(id string) (CertInfo, error)

Get returns a single certificate's info.

func (*TLSStore) GetPEM

func (s *TLSStore) GetPEM(id string) (string, error)

GetPEM returns the certificate PEM content.

func (*TLSStore) Import

func (s *TLSStore) Import(id, name, certPEM, keyPEM string) error

Import saves a certificate (and optional key) from PEM content.

func (*TLSStore) KeyPath

func (s *TLSStore) KeyPath(id string) string

KeyPath returns the file path for a key.

func (*TLSStore) List

func (s *TLSStore) List() ([]CertInfo, error)

List returns all certificates.

func (*TLSStore) SignWithCA added in v1.1.3

func (s *TLSStore) SignWithCA(caID, newID, name, cn string, days int) error

SignWithCA uses a CA certificate to sign a new server certificate.

type UserConfig

type UserConfig struct {
	ID           string `yaml:"id" json:"id"`
	Username     string `yaml:"username" json:"username"`
	Password     string `yaml:"password" json:"password"`
	ExitVia      string `yaml:"exit_via" json:"exit_via"`
	ExitMode     string `yaml:"exit_mode,omitempty" json:"exit_mode,omitempty"` // ""|"stability"|"speed"
	TrafficLimit int64  `yaml:"traffic_limit" json:"traffic_limit"`             // bytes, 0=unlimited
	TrafficUsed  int64  `yaml:"traffic_used" json:"traffic_used"`
	ExpiryDate   string `yaml:"expiry_date,omitempty" json:"expiry_date"`
	Enabled      bool   `yaml:"enabled" json:"enabled"`
}

UserConfig defines a client user with auth and exit routing.

type WireGuardConfig added in v1.1.0

type WireGuardConfig struct {
	Enabled    bool            `yaml:"enabled" json:"enabled"`
	ListenPort int             `yaml:"listen_port" json:"listen_port"`
	PrivateKey string          `yaml:"private_key" json:"private_key"`
	Address    string          `yaml:"address" json:"address"`
	DNS        string          `yaml:"dns,omitempty" json:"dns,omitempty"`
	MTU        int             `yaml:"mtu,omitempty" json:"mtu,omitempty"`
	Peers      []WireGuardPeer `yaml:"peers" json:"peers"`
}

WireGuardConfig stored in config.yaml.

type WireGuardPeer added in v1.1.0

type WireGuardPeer struct {
	Name       string `yaml:"name" json:"name"`
	PublicKey  string `yaml:"public_key" json:"public_key"`
	PrivateKey string `yaml:"private_key" json:"private_key"`
	AllowedIPs string `yaml:"allowed_ips" json:"allowed_ips"`
	Keepalive  int    `yaml:"keepalive" json:"keepalive"`
	ExitVia    string `yaml:"exit_via,omitempty" json:"exit_via"`
	ExitMode   string `yaml:"exit_mode,omitempty" json:"exit_mode,omitempty"`
}

WireGuardPeer is a peer entry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL