Files
inp2p/pkg/config/config.go
openclaw 91e3d4da2a feat: INP2P v0.1.0 — complete P2P tunneling system
Core modules (M1-M6):
- pkg/protocol: message format, encoding, NAT type enums
- pkg/config: server/client config structs, env vars, validation
- pkg/auth: CRC64 token, TOTP gen/verify, one-time relay tokens
- pkg/nat: UDP/TCP STUN client and server
- pkg/signal: WSS message dispatch, sync request/response
- pkg/punch: UDP/TCP hole punching + priority chain
- pkg/mux: stream multiplexer (7B frame: StreamID+Flags+Len)
- pkg/tunnel: mux-based port forwarding with stats
- pkg/relay: relay manager with TOTP auth + session bridging
- internal/server: signaling server (login/heartbeat/report/coordinator)
- internal/client: client (NAT detect/login/punch/relay/reconnect)
- cmd/inp2ps + cmd/inp2pc: main entrypoints with graceful shutdown

All tests pass: 16 tests across 5 packages
Code: 3559 lines core + 861 lines tests = 19 source files
2026-03-02 15:13:22 +08:00

162 lines
4.1 KiB
Go

// Package config provides shared configuration types.
package config
import (
"crypto/rand"
"encoding/hex"
"fmt"
"os"
"strconv"
)
const (
Version = "0.1.0"
DefaultWSPort = 27183 // WSS signaling
DefaultSTUNUDP1 = 27182 // UDP STUN port 1
DefaultSTUNUDP2 = 27183 // UDP STUN port 2
DefaultSTUNTCP1 = 27180 // TCP STUN port 1
DefaultSTUNTCP2 = 27181 // TCP STUN port 2
DefaultWebPort = 10088 // Web console
DefaultAPIPort = 10008 // REST API
DefaultMaxRelayLoad = 20
DefaultRelayPort = 27185
HeartbeatInterval = 30 // seconds
HeartbeatTimeout = 90 // seconds — 3x missed heartbeats → offline
)
// ServerConfig holds inp2ps configuration.
type ServerConfig struct {
WSPort int `json:"wsPort"`
STUNUDP1 int `json:"stunUDP1"`
STUNUDP2 int `json:"stunUDP2"`
STUNTCP1 int `json:"stunTCP1"`
STUNTCP2 int `json:"stunTCP2"`
WebPort int `json:"webPort"`
APIPort int `json:"apiPort"`
DBPath string `json:"dbPath"`
CertFile string `json:"certFile"`
KeyFile string `json:"keyFile"`
LogLevel int `json:"logLevel"` // 0=debug, 1=info, 2=warn, 3=error
Token uint64 `json:"token"` // master token for auth
JWTKey string `json:"jwtKey"` // auto-generated if empty
AdminUser string `json:"adminUser"`
AdminPass string `json:"adminPass"`
}
func DefaultServerConfig() ServerConfig {
return ServerConfig{
WSPort: DefaultWSPort,
STUNUDP1: DefaultSTUNUDP1,
STUNUDP2: DefaultSTUNUDP2,
STUNTCP1: DefaultSTUNTCP1,
STUNTCP2: DefaultSTUNTCP2,
WebPort: DefaultWebPort,
APIPort: DefaultAPIPort,
DBPath: "inp2ps.db",
LogLevel: 1,
AdminUser: "admin",
AdminPass: "admin123",
}
}
func (c *ServerConfig) FillFromEnv() {
if v := os.Getenv("INP2PS_WS_PORT"); v != "" {
c.WSPort, _ = strconv.Atoi(v)
}
if v := os.Getenv("INP2PS_WEB_PORT"); v != "" {
c.WebPort, _ = strconv.Atoi(v)
}
if v := os.Getenv("INP2PS_DB_PATH"); v != "" {
c.DBPath = v
}
if v := os.Getenv("INP2PS_TOKEN"); v != "" {
c.Token, _ = strconv.ParseUint(v, 10, 64)
}
if v := os.Getenv("INP2PS_CERT"); v != "" {
c.CertFile = v
}
if v := os.Getenv("INP2PS_KEY"); v != "" {
c.KeyFile = v
}
if c.JWTKey == "" {
b := make([]byte, 32)
rand.Read(b)
c.JWTKey = hex.EncodeToString(b)
}
}
func (c *ServerConfig) Validate() error {
if c.Token == 0 {
return fmt.Errorf("token is required (INP2PS_TOKEN or -token)")
}
return nil
}
// ClientConfig holds inp2pc configuration.
type ClientConfig struct {
ServerHost string `json:"serverHost"`
ServerPort int `json:"serverPort"`
Node string `json:"node"`
Token uint64 `json:"token"`
User string `json:"user,omitempty"`
Insecure bool `json:"insecure"` // skip TLS verify
// STUN ports (defaults match server defaults)
STUNUDP1 int `json:"stunUDP1,omitempty"`
STUNUDP2 int `json:"stunUDP2,omitempty"`
STUNTCP1 int `json:"stunTCP1,omitempty"`
STUNTCP2 int `json:"stunTCP2,omitempty"`
RelayEnabled bool `json:"relayEnabled"` // --relay
SuperRelay bool `json:"superRelay"` // --super
RelayPort int `json:"relayPort"`
MaxRelayLoad int `json:"maxRelayLoad"`
ShareBandwidth int `json:"shareBandwidth"` // Mbps
LogLevel int `json:"logLevel"`
Apps []AppConfig `json:"apps"`
}
type AppConfig struct {
AppName string `json:"appName"`
Protocol string `json:"protocol"` // tcp, udp
SrcPort int `json:"srcPort"`
PeerNode string `json:"peerNode"`
DstHost string `json:"dstHost"`
DstPort int `json:"dstPort"`
Enabled bool `json:"enabled"`
}
func DefaultClientConfig() ClientConfig {
return ClientConfig{
ServerPort: DefaultWSPort,
STUNUDP1: DefaultSTUNUDP1,
STUNUDP2: DefaultSTUNUDP2,
STUNTCP1: DefaultSTUNTCP1,
STUNTCP2: DefaultSTUNTCP2,
ShareBandwidth: 10,
RelayPort: DefaultRelayPort,
MaxRelayLoad: DefaultMaxRelayLoad,
LogLevel: 1,
}
}
func (c *ClientConfig) Validate() error {
if c.ServerHost == "" {
return fmt.Errorf("serverHost is required")
}
if c.Token == 0 {
return fmt.Errorf("token is required")
}
if c.Node == "" {
hostname, _ := os.Hostname()
c.Node = hostname
}
return nil
}