added anyone proxy support

This commit is contained in:
anonpenguin 2025-08-10 16:34:11 +03:00
parent 2015d454eb
commit 2647f75ed6
8 changed files with 403 additions and 167 deletions

View File

@ -14,6 +14,7 @@ import (
"git.debros.io/DeBros/network/pkg/constants" "git.debros.io/DeBros/network/pkg/constants"
"github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
"git.debros.io/DeBros/network/pkg/anyoneproxy"
) )
var ( var (
@ -21,6 +22,7 @@ var (
timeout = 30 * time.Second timeout = 30 * time.Second
format = "table" format = "table"
useProduction = false useProduction = false
disableAnon = false
) )
// version metadata populated via -ldflags at build time // version metadata populated via -ldflags at build time
@ -42,6 +44,9 @@ func main() {
// Parse global flags // Parse global flags
parseGlobalFlags(args) parseGlobalFlags(args)
// Apply disable flag early so all network operations honor it
anyoneproxy.SetDisabled(disableAnon)
switch command { switch command {
case "version": case "version":
fmt.Printf("network-cli %s", version) fmt.Printf("network-cli %s", version)
@ -105,6 +110,8 @@ func parseGlobalFlags(args []string) {
} }
case "--production": case "--production":
useProduction = true useProduction = true
case "--disable-anonrc":
disableAnon = true
} }
} }
} }

View File

