diff --git a/libp2p/builders.nim b/libp2p/builders.nim index dc3536793..df4ea92e9 100644 --- a/libp2p/builders.nim +++ b/libp2p/builders.nim @@ -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) diff --git a/libp2p/protocols/connectivity/autonatv2/server.nim b/libp2p/protocols/connectivity/autonatv2/server.nim index 7e5b7e945..c585473bf 100644 --- a/libp2p/protocols/connectivity/autonatv2/server.nim +++ b/libp2p/protocols/connectivity/autonatv2/server.nim @@ -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]).} = diff --git a/libp2p/protocols/connectivity/autonatv2/types.nim b/libp2p/protocols/connectivity/autonatv2/types.nim index 4637bcff5..1fa3883a4 100644 --- a/libp2p/protocols/connectivity/autonatv2/types.nim +++ b/libp2p/protocols/connectivity/autonatv2/types.nim @@ -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" diff --git a/tests/testautonatv2.nim b/tests/testautonatv2.nim index 907473280..0a22b83cc 100644 --- a/tests/testautonatv2.nim +++ b/tests/testautonatv2.nim @@ -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()