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
6 changes: 5 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,11 @@ func (cfg *Config) NewNode() (host.Host, error) {
if !cfg.DisableMetrics {
mt = autonatv2.NewMetricsTracer(cfg.PrometheusRegisterer)
}
autoNATv2, err := autonatv2.New(ah, autonatv2.WithMetricsTracer(mt))
opts := []autonatv2.AutoNATOption{autonatv2.WithMetricsTracer(mt)}
if cfg.AutoNATConfig.ForceReachability != nil {
opts = append(opts, autonatv2.WithReachability(*cfg.AutoNATConfig.ForceReachability))
}
autoNATv2, err := autonatv2.New(ah, opts...)
if err != nil {
return nil, fmt.Errorf("failed to create autonatv2: %w", err)
}
Expand Down
18 changes: 18 additions & 0 deletions libp2p_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,24 @@ func TestAutoNATv2Service(t *testing.T) {
h.Close()
}

func TestAutoNATv2ForcedReachability(t *testing.T) {
client, err := New(
EnableAutoNATv2(),
ForceReachabilityPrivate(),
)
require.NoError(t, err)
defer client.Close()

confirmedAddrsHost, ok := client.(interface {
ConfirmedAddrs() (reachable, unreachable, unknown []ma.Multiaddr)
})
require.True(t, ok)
require.Eventually(t, func() bool {
reachable, unreachable, unknown := confirmedAddrsHost.ConfirmedAddrs()
return len(reachable) == 0 && len(unreachable) > 0 && len(unknown) == 0
}, 10*time.Second, 50*time.Millisecond)
}

func TestDisableIdentifyAddressDiscovery(t *testing.T) {
h, err := New(DisableIdentifyAddressDiscovery())
require.NoError(t, err)
Expand Down
5 changes: 5 additions & 0 deletions p2p/protocol/autonatv2/autonat.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ type AutoNAT struct {
// allowPrivateAddrs enables using private and localhost addresses for reachability checks.
// This is only useful for testing.
allowPrivateAddrs bool
forceReachability *network.Reachability
}

// New returns a new AutoNAT instance.
Expand All @@ -110,6 +111,7 @@ func New(dialerHost host.Host, opts ...AutoNATOption) (*AutoNAT, error) {
srv: newServer(dialerHost, s),
cli: newClient(s),
allowPrivateAddrs: s.allowPrivateAddrs,
forceReachability: s.forceReachability,
peers: newPeersMap(),
throttlePeer: make(map[peer.ID]time.Time),
throttlePeerDuration: s.throttlePeerDuration,
Expand Down Expand Up @@ -179,6 +181,9 @@ func (an *AutoNAT) Close() {

// GetReachability makes a single dial request for checking reachability for requested addresses
func (an *AutoNAT) GetReachability(ctx context.Context, reqs []Request) (Result, error) {
if an.forceReachability != nil && len(reqs) > 0 {
return Result{Addr: reqs[0].Addr, Idx: 0, Reachability: *an.forceReachability}, nil
}
var filteredReqs []Request
if !an.allowPrivateAddrs {
filteredReqs = make([]Request, 0, len(reqs))
Expand Down
18 changes: 18 additions & 0 deletions p2p/protocol/autonatv2/autonat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ func TestAutoNATPrivateAddr(t *testing.T) {
require.ErrorIs(t, err, ErrPrivateAddrs)
}

func TestForcedReachability(t *testing.T) {
addr := ma.StringCast("/ip4/192.168.0.1/udp/10/quic-v1")
for _, reachability := range []network.Reachability{
network.ReachabilityPrivate,
network.ReachabilityPublic,
} {
t.Run(reachability.String(), func(t *testing.T) {
an := newAutoNAT(t, nil, WithReachability(reachability))
defer an.Close()
defer an.host.Close()

res, err := an.GetReachability(context.Background(), []Request{{Addr: addr}})
require.NoError(t, err)
require.Equal(t, Result{Addr: addr, Reachability: reachability}, res)
})
}
}

func TestClientRequest(t *testing.T) {
an := newAutoNAT(t, nil, AllowPrivateAddrs)
defer an.Close()
Expand Down
16 changes: 15 additions & 1 deletion p2p/protocol/autonatv2/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package autonatv2

import "time"
import (
"time"

"github.com/libp2p/go-libp2p/core/network"
)

// autoNATSettings is used to configure AutoNAT
type autoNATSettings struct {
Expand All @@ -14,6 +18,7 @@ type autoNATSettings struct {
amplificatonAttackPreventionDialWait time.Duration
metricsTracer MetricsTracer
throttlePeerDuration time.Duration
forceReachability *network.Reachability
}

func defaultSettings() *autoNATSettings {
Expand Down Expand Up @@ -49,6 +54,15 @@ func WithMetricsTracer(m MetricsTracer) AutoNATOption {
}
}

// WithReachability overrides automatic reachability detection with a fixed status.
// The AutoNAT service continues to handle requests from other peers.
func WithReachability(reachability network.Reachability) AutoNATOption {
return func(s *autoNATSettings) error {
s.forceReachability = &reachability
return nil
}
}

func withDataRequestPolicy(drp dataRequestPolicyFunc) AutoNATOption {
return func(s *autoNATSettings) error {
s.dataRequestPolicy = drp
Expand Down