Fixed WG port issues and production firewall fixes

This commit is contained in:
anonpenguin23 2026-02-10 09:39:26 +02:00
parent a02c63a7ee
commit 21e82abb65
12 changed files with 118 additions and 15 deletions

View File

@ -86,7 +86,7 @@ test-e2e-quick:
.PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports install-hooks kill
VERSION := 0.101.3
VERSION := 0.101.4
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)'

View File

@ -33,7 +33,8 @@ type Flags struct {
// Security flags
SkipFirewall bool // Skip UFW firewall setup (for users who manage their own firewall)
// Anyone relay operator flags
// Anyone flags
AnyoneClient bool // Run Anyone as client-only (SOCKS5 proxy on port 9050, no relay)
AnyoneRelay bool // Run as relay operator instead of client
AnyoneExit bool // Run as exit relay (legal implications)
AnyoneMigrate bool // Migrate existing Anyone installation
@ -80,7 +81,8 @@ func ParseFlags(args []string) (*Flags, error) {
// Security flags
fs.BoolVar(&flags.SkipFirewall, "skip-firewall", false, "Skip UFW firewall setup (for users who manage their own firewall)")
// Anyone relay operator flags
// Anyone flags
fs.BoolVar(&flags.AnyoneClient, "anyone-client", false, "Install Anyone as client-only (SOCKS5 proxy on port 9050, no relay)")
fs.BoolVar(&flags.AnyoneRelay, "anyone-relay", false, "Run as Anyone relay operator (earn rewards)")
fs.BoolVar(&flags.AnyoneExit, "anyone-exit", false, "Run as exit relay (requires --anyone-relay, legal implications)")
fs.BoolVar(&flags.AnyoneMigrate, "anyone-migrate", false, "Migrate existing Anyone installation into Orama Network")

View File

@ -47,7 +47,10 @@ func NewOrchestrator(flags *Flags) (*Orchestrator, error) {
setup := production.NewProductionSetup(oramaHome, os.Stdout, flags.Force, flags.Branch, flags.NoPull, flags.SkipChecks, flags.PreBuilt)
setup.SetNameserver(flags.Nameserver)
// Configure Anyone relay if enabled
// Configure Anyone mode
if flags.AnyoneRelay && flags.AnyoneClient {
return nil, fmt.Errorf("--anyone-relay and --anyone-client are mutually exclusive")
}
if flags.AnyoneRelay {
setup.SetAnyoneRelayConfig(&production.AnyoneRelayConfig{
Enabled: true,
@ -61,6 +64,8 @@ func NewOrchestrator(flags *Flags) (*Orchestrator, error) {
BandwidthPct: flags.AnyoneBandwidth,
AccountingMax: flags.AnyoneAccounting,
})
} else if flags.AnyoneClient {
setup.SetAnyoneClient(true)
}
validator := NewValidator(flags, oramaDir)
@ -118,10 +123,11 @@ func (o *Orchestrator) Execute() error {
}
}
// Save preferences for future upgrades (branch + nameserver)
// Save preferences for future upgrades
prefs := &production.NodePreferences{
Branch: o.flags.Branch,
Nameserver: o.flags.Nameserver,
Branch: o.flags.Branch,
Nameserver: o.flags.Nameserver,
AnyoneClient: o.flags.AnyoneClient,
}
if err := production.SavePreferences(o.oramaDir, prefs); err != nil {
fmt.Fprintf(os.Stderr, "⚠️ Warning: Failed to save preferences: %v\n", err)

View File

@ -16,7 +16,8 @@ type Flags struct {
Branch string
Nameserver *bool // Pointer so we can detect if explicitly set vs default
// Anyone relay operator flags
// Anyone flags
AnyoneClient bool
AnyoneRelay bool
AnyoneExit bool
AnyoneMigrate bool
@ -46,7 +47,8 @@ func ParseFlags(args []string) (*Flags, error) {
// Nameserver flag - use pointer to detect if explicitly set
nameserver := fs.Bool("nameserver", false, "Make this node a nameserver (uses saved preference if not specified)")
// Anyone relay operator flags
// Anyone flags
fs.BoolVar(&flags.AnyoneClient, "anyone-client", false, "Install Anyone as client-only (SOCKS5 proxy on port 9050, no relay)")
fs.BoolVar(&flags.AnyoneRelay, "anyone-relay", false, "Run as Anyone relay operator (earn rewards)")
fs.BoolVar(&flags.AnyoneExit, "anyone-exit", false, "Run as exit relay (requires --anyone-relay, legal implications)")
fs.BoolVar(&flags.AnyoneMigrate, "anyone-migrate", false, "Migrate existing Anyone installation into Orama Network")

View File

@ -47,7 +47,7 @@ func NewOrchestrator(flags *Flags) *Orchestrator {
setup := production.NewProductionSetup(oramaHome, os.Stdout, flags.Force, branch, flags.NoPull, flags.SkipChecks, flags.PreBuilt)
setup.SetNameserver(isNameserver)
// Configure Anyone relay if enabled
// Configure Anyone mode (flag > saved preference)
if flags.AnyoneRelay {
setup.SetAnyoneRelayConfig(&production.AnyoneRelayConfig{
Enabled: true,
@ -61,6 +61,8 @@ func NewOrchestrator(flags *Flags) *Orchestrator {
BandwidthPct: flags.AnyoneBandwidth,
AccountingMax: flags.AnyoneAccounting,
})
} else if flags.AnyoneClient || prefs.AnyoneClient {
setup.SetAnyoneClient(true)
}
return &Orchestrator{
@ -208,6 +210,12 @@ func (o *Orchestrator) handleBranchPreferences() error {
fmt.Printf(" Nameserver mode: enabled (CoreDNS + Caddy)\n")
}
// If anyone-client was explicitly provided, update it
if o.flags.AnyoneClient {
prefs.AnyoneClient = true
prefsChanged = true
}
// Save preferences if anything changed
if prefsChanged {
if err := production.SavePreferences(o.oramaDir, prefs); err != nil {

View File

@ -90,6 +90,14 @@ func (fp *FirewallProvisioner) GenerateRules() []string {
// Enable firewall
rules = append(rules, "ufw --force enable")
// Accept all WireGuard traffic before conntrack can classify it as "invalid".
// UFW's built-in "ct state invalid → DROP" runs before user rules like
// "allow from 10.0.0.0/8". Packets arriving through the WireGuard tunnel
// can be misclassified as "invalid" by conntrack due to reordering/jitter
// (especially between high-latency peers), causing silent packet drops.
// Inserting at position 1 in INPUT ensures this runs before UFW chains.
rules = append(rules, "iptables -I INPUT 1 -i wg0 -s 10.0.0.0/8 -j ACCEPT")
return rules
}

View File

@ -20,6 +20,7 @@ func TestFirewallProvisioner_GenerateRules_StandardNode(t *testing.T) {
assertContainsRule(t, rules, "ufw allow 443/tcp")
assertContainsRule(t, rules, "ufw allow from 10.0.0.0/8")
assertContainsRule(t, rules, "ufw --force enable")
assertContainsRule(t, rules, "iptables -I INPUT 1 -i wg0 -s 10.0.0.0/8 -j ACCEPT")
// Should NOT contain DNS or Anyone relay
for _, rule := range rules {

View File

@ -290,6 +290,38 @@ func (ari *AnyoneRelayInstaller) Configure() error {
return nil
}
// ConfigureClient generates a client-only anonrc (SocksPort 9050, no relay)
func (ari *AnyoneRelayInstaller) ConfigureClient() error {
fmt.Fprintf(ari.logWriter, " Configuring Anyone client-only mode...\n")
configPath := "/etc/anon/anonrc"
// Backup existing config if it exists
if _, err := os.Stat(configPath); err == nil {
backupPath := configPath + ".bak"
if err := exec.Command("cp", configPath, backupPath).Run(); err != nil {
fmt.Fprintf(ari.logWriter, " ⚠️ Warning: failed to backup existing config: %v\n", err)
}
}
config := `# Anyone Client Configuration (Managed by Orama Network)
# Client-only mode no relay traffic, no ORPort
SocksPort 9050
Log notice file /var/log/anon/notices.log
DataDirectory /var/lib/anon
ControlPort 9051
`
if err := os.WriteFile(configPath, []byte(config), 0644); err != nil {
return fmt.Errorf("failed to write client anonrc: %w", err)
}
fmt.Fprintf(ari.logWriter, " ✓ Anyone client configured (SocksPort 9050)\n")
return nil
}
// generateAnonrc creates the anonrc configuration content
func (ari *AnyoneRelayInstaller) generateAnonrc() string {
var sb strings.Builder

View File

@ -37,6 +37,7 @@ type ProductionSetup struct {
skipOptionalDeps bool
skipResourceChecks bool
isNameserver bool // Whether this node is a nameserver (runs CoreDNS + Caddy)
isAnyoneClient bool // Whether this node runs Anyone as client-only (SOCKS5 proxy)
anyoneRelayConfig *AnyoneRelayConfig // Configuration for Anyone relay mode
privChecker *PrivilegeChecker
osDetector *OSDetector
@ -152,6 +153,16 @@ func (ps *ProductionSetup) IsAnyoneRelay() bool {
return ps.anyoneRelayConfig != nil && ps.anyoneRelayConfig.Enabled
}
// SetAnyoneClient sets whether this node runs Anyone as client-only
func (ps *ProductionSetup) SetAnyoneClient(enabled bool) {
ps.isAnyoneClient = enabled
}
// IsAnyoneClient returns whether this node runs Anyone as client-only
func (ps *ProductionSetup) IsAnyoneClient() bool {
return ps.isAnyoneClient
}
// Phase1CheckPrerequisites performs initial environment validation
func (ps *ProductionSetup) Phase1CheckPrerequisites() error {
ps.logf("Phase 1: Checking prerequisites...")
@ -444,6 +455,19 @@ func (ps *ProductionSetup) Phase2bInstallBinaries() error {
if err := relayInstaller.Configure(); err != nil {
ps.logf(" ⚠️ Anyone relay config warning: %v", err)
}
} else if ps.IsAnyoneClient() {
ps.logf(" Installing Anyone client-only mode (SOCKS5 proxy)...")
clientInstaller := installers.NewAnyoneRelayInstaller(ps.arch, ps.logWriter, installers.AnyoneRelayConfig{})
// Install the anon binary (same apt package as relay)
if err := clientInstaller.Install(); err != nil {
ps.logf(" ⚠️ Anyone client install warning: %v", err)
}
// Configure as client-only (SocksPort 9050, no ORPort)
if err := clientInstaller.ConfigureClient(); err != nil {
ps.logf(" ⚠️ Anyone client config warning: %v", err)
}
}
ps.logf(" ✓ All binaries installed")
@ -711,6 +735,12 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error {
return fmt.Errorf("failed to write Anyone Relay service: %w", err)
}
ps.logf(" ✓ Anyone Relay service created (operator mode, ORPort: %d)", ps.anyoneRelayConfig.ORPort)
} else if ps.IsAnyoneClient() {
anyoneUnit := ps.serviceGenerator.GenerateAnyoneRelayService()
if err := ps.serviceController.WriteServiceUnit("debros-anyone-relay.service", anyoneUnit); err != nil {
return fmt.Errorf("failed to write Anyone client service: %w", err)
}
ps.logf(" ✓ Anyone client service created (SocksPort 9050)")
}
// CoreDNS service (only for nameserver nodes)
@ -753,8 +783,8 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error {
// Note: debros-rqlite.service is NOT created - RQLite is managed by each node internally
services := []string{"debros-ipfs.service", "debros-ipfs-cluster.service", "debros-olric.service", "debros-node.service"}
// Add Anyone Relay service if configured
if ps.IsAnyoneRelay() {
// Add Anyone service if configured (relay or client)
if ps.IsAnyoneRelay() || ps.IsAnyoneClient() {
services = append(services, "debros-anyone-relay.service")
}
@ -783,7 +813,7 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error {
// Start infrastructure first (IPFS, Olric, Anyone) - RQLite is managed internally by each node
infraServices := []string{"debros-ipfs.service", "debros-olric.service"}
// Add Anyone Relay service if configured
// Add Anyone service if configured (relay or client)
if ps.IsAnyoneRelay() {
orPort := 9001
if ps.anyoneRelayConfig != nil && ps.anyoneRelayConfig.ORPort > 0 {
@ -795,6 +825,8 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error {
} else {
infraServices = append(infraServices, "debros-anyone-relay.service")
}
} else if ps.IsAnyoneClient() {
infraServices = append(infraServices, "debros-anyone-relay.service")
}
for _, svc := range infraServices {

View File

@ -10,8 +10,9 @@ import (
// NodePreferences contains persistent node configuration that survives upgrades
type NodePreferences struct {
Branch string `yaml:"branch"`
Nameserver bool `yaml:"nameserver"`
Branch string `yaml:"branch"`
Nameserver bool `yaml:"nameserver"`
AnyoneClient bool `yaml:"anyone_client"`
}
const (

View File

@ -114,6 +114,11 @@ func (wp *WireGuardProvisioner) GenerateConfig() string {
sb.WriteString(fmt.Sprintf("Address = %s/24\n", wp.config.PrivateIP))
sb.WriteString(fmt.Sprintf("ListenPort = %d\n", wp.config.ListenPort))
// Accept all WireGuard subnet traffic before UFW's conntrack "invalid" drop.
// Without this, packets reordered by the tunnel get silently dropped.
sb.WriteString("PostUp = iptables -I INPUT 1 -i wg0 -s 10.0.0.0/8 -j ACCEPT\n")
sb.WriteString("PostDown = iptables -D INPUT -i wg0 -s 10.0.0.0/8 -j ACCEPT\n")
for _, peer := range wp.config.Peers {
sb.WriteString("\n[Peer]\n")
sb.WriteString(fmt.Sprintf("PublicKey = %s\n", peer.PublicKey))

View File

@ -92,6 +92,12 @@ func TestWireGuardProvisioner_GenerateConfig_NoPeers(t *testing.T) {
if !strings.Contains(config, "PrivateKey = dGVzdHByaXZhdGVrZXl0ZXN0cHJpdmF0ZWtleXM=") {
t.Error("config should contain PrivateKey")
}
if !strings.Contains(config, "PostUp = iptables -I INPUT 1 -i wg0 -s 10.0.0.0/8 -j ACCEPT") {
t.Error("config should contain PostUp iptables rule for WireGuard subnet")
}
if !strings.Contains(config, "PostDown = iptables -D INPUT -i wg0 -s 10.0.0.0/8 -j ACCEPT") {
t.Error("config should contain PostDown iptables cleanup rule")
}
if strings.Contains(config, "[Peer]") {
t.Error("config should NOT contain [Peer] section with no peers")
}