Skip to content

Commit eb3ff9f

Browse files
committed
autonatv2: fix server dial data request policy (#3247)
1 parent 99a511f commit eb3ff9f

File tree

2 files changed

+79
-9
lines changed

2 files changed

+79
-9
lines changed

p2p/protocol/autonatv2/server.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ var (
3030
errDialDataRefused = errors.New("dial data refused")
3131
)
3232

33-
type dataRequestPolicyFunc = func(s network.Stream, dialAddr ma.Multiaddr) bool
33+
type dataRequestPolicyFunc = func(observedAddr, dialAddr ma.Multiaddr) bool
3434

3535
type EventDialRequestCompleted struct {
3636
Error error
@@ -212,7 +212,7 @@ func (as *server) serveDialRequest(s network.Stream) EventDialRequestCompleted {
212212

213213
nonce := msg.GetDialRequest().Nonce
214214

215-
isDialDataRequired := as.dialDataRequestPolicy(s, dialAddr)
215+
isDialDataRequired := as.dialDataRequestPolicy(s.Conn().RemoteMultiaddr(), dialAddr)
216216
if isDialDataRequired && !as.limiter.AcceptDialDataRequest(p) {
217217
msg = pb.Message{
218218
Msg: &pb.Message_DialResponse{
@@ -517,11 +517,11 @@ func (r *rateLimiter) Close() {
517517

518518
// amplificationAttackPrevention is a dialDataRequestPolicy which requests data when the peer's observed
519519
// IP address is different from the dial back IP address
520-
func amplificationAttackPrevention(s network.Stream, dialAddr ma.Multiaddr) bool {
521-
connIP, err := manet.ToIP(s.Conn().RemoteMultiaddr())
520+
func amplificationAttackPrevention(observedAddr, dialAddr ma.Multiaddr) bool {
521+
observedIP, err := manet.ToIP(observedAddr)
522522
if err != nil {
523523
return true
524524
}
525-
dialIP, _ := manet.ToIP(s.Conn().LocalMultiaddr()) // must be an IP multiaddr
526-
return !connIP.Equal(dialIP)
525+
dialIP, _ := manet.ToIP(dialAddr) // must be an IP multiaddr
526+
return !observedIP.Equal(dialIP)
527527
}

p2p/protocol/autonatv2/server_test.go

+73-3
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func TestServerDataRequest(t *testing.T) {
143143
dialer := bhost.NewBlankHost(swarmt.GenSwarm(t, swarmt.OptDisableTCP))
144144
// ask for dial data for quic address
145145
an := newAutoNAT(t, dialer, allowPrivateAddrs, withDataRequestPolicy(
146-
func(s network.Stream, dialAddr ma.Multiaddr) bool {
146+
func(_, dialAddr ma.Multiaddr) bool {
147147
if _, err := dialAddr.ValueForProtocol(ma.P_QUIC_V1); err == nil {
148148
return true
149149
}
@@ -197,7 +197,7 @@ func TestServerMaxConcurrentRequestsPerPeer(t *testing.T) {
197197
doneChan := make(chan struct{})
198198
an := newAutoNAT(t, dialer, allowPrivateAddrs, withDataRequestPolicy(
199199
// stall all allowed requests
200-
func(s network.Stream, dialAddr ma.Multiaddr) bool {
200+
func(_, dialAddr ma.Multiaddr) bool {
201201
<-doneChan
202202
return true
203203
}),
@@ -255,7 +255,7 @@ func TestServerDataRequestJitter(t *testing.T) {
255255
dialer := bhost.NewBlankHost(swarmt.GenSwarm(t, swarmt.OptDisableTCP))
256256
// ask for dial data for quic address
257257
an := newAutoNAT(t, dialer, allowPrivateAddrs, withDataRequestPolicy(
258-
func(s network.Stream, dialAddr ma.Multiaddr) bool {
258+
func(_, dialAddr ma.Multiaddr) bool {
259259
if _, err := dialAddr.ValueForProtocol(ma.P_QUIC_V1); err == nil {
260260
return true
261261
}
@@ -520,6 +520,76 @@ func TestReadDialData(t *testing.T) {
520520
}
521521
}
522522

523+
func TestServerDataRequestWithAmplificationAttackPrevention(t *testing.T) {
524+
// server will skip all tcp addresses
525+
dialer := bhost.NewBlankHost(swarmt.GenSwarm(t, swarmt.OptDisableTCP))
526+
// ask for dial data for quic address
527+
an := newAutoNAT(t, dialer, allowPrivateAddrs,
528+
WithServerRateLimit(10, 10, 10, 2),
529+
withAmplificationAttackPreventionDialWait(0),
530+
)
531+
defer an.Close()
532+
defer an.host.Close()
533+
534+
c := newAutoNAT(t, nil, allowPrivateAddrs)
535+
defer c.Close()
536+
defer c.host.Close()
537+
538+
idAndWait(t, c, an)
539+
540+
err := c.host.Network().Listen(ma.StringCast("/ip6/::1/udp/0/quic-v1"))
541+
if err != nil {
542+
// machine doesn't have ipv6
543+
t.Skip("skipping test because machine doesn't have ipv6")
544+
}
545+
546+
var quicv4Addr ma.Multiaddr
547+
var quicv6Addr ma.Multiaddr
548+
for _, a := range c.host.Addrs() {
549+
if _, err := a.ValueForProtocol(ma.P_QUIC_V1); err == nil {
550+
if _, err := a.ValueForProtocol(ma.P_IP4); err == nil {
551+
quicv4Addr = a
552+
} else {
553+
quicv6Addr = a
554+
}
555+
}
556+
}
557+
res, err := c.GetReachability(context.Background(), []Request{{Addr: quicv4Addr, SendDialData: false}})
558+
require.NoError(t, err)
559+
require.Equal(t, Result{
560+
Addr: quicv4Addr,
561+
Reachability: network.ReachabilityPublic,
562+
Status: pb.DialStatus_OK,
563+
}, res)
564+
565+
// ipv6 address should require dial data
566+
_, err = c.GetReachability(context.Background(), []Request{{Addr: quicv6Addr, SendDialData: false}})
567+
require.Error(t, err)
568+
require.ErrorContains(t, err, "invalid dial data request: low priority addr")
569+
570+
// ipv6 address should work fine with dial data
571+
res, err = c.GetReachability(context.Background(), []Request{{Addr: quicv6Addr, SendDialData: true}})
572+
require.NoError(t, err)
573+
require.Equal(t, Result{
574+
Addr: quicv6Addr,
575+
Reachability: network.ReachabilityPublic,
576+
Status: pb.DialStatus_OK,
577+
}, res)
578+
}
579+
580+
func TestDefaultAmplificationAttackPrevention(t *testing.T) {
581+
q1 := ma.StringCast("/ip4/1.2.3.4/udp/1234/quic-v1")
582+
q2 := ma.StringCast("/ip4/1.2.3.4/udp/1235/quic-v1")
583+
t1 := ma.StringCast("/ip4/1.2.3.4/tcp/1234")
584+
585+
require.False(t, amplificationAttackPrevention(q1, q1))
586+
require.False(t, amplificationAttackPrevention(q1, q2))
587+
require.False(t, amplificationAttackPrevention(q1, t1))
588+
589+
t2 := ma.StringCast("/ip4/1.1.1.1/tcp/1235") // different IP
590+
require.True(t, amplificationAttackPrevention(q2, t2))
591+
}
592+
523593
func FuzzServerDialRequest(f *testing.F) {
524594
a := newAutoNAT(f, nil, allowPrivateAddrs, WithServerRateLimit(math.MaxInt32, math.MaxInt32, math.MaxInt32, 2))
525595
c := newAutoNAT(f, nil)

0 commit comments

Comments
 (0)