chore(autonat-v2): add server config (#1669)

This commit is contained in:
Gabriel Cruz
2025-09-08 12:23:23 -03:00
committed by GitHub
parent f345026900
commit 10f7f5c68a
4 changed files with 52 additions and 29 deletions

View File

@@ -76,6 +76,7 @@ type
peerStoreCapacity: Opt[int]
autonat: bool
autonatV2: bool
autonatV2Config: AutonatV2Config
autotls: AutotlsService
circuitRelay: Relay
rdv: RendezVous
@@ -282,8 +283,11 @@ proc withAutonat*(b: SwitchBuilder): SwitchBuilder =
b.autonat = true
b
proc withAutonatV2*(b: SwitchBuilder): SwitchBuilder =
proc withAutonatV2*(
b: SwitchBuilder, config: AutonatV2Config = AutonatV2Config.new()
): SwitchBuilder =
b.autonatV2 = true
b.autonatV2Config = config
b
when defined(libp2p_autotls_support):
@@ -386,7 +390,7 @@ proc build*(b: SwitchBuilder): Switch {.raises: [LPError], public.} =
switch.mount(identify)
if b.autonatV2:
let autonatV2 = AutonatV2.new(switch)
let autonatV2 = AutonatV2.new(switch, config = b.autonatV2Config)
switch.mount(autonatV2)
elif b.autonat:
let autonat = Autonat.new(switch)

View File

@@ -29,19 +29,29 @@ import
logScope:
topics = "libp2p autonat v2 server"
const
DefaultDialTimeout: Duration = 15.seconds
DefaultAmplificationAttackDialTimeout: Duration = 3.seconds
DefaultDialDataSize: uint64 = 50 * 1024 # 50 KiB > 50 KB
AutonatV2MsgLpSize: int = 1024
# readLp needs to receive more than 4096 bytes (since it's a DialDataResponse) + overhead
AutonatV2DialDataResponseLpSize: int = 5000
type AutonatV2* = ref object of LPProtocol
switch*: Switch
type AutonatV2Config* = object
dialTimeout: Duration
dialDataSize: uint64
amplificationAttackTimeout: Duration
allowPrivateAddresses: bool
type AutonatV2* = ref object of LPProtocol
switch*: Switch
config: AutonatV2Config
proc new*(
T: typedesc[AutonatV2Config],
dialTimeout: Duration = DefaultDialTimeout,
dialDataSize: uint64 = DefaultDialDataSize,
amplificationAttackTimeout: Duration = DefaultAmplificationAttackDialTimeout,
allowPrivateAddresses: bool = false,
): T =
T(
dialTimeout: dialTimeout,
dialDataSize: dialDataSize,
amplificationAttackTimeout: amplificationAttackTimeout,
allowPrivateAddresses: allowPrivateAddresses,
)
proc sendDialResponse(
conn: Connection,
@@ -110,7 +120,7 @@ proc handleDialDataResponses(
) {.async: (raises: [CancelledError, AutonatV2Error, LPStreamError]).} =
var dataReceived: uint64 = 0
while dataReceived < self.dialDataSize:
while dataReceived < self.config.dialDataSize:
let msg = AutonatV2Msg.decode(
initProtoBuffer(await conn.readLp(AutonatV2DialDataResponseLpSize))
).valueOr:
@@ -131,15 +141,15 @@ proc amplificationAttackPrevention(
await conn.writeLp(
AutonatV2Msg(
msgType: MsgType.DialDataRequest,
dialDataReq: DialDataRequest(addrIdx: addrIdx, numBytes: self.dialDataSize),
dialDataReq: DialDataRequest(addrIdx: addrIdx, numBytes: self.config.dialDataSize),
).encode().buffer
)
# recieve DialDataResponses until we're satisfied
try:
if not await self.handleDialDataResponses(conn).withTimeout(self.dialTimeout):
if not await self.handleDialDataResponses(conn).withTimeout(self.config.dialTimeout):
error "Amplification attack prevention timeout",
timeout = self.amplificationAttackTimeout, peer = conn.peerId
timeout = self.config.amplificationAttackTimeout, peer = conn.peerId
return false
except AutonatV2Error as exc:
error "Amplification attack prevention failed", description = exc.msg
@@ -155,7 +165,7 @@ proc canDial(self: AutonatV2, addrs: MultiAddress): bool =
if IP6.match(addrIp) and not ipv6Support:
return false
try:
if isPrivate($addrIp):
if not self.config.allowPrivateAddresses and isPrivate($addrIp):
return false
except ValueError:
warn "Unable to parse IP address, skipping", addrs = $addrIp
@@ -230,16 +240,9 @@ proc handleDialRequest(
proc new*(
T: typedesc[AutonatV2],
switch: Switch,
dialTimeout: Duration = DefaultDialTimeout,
dialDataSize: uint64 = DefaultDialDataSize,
amplificationAttackTimeout: Duration = DefaultAmplificationAttackDialTimeout,
config: AutonatV2Config = AutonatV2Config.new(),
): T =
let autonatV2 = T(
switch: switch,
dialTimeout: dialTimeout,
dialDataSize: dialDataSize,
amplificationAttackTimeout: amplificationAttackTimeout,
)
let autonatV2 = T(switch: switch, config: config)
proc handleStream(
conn: Connection, proto: string
) {.async: (raises: [CancelledError]).} =

View File

@@ -14,6 +14,14 @@ import
../../../multiaddress, ../../../peerid, ../../../protobuf/minprotobuf, ../../../switch
from ../autonat/types import NetworkReachability
const
DefaultDialTimeout*: Duration = 15.seconds
DefaultAmplificationAttackDialTimeout*: Duration = 3.seconds
DefaultDialDataSize*: uint64 = 50 * 1024 # 50 KiB > 50 KB
AutonatV2MsgLpSize*: int = 1024
# readLp needs to receive more than 4096 bytes (since it's a DialDataResponse) + overhead
AutonatV2DialDataResponseLpSize*: int = 5000
type
AutonatV2Codec* {.pure.} = enum
DialRequest = "/libp2p/autonat/2/dial-request"

View File

@@ -18,6 +18,7 @@ import
upgrademngrs/upgrade,
builders,
protocols/connectivity/autonatv2/types,
protocols/connectivity/autonatv2/server,
protocols/connectivity/autonatv2/utils,
],
./helpers
@@ -27,8 +28,8 @@ proc checkEncodeDecode[T](msg: T) =
# check msg == DialBack.decode(msg.encode()).get()
check msg == T.decode(msg.encode()).get()
proc newAutonatV2ServerSwitch(): Switch =
var builder = newStandardSwitchBuilder().withAutonatV2()
proc newAutonatV2ServerSwitch(config: AutonatV2Config = AutonatV2Config.new()): Switch =
var builder = newStandardSwitchBuilder().withAutonatV2(config = config)
return builder.build()
suite "AutonatV2":
@@ -154,7 +155,14 @@ suite "AutonatV2":
reachability: Reachable, dialResp: correctDialResp, addrs: Opt.some(addrs[0])
)
asyncTest "Instanciate server":
asyncTest "Instantiate server":
let serverSwitch = newAutonatV2ServerSwitch()
await serverSwitch.start()
await serverSwitch.stop()
asyncTest "Instantiate server with config":
let serverSwitch = newAutonatV2ServerSwitch(
config = AutonatV2Config.new(allowPrivateAddresses = true)
)
await serverSwitch.start()
await serverSwitch.stop()