@ -4,8 +4,8 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"net"
"log" "log"
"net"
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
@ -13,11 +13,12 @@ import (
"strings" "strings"
"syscall" "syscall"
"git.debros.io/DeBros/network/pkg/anyoneproxy"
"git.debros.io/DeBros/network/pkg/client"
"git.debros.io/DeBros/network/pkg/config" "git.debros.io/DeBros/network/pkg/config"
"git.debros.io/DeBros/network/pkg/constants" "git.debros.io/DeBros/network/pkg/constants"
"git.debros.io/DeBros/network/pkg/logging" "git.debros.io/DeBros/network/pkg/logging"
"git.debros.io/DeBros/network/pkg/node" "git.debros.io/DeBros/network/pkg/node"
"git.debros.io/DeBros/network/pkg/client"
) )
func main() { func main() {
@ -31,10 +32,14 @@ func main() {
rqlRaft = flag.Int("rqlite-raft-port", 7001, "RQLite Raft port") rqlRaft = flag.Int("rqlite-raft-port", 7001, "RQLite Raft port")
advertise = flag.String("advertise", "auto", "Advertise mode: auto|localhost|ip") advertise = flag.String("advertise", "auto", "Advertise mode: auto|localhost|ip")
devLocal = flag.Bool("dev-local", false, "Enable development localhost defaults for the client library (sets NETWORK_DEV_LOCAL=1)") devLocal = flag.Bool("dev-local", false, "Enable development localhost defaults for the client library (sets NETWORK_DEV_LOCAL=1)")
disableAnon = flag.Bool("disable-anonrc", false, "Disable Anyone proxy routing (defaults to enabled on 127.0.0.1:9050)")
help = flag.Bool("help", false, "Show help") help = flag.Bool("help", false, "Show help")
) )
flag.Parse() flag.Parse()
// Apply proxy disable flag early
anyoneproxy.SetDisabled(*disableAnon)
if *help { if *help {
flag.Usage() flag.Usage()
return return
@ -236,7 +241,7 @@ func isLocalIP(ip string) bool {
return false return false
} }
for _, iface := range ifaces { for _, iface := range ifaces {
if (iface.Flags&net.FlagUp) == 0 { if (iface.Flags & net.FlagUp) == 0 {
continue continue
} }
addrs, err := iface.Addrs() addrs, err := iface.Addrs()

4
go.mod
View File

@ -5,13 +5,13 @@ go 1.23.8
toolchain go1.24.1 toolchain go1.24.1
require ( require (
github.com/joho/godotenv v1.5.1
github.com/libp2p/go-libp2p v0.41.1 github.com/libp2p/go-libp2p v0.41.1
github.com/libp2p/go-libp2p-kad-dht v0.33.1 github.com/libp2p/go-libp2p-kad-dht v0.33.1
github.com/libp2p/go-libp2p-pubsub v0.14.2 github.com/libp2p/go-libp2p-pubsub v0.14.2
github.com/multiformats/go-multiaddr v0.15.0 github.com/multiformats/go-multiaddr v0.15.0
github.com/rqlite/gorqlite v0.0.0-20250609141355-ac86a4a1c9a8 github.com/rqlite/gorqlite v0.0.0-20250609141355-ac86a4a1c9a8
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/net v0.42.0
) )
require ( require (
@ -59,7 +59,6 @@ require (
github.com/libp2p/go-netroute v0.2.2 // indirect github.com/libp2p/go-netroute v0.2.2 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v5 v5.0.0 // indirect github.com/libp2p/go-yamux/v5 v5.0.0 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/miekg/dns v1.1.66 // indirect github.com/miekg/dns v1.1.66 // indirect
@ -123,7 +122,6 @@ require (
golang.org/x/crypto v0.40.0 // indirect golang.org/x/crypto v0.40.0 // indirect
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect
golang.org/x/mod v0.26.0 // indirect golang.org/x/mod v0.26.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect golang.org/x/text v0.27.0 // indirect

10
go.sum
View File

@ -132,8 +132,6 @@ github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@ -186,8 +184,6 @@ github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQsc
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/libp2p/go-yamux/v5 v5.0.0 h1:2djUh96d3Jiac/JpGkKs4TO49YhsfLopAoryfPmf+Po= github.com/libp2p/go-yamux/v5 v5.0.0 h1:2djUh96d3Jiac/JpGkKs4TO49YhsfLopAoryfPmf+Po=
github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q=
github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
@ -196,7 +192,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
@ -450,7 +445,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
@ -488,9 +482,6 @@ golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -512,7 +503,6 @@ golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=

160
pkg/anyoneproxy/socks.go Normal file
View File

@ -0,0 +1,160 @@
package anyoneproxy
import (
"context"
"net"
"net/http"
"os"
"time"
goproxy "golang.org/x/net/proxy"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
ma "github.com/multiformats/go-multiaddr"
)
// disabled controls runtime disabling via flags. Default is false (proxy enabled).
var disabled bool
// SetDisabled allows binaries to disable Anyone routing via a flag (e.g. --disable-anonrc).
func SetDisabled(v bool) { disabled = v }
// Enabled reports whether Anyone proxy routing is active.
// Defaults to true, using SOCKS5 at 127.0.0.1:9050, unless explicitly disabled
// via SetDisabled(true) or environment variable ANYONE_DISABLE=1.
// ANYONE_SOCKS5 may override the proxy address.
func Enabled() bool {
if disabled {
return false
}
if os.Getenv("ANYONE_DISABLE") == "1" {
return false
}
// If explicitly enabled via env or custom addr provided, also true.
if os.Getenv("ANYONE_PROXY_ENABLED") == "1" {
return true
}
if os.Getenv("ANYONE_SOCKS5") != "" {
return true
}
// Default: enabled
return true
}
// socksAddr returns the SOCKS5 address to use for proxying (host:port).
func socksAddr() string {
if v := os.Getenv("ANYONE_SOCKS5"); v != "" {
return v
}
return "127.0.0.1:9050"
}
// socksContextDialer implements tcp.ContextDialer over a SOCKS5 proxy.
type socksContextDialer struct{ addr string }
func (d *socksContextDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
// Derive timeout from context deadline if present
var timeout time.Duration
if deadline, ok := ctx.Deadline(); ok {
timeout = time.Until(deadline)
if timeout <= 0 {
return nil, context.DeadlineExceeded
}
}
base := &net.Dialer{Timeout: timeout}
// Create a SOCKS5 dialer using the base dialer
socksDialer, err := goproxy.SOCKS5("tcp", d.addr, nil, base)
if err != nil {
return nil, err
}
return socksDialer.Dial(network, address)
}
// DialerForAddr returns a tcp.DialerForAddr that routes through the Anyone SOCKS5 proxy.
// It automatically BYPASSES the proxy for loopback, private, and link-local addresses
// to allow local/dev networking (e.g. 127.0.0.1, 10.0.0.0/8, 192.168.0.0/16, fc00::/7, fe80::/10).
func DialerForAddr() tcp.DialerForAddr {
return func(raddr ma.Multiaddr) (tcp.ContextDialer, error) {
// Prefer direct dialing for local/private targets
if ip4, err := raddr.ValueForProtocol(ma.P_IP4); err == nil {
if ip := net.ParseIP(ip4); ip != nil {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
return &net.Dialer{}, nil
}
}
}
if ip6, err := raddr.ValueForProtocol(ma.P_IP6); err == nil {
if ip := net.ParseIP(ip6); ip != nil {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
return &net.Dialer{}, nil
}
}
}
if host, err := raddr.ValueForProtocol(ma.P_DNS); err == nil {
if host == "localhost" {
return &net.Dialer{}, nil
}
}
if host, err := raddr.ValueForProtocol(ma.P_DNS4); err == nil {
if host == "localhost" {
return &net.Dialer{}, nil
}
}
if host, err := raddr.ValueForProtocol(ma.P_DNS6); err == nil {
if host == "localhost" {
return &net.Dialer{}, nil
}
}
// Default: use SOCKS dialer
return &socksContextDialer{addr: socksAddr()}, nil
}
}
// NewHTTPClient returns an *http.Client that routes all TCP connections via the Anyone SOCKS5 proxy.
// If Anyone proxy is not enabled, it returns http.DefaultClient.
func NewHTTPClient() *http.Client {
if !Enabled() {
return http.DefaultClient
}
tr := &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
// Bypass proxy for localhost/private IPs
host, _, err := net.SplitHostPort(addr)
if err != nil {
host = addr
}
if ip := net.ParseIP(host); ip != nil {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
d := &net.Dialer{}
return d.DialContext(ctx, network, addr)
}
}
if host == "localhost" {
d := &net.Dialer{}
return d.DialContext(ctx, network, addr)
}
d := &socksContextDialer{addr: socksAddr()}
return d.DialContext(ctx, network, addr)
},
}
return &http.Client{Transport: tr}
}
// Address returns the SOCKS5 address used for Anyone routing.
func Address() string { return socksAddr() }
// Running returns true if Anyone proxy is enabled and reachable at Address().
// It attempts a short TCP dial and returns false on failure.
func Running() bool {
if !Enabled() {
return false
}
conn, err := net.DialTimeout("tcp", socksAddr(), 200*time.Millisecond)
if err != nil {
return false
}
_ = conn.Close()
return true
}

View File

@ -21,6 +21,7 @@ import (
"git.debros.io/DeBros/network/pkg/discovery" "git.debros.io/DeBros/network/pkg/discovery"
"git.debros.io/DeBros/network/pkg/pubsub" "git.debros.io/DeBros/network/pkg/pubsub"
"git.debros.io/DeBros/network/pkg/storage" "git.debros.io/DeBros/network/pkg/storage"
"git.debros.io/DeBros/network/pkg/anyoneproxy"
) )
// Client implements the NetworkClient interface // Client implements the NetworkClient interface
@ -123,14 +124,23 @@ func (c *Client) Connect() error {
return nil return nil
} }
// Create LibP2P host // Create LibP2P host with optional Anyone proxy for TCP and optional QUIC disable
h, err := libp2p.New( var opts []libp2p.Option
opts = append(opts,
libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"), // Random port libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"), // Random port
libp2p.Security(noise.ID, noise.New), libp2p.Security(noise.ID, noise.New),
libp2p.Transport(tcp.NewTCPTransport),
libp2p.Transport(libp2pquic.NewTransport),
libp2p.DefaultMuxers, libp2p.DefaultMuxers,
) )
if anyoneproxy.Enabled() {
opts = append(opts, libp2p.Transport(tcp.NewTCPTransport, tcp.WithDialerForAddr(anyoneproxy.DialerForAddr())))
} else {
opts = append(opts, libp2p.Transport(tcp.NewTCPTransport))
}
// Enable QUIC only when not proxying. When proxy is enabled, prefer TCP via SOCKS5.
if !anyoneproxy.Enabled() {
opts = append(opts, libp2p.Transport(libp2pquic.NewTransport))
}
h, err := libp2p.New(opts...)
if err != nil { if err != nil {
return fmt.Errorf("failed to create libp2p host: %w", err) return fmt.Errorf("failed to create libp2p host: %w", err)
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/rqlite/gorqlite" "github.com/rqlite/gorqlite"
"git.debros.io/DeBros/network/pkg/anyoneproxy"
) )
// DatabaseClientImpl implements DatabaseClient // DatabaseClientImpl implements DatabaseClient
@ -250,7 +251,15 @@ func (d *DatabaseClientImpl) connectToAvailableNode() (*gorqlite.Connection, err
var lastErr error var lastErr error
for _, rqliteURL := range rqliteNodes { for _, rqliteURL := range rqliteNodes {
conn, err := gorqlite.Open(rqliteURL) var conn *gorqlite.Connection
var err error
// If Anyone proxy is enabled, build a proxy-aware HTTP client
if anyoneproxy.Enabled() {
httpClient := anyoneproxy.NewHTTPClient()
conn, err = gorqlite.OpenWithClient(rqliteURL, httpClient)
} else {
conn, err = gorqlite.Open(rqliteURL)
}
if err != nil { if err != nil {
lastErr = err lastErr = err
continue continue

View File

@ -14,6 +14,7 @@ import (
"github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
noise "github.com/libp2p/go-libp2p/p2p/security/noise" noise "github.com/libp2p/go-libp2p/p2p/security/noise"
libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/libp2p/go-libp2p/p2p/transport/tcp"
@ -22,6 +23,7 @@ import (
"git.debros.io/DeBros/network/pkg/config" "git.debros.io/DeBros/network/pkg/config"
"git.debros.io/DeBros/network/pkg/database" "git.debros.io/DeBros/network/pkg/database"
"git.debros.io/DeBros/network/pkg/anyoneproxy"
"git.debros.io/DeBros/network/pkg/logging" "git.debros.io/DeBros/network/pkg/logging"
"git.debros.io/DeBros/network/pkg/storage" "git.debros.io/DeBros/network/pkg/storage"
) )
@ -132,15 +134,44 @@ func (n *Node) startLibP2P() error {
return fmt.Errorf("failed to load identity: %w", err) return fmt.Errorf("failed to load identity: %w", err)
} }
// Log Anyone proxy status before constructing host
n.logger.ComponentInfo(logging.ComponentLibP2P, "Anyone proxy status",
zap.Bool("proxy_enabled", anyoneproxy.Enabled()),
zap.String("proxy_addr", anyoneproxy.Address()),
zap.Bool("proxy_running", anyoneproxy.Running()),
)
if anyoneproxy.Enabled() && !anyoneproxy.Running() {
n.logger.Warn("Anyone proxy is enabled but not reachable",
zap.String("addr", anyoneproxy.Address()))
}
// Create LibP2P host with persistent identity // Create LibP2P host with persistent identity
h, err := libp2p.New( // Build options allowing conditional proxying via Anyone SOCKS5 and optional QUIC disable
var opts []libp2p.Option
opts = append(opts,
libp2p.Identity(identity), libp2p.Identity(identity),
libp2p.ListenAddrs(listenAddrs...), libp2p.ListenAddrs(listenAddrs...),
libp2p.Security(noise.ID, noise.New), libp2p.Security(noise.ID, noise.New),
libp2p.Transport(tcp.NewTCPTransport),
libp2p.Transport(libp2pquic.NewTransport),
libp2p.DefaultMuxers, libp2p.DefaultMuxers,
) )
// TCP transport with optional SOCKS5 dialer override
if anyoneproxy.Enabled() {
opts = append(opts, libp2p.Transport(tcp.NewTCPTransport, tcp.WithDialerForAddr(anyoneproxy.DialerForAddr())))
} else {
opts = append(opts, libp2p.Transport(tcp.NewTCPTransport))
}
// QUIC transport: disabled when proxy is enabled (default),
// enabled only when not proxying.
if !anyoneproxy.Enabled() {
opts = append(opts, libp2p.Transport(libp2pquic.NewTransport))
} else {
n.logger.ComponentDebug(logging.ComponentLibP2P, "QUIC disabled due to proxy being enabled")
}
h, err := libp2p.New(opts...)
if err != nil { if err != nil {
return err return err
} }
@ -148,12 +179,31 @@ func (n *Node) startLibP2P() error {
n.host = h n.host = h
// Create DHT for peer discovery - Use server mode for better peer discovery // Create DHT for peer discovery - Use server mode for better peer discovery
kademliaDHT, err := dht.New(context.Background(), h, dht.Mode(dht.ModeServer)) // Use configured protocol prefix to ensure we discover peers on the correct DHT namespace
dhtPrefix := n.config.Discovery.DHTPrefix
if strings.TrimSpace(dhtPrefix) == "" {
dhtPrefix = "/network/kad/1.0.0"
}
n.logger.ComponentInfo(logging.ComponentDHT, "Using DHT protocol prefix", zap.String("prefix", dhtPrefix))
kademliaDHT, err := dht.New(
context.Background(),
h,
dht.Mode(dht.ModeServer),
dht.ProtocolPrefix(protocol.ID(dhtPrefix)),
)
if err != nil { if err != nil {
return fmt.Errorf("failed to create DHT: %w", err) return fmt.Errorf("failed to create DHT: %w", err)
} }
n.dht = kademliaDHT n.dht = kademliaDHT
// Log configured bootstrap peers
if len(n.config.Discovery.BootstrapPeers) > 0 {
n.logger.ComponentInfo(logging.ComponentDHT, "Configured bootstrap peers",
zap.Strings("peers", n.config.Discovery.BootstrapPeers))
} else {
n.logger.ComponentDebug(logging.ComponentDHT, "No bootstrap peers configured")
}
// Connect to LibP2P bootstrap peers if configured // Connect to LibP2P bootstrap peers if configured
if err := n.connectToBootstrapPeers(); err != nil { if err := n.connectToBootstrapPeers(); err != nil {
n.logger.Warn("Failed to connect to bootstrap peers", zap.Error(err)) n.logger.Warn("Failed to connect to bootstrap peers", zap.Error(err))
@ -308,6 +358,13 @@ func (n *Node) connectToBootstrapPeer(ctx context.Context, addr string) error {
return fmt.Errorf("failed to extract peer info: %w", err) return fmt.Errorf("failed to extract peer info: %w", err)
} }
// Log resolved peer info prior to connect
n.logger.ComponentDebug(logging.ComponentDHT, "Resolved bootstrap peer",
zap.String("peer_id", peerInfo.ID.String()),
zap.String("addr", addr),
zap.Int("addr_count", len(peerInfo.Addrs)),
)
// Connect to the peer // Connect to the peer
if err := n.host.Connect(ctx, *peerInfo); err != nil { if err := n.host.Connect(ctx, *peerInfo); err != nil {
return fmt.Errorf("failed to connect to peer: %w", err) return fmt.Errorf("failed to connect to peer: %w", err)