Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ var (
utils.NoDiscoverFlag,
utils.DiscoveryV4Flag,
utils.DiscoveryV5Flag,
utils.UseProxyFlag,
utils.LegacyDiscoveryV5Flag, // deprecated
utils.NetrestrictFlag,
utils.NodeKeyFileFlag,
Expand Down
6 changes: 6 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,11 @@ var (
Category: flags.NetworkingCategory,
Value: node.DefaultConfig.P2P.DiscoveryV5,
}
UseProxyFlag = &cli.BoolFlag{
Name: "use-proxy",
Usage: "Use SOCKS5 proxy from ALL_PROXY or all_proxy environment variable for peer connections",
Category: flags.NetworkingCategory,
}
NetrestrictFlag = &cli.StringFlag{
Name: "netrestrict",
Usage: "Restricts network communication to the given IP networks (CIDR masks)",
Expand Down Expand Up @@ -1379,6 +1384,7 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
if ctx.IsSet(DiscoveryV5Flag.Name) {
cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name)
}
cfg.UseProxy = ctx.Bool(UseProxyFlag.Name)

if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" {
list, err := netutil.ParseNetlist(netrestrict)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ require (
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/net v0.38.0
gopkg.in/yaml.v2 v2.4.0 // indirect
)

Expand Down
3 changes: 3 additions & 0 deletions p2p/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ type Config struct {
// Logger is a custom logger to use with the p2p.Server.
Logger log.Logger `toml:"-"`

// If UseProxy is set to true, the server will use SOCKS5 proxy from ALL_PROXY or all_proxy environment variable for dialing peers.
UseProxy bool `toml:",omitempty"`

clock mclock.Clock
}

Expand Down
6 changes: 6 additions & 0 deletions p2p/config_toml.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion p2p/dial.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/p2p/netutil"
"golang.org/x/net/proxy"
)

const (
Expand Down Expand Up @@ -63,11 +64,28 @@ type nodeResolver interface {

// tcpDialer implements NodeDialer using real TCP connections.
type tcpDialer struct {
d *net.Dialer
d *net.Dialer
useProxy bool
}

// dialerWithContext is an interface implemented by proxy dialers that support context-aware dialing.
// see proxy/direct#direct, proxy.SOCKS5() and internal/socks#Dialer.
type dialerWithContext interface {
DialContext(ctx context.Context, network, address string) (net.Conn, error)
}

var proxyDialer = proxy.FromEnvironment()
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The global variable proxyDialer is initialized once at package level and accessed by all tcpDialer instances. This could lead to a race condition if the environment variable changes at runtime or if different instances need different proxy configurations. Consider making proxyDialer a field of tcpDialer that is initialized when the dialer is created, or use sync.Once to ensure thread-safe initialization if shared state is intended.

Copilot uses AI. Check for mistakes.

func (t tcpDialer) Dial(ctx context.Context, dest *enode.Node) (net.Conn, error) {
addr, _ := dest.TCPEndpoint()
if t.useProxy {
log.Debug("Dialing peer via proxy", "direct", proxyDialer == proxy.Direct, "addr", addr.String())
if v, ok := proxyDialer.(dialerWithContext); ok {
return v.DialContext(ctx, "tcp", addr.String())
} else {
log.Warn("Proxy dialer does not support context, falling back to direct", "addr", addr.String())
}
Comment on lines +85 to +87
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the proxy dialer doesn't support DialContext, the code logs a warning and falls back to direct connection without actually using the non-context-aware proxy dialer. This fallback behavior is inconsistent with the user's intention to use a proxy. Consider either returning an error when UseProxy is true but the proxy doesn't support context, or actually calling the non-context-aware Dial method (though this would lose context cancellation support). The current implementation silently ignores the proxy requirement.

Copilot uses AI. Check for mistakes.
}
Comment on lines +81 to +88
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new proxy dialing functionality lacks test coverage. The codebase has comprehensive tests for the dialing logic in dial_test.go, but there are no tests verifying the proxy behavior. Consider adding tests to cover: (1) successful proxy connections when useProxy is true, (2) fallback to direct connection when proxy dialer doesn't support context, (3) behavior when proxy environment variables are not set, and (4) interaction with the existing dial scheduler.

Copilot uses AI. Check for mistakes.
return t.d.DialContext(ctx, "tcp", addr.String())
}

Expand Down
2 changes: 1 addition & 1 deletion p2p/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ func (srv *Server) setupDialScheduler() {
config.resolver = srv.discv4
}
if config.dialer == nil {
config.dialer = tcpDialer{&net.Dialer{Timeout: defaultDialTimeout}}
config.dialer = tcpDialer{&net.Dialer{Timeout: defaultDialTimeout}, srv.UseProxy}
}
srv.dialsched = newDialScheduler(config, srv.discmix, srv.SetupConn)
for _, n := range srv.StaticNodes {
Expand Down