mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-08 19:27:14 +00:00
3450d872d9
Hard cutover, part 1: injectAmneziawgnetSocks replaces injectAmneziawgEgress as the AmneziaWG-side Xray config injector. Every enabled AmneziaWG inbound now gets an always-on loopback SOCKS5 inbound (built by amneziawgnet.SocksInboundSettings) instead of an opt-in dokodemo-door TPROXY bridge -- there's no RouteThroughXray gate anymore since the embedded path has no alternative datapath once traffic is decapsulated in gVisor. Reuses the real inbound's own tag, same as before, so per-inbound stats totals keep matching. internal/amneziawgnet gains SOCKSPortForInbound (deterministic port derivation, its own range distinct from the kernel-module bridge's) and SocksPassword (a process-wide, lazily-generated, not-persisted password -- this traffic never leaves loopback). port_conflict.go's port-reservation check is updated to match: the new SOCKS5 relay port is reserved unconditionally for every qualifying AmneziaWG inbound, not gated on RouteThroughXray. Not yet done (tracked in the migration plan): swapping the actual manager call sites (cron job, immediate-apply CRUD, shutdown) from the kernel-module Manager to amneziawgnet's, and deleting the now-dead TPROXY/awg-quick code. This commit could not be locally verified beyond internal/amneziawgnet itself (this machine has no C compiler, so internal/database and anything that imports it -- including internal/web/service -- can't be built or vetted here); pushing for real CI feedback before continuing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
56 lines
2.2 KiB
Go
56 lines
2.2 KiB
Go
package amneziawgnet
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// SOCKSBasePort is the first loopback port used for an AmneziaWG inbound's
|
|
// own Xray SOCKS5 relay inbound (see relay.go/SocksInboundSettings). Its own
|
|
// range, distinct from amneziawg.EgressBasePort (63100, the kernel-module
|
|
// path's TPROXY bridge port) so the two can never collide even if both
|
|
// happen to be reachable during a transition.
|
|
const SOCKSBasePort = 65100
|
|
|
|
// SOCKSPortForInbound returns the loopback port of one AmneziaWG inbound's
|
|
// own Xray SOCKS5 relay inbound, derived deterministically from its id so
|
|
// the config-generation code (which builds the inbound) and the relay code
|
|
// (which dials it) never have to agree on a runtime-negotiated value --
|
|
// mirrors amneziawg.EgressPortForInbound's own reasoning exactly.
|
|
func SOCKSPortForInbound(inboundID int) int {
|
|
return SOCKSBasePort + inboundID
|
|
}
|
|
|
|
var (
|
|
socksPasswordOnce sync.Once
|
|
socksPassword string
|
|
)
|
|
|
|
// SocksPassword returns the process-wide password used to authenticate into
|
|
// every AmneziaWG SOCKS5 relay inbound, generating and caching it once
|
|
// (lazily, on first use) rather than persisting it anywhere: this traffic
|
|
// never leaves loopback, both the config generator (SocksInboundSettings'
|
|
// caller) and the relay dialer (SocksRelay/UDPRelay) live in this same
|
|
// process, and Xray's own generated config is already rebuilt from scratch
|
|
// on every reconcile -- there is nothing for a stored value to survive
|
|
// across that a fresh one wouldn't equally satisfy. Not a real secret (see
|
|
// SocksRelay's own doc comment); this only needs to be unpredictable enough
|
|
// that nothing outside this process could plausibly guess it and dial in
|
|
// over loopback.
|
|
func SocksPassword() string {
|
|
socksPasswordOnce.Do(func() {
|
|
var b [24]byte
|
|
if _, err := rand.Read(b[:]); err != nil {
|
|
// crypto/rand failing is effectively unrecoverable for a
|
|
// process that generates real WireGuard keys elsewhere too;
|
|
// a fixed fallback keeps this from panicking outright.
|
|
socksPassword = fmt.Sprintf("amneziawgnet-fallback-%x", b)
|
|
return
|
|
}
|
|
socksPassword = base64.RawURLEncoding.EncodeToString(b[:])
|
|
})
|
|
return socksPassword
|
|
}
|