@libp2p/upnp-nat 2.0.12-8a9258a24 → 2.0.12-92cc74082
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/constants.d.ts +0 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +0 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/gateway-finder.d.ts.map +1 -1
- package/dist/src/gateway-finder.js +7 -2
- package/dist/src/gateway-finder.js.map +1 -1
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/upnp-nat.d.ts +3 -1
- package/dist/src/upnp-nat.d.ts.map +1 -1
- package/dist/src/upnp-nat.js +17 -5
- package/dist/src/upnp-nat.js.map +1 -1
- package/dist/src/upnp-port-mapper.d.ts +4 -1
- package/dist/src/upnp-port-mapper.d.ts.map +1 -1
- package/dist/src/upnp-port-mapper.js +42 -39
- package/dist/src/upnp-port-mapper.js.map +1 -1
- package/package.json +11 -11
- package/src/constants.ts +0 -1
- package/src/gateway-finder.ts +7 -2
- package/src/index.ts +18 -0
- package/src/upnp-nat.ts +19 -5
- package/src/upnp-port-mapper.ts +52 -44
- package/LICENSE +0 -4
package/dist/src/constants.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,8BAA8B,QAAS,CAAA;AACpD,eAAO,MAAM,+BAA+B,SAAU,CAAA"}
|
package/dist/src/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,8BAA8B,GAAG,MAAM,CAAA;AACpD,MAAM,CAAC,MAAM,+BAA+B,GAAG,OAAO,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-finder.d.ts","sourceRoot":"","sources":["../../src/gateway-finder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,mBAAmB,CAAA;AAGlE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,mBAAmB,CAAA;AAGhE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;CAChC;AAED,qBAAa,aAAc,SAAQ,iBAAiB,CAAC,mBAAmB,CAAC;IACvE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,OAAO,CAAS;gBAEX,UAAU,EAAE,uBAAuB,EAAE,IAAI,EAAE,iBAAiB;
|
|
1
|
+
{"version":3,"file":"gateway-finder.d.ts","sourceRoot":"","sources":["../../src/gateway-finder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,mBAAmB,CAAA;AAGlE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,mBAAmB,CAAA;AAGhE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;CAChC;AAED,qBAAa,aAAc,SAAQ,iBAAiB,CAAC,mBAAmB,CAAC;IACvE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,OAAO,CAAS;gBAEX,UAAU,EAAE,uBAAuB,EAAE,IAAI,EAAE,iBAAiB;IAgCnE,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;IAS7B;;OAEG;IACG,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;CAI7B"}
|
|
@@ -15,8 +15,13 @@ export class GatewayFinder extends TypedEventEmitter {
|
|
|
15
15
|
this.gateways = [];
|
|
16
16
|
// every five minutes, search for network gateways for one minute
|
|
17
17
|
this.findGateways = repeatingTask(async (options) => {
|
|
18
|
-
for await (const gateway of this.portMappingClient.findGateways(
|
|
19
|
-
|
|
18
|
+
for await (const gateway of this.portMappingClient.findGateways({
|
|
19
|
+
...options,
|
|
20
|
+
searchInterval: 10000
|
|
21
|
+
})) {
|
|
22
|
+
if (this.gateways.some(g => {
|
|
23
|
+
return g.id === gateway.id && g.family === gateway.family;
|
|
24
|
+
})) {
|
|
20
25
|
// already seen this gateway
|
|
21
26
|
continue;
|
|
22
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-finder.js","sourceRoot":"","sources":["../../src/gateway-finder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,+BAA+B,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAA;AAiBhG,MAAM,OAAO,aAAc,SAAQ,iBAAsC;IACtD,GAAG,CAAQ;IACX,QAAQ,CAAW;IACnB,YAAY,CAAe;IAC3B,iBAAiB,CAAS;IACnC,OAAO,CAAS;IAExB,YAAa,UAAmC,EAAE,IAAuB;QACvE,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAA;QAC5D,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAA;QAC/C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;QAElB,iEAAiE;QACjE,IAAI,CAAC,YAAY,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAClD,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway-finder.js","sourceRoot":"","sources":["../../src/gateway-finder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,+BAA+B,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAA;AAiBhG,MAAM,OAAO,aAAc,SAAQ,iBAAsC;IACtD,GAAG,CAAQ;IACX,QAAQ,CAAW;IACnB,YAAY,CAAe;IAC3B,iBAAiB,CAAS;IACnC,OAAO,CAAS;IAExB,YAAa,UAAmC,EAAE,IAAuB;QACvE,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAA;QAC5D,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAA;QAC/C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;QAElB,iEAAiE;QACjE,IAAI,CAAC,YAAY,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAClD,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;gBAC9D,GAAG,OAAO;gBACV,cAAc,EAAE,KAAK;aACtB,CAAC,EAAE,CAAC;gBACH,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oBACzB,OAAO,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAA;gBAC3D,CAAC,CAAC,EAAE,CAAC;oBACH,4BAA4B;oBAC5B,SAAQ;gBACV,CAAC;gBAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC3B,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE;oBAChC,MAAM,EAAE,OAAO;iBAChB,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,EAAE,+BAA+B,EAAE;YAClC,cAAc,EAAE,IAAI;YACpB,OAAO,EAAE,8BAA8B;SACxC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAM;QACR,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,MAAM,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC7B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;CACF"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -76,11 +76,27 @@ export interface UPnPNATInit {
|
|
|
76
76
|
* @default true
|
|
77
77
|
*/
|
|
78
78
|
portMappingAutoRefresh?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* How long before a port mapping expires to refresh it in ms
|
|
81
|
+
*
|
|
82
|
+
* @default 60_000
|
|
83
|
+
*/
|
|
84
|
+
portMappingRefreshThreshold?: number;
|
|
79
85
|
/**
|
|
80
86
|
* A preconfigured instance of a NatAPI client can be passed as an option,
|
|
81
87
|
* otherwise one will be created
|
|
82
88
|
*/
|
|
83
89
|
portMappingClient?: UPnPNATClient;
|
|
90
|
+
/**
|
|
91
|
+
* Any mapped addresses are added to the observed address list. These
|
|
92
|
+
* addresses require additional verification by the `@libp2p/autonat` protocol
|
|
93
|
+
* or similar before they are trusted.
|
|
94
|
+
*
|
|
95
|
+
* To skip this verification and trust them immediately pass `true` here
|
|
96
|
+
*
|
|
97
|
+
* @default false
|
|
98
|
+
*/
|
|
99
|
+
autoConfirmAddress?: boolean;
|
|
84
100
|
}
|
|
85
101
|
export interface UPnPNATComponents {
|
|
86
102
|
peerId: PeerId;
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC5F,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC1G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAEhE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAA;AAE7C,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IAErC;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAA;IAEpC;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAE/B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAEhC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC5F,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC1G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAEhE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAA;AAE7C,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IAErC;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAA;IAEpC;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAE/B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAEhC;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAA;IAEpC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,aAAa,CAAA;IAEjC;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,eAAe,CAAA;IACvB,cAAc,EAAE,cAAc,CAAA;IAC9B,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;CACvC;AAED,MAAM,WAAW,OAAO;IACtB,iBAAiB,EAAE,aAAa,CAAA;CACjC;AAED,wBAAgB,OAAO,CAAE,IAAI,GAAE,WAAgB,GAAG,CAAC,UAAU,EAAE,iBAAiB,KAAK,OAAO,CAI3F"}
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,eAAe,CAAA;AAwFvD,MAAM,UAAU,OAAO,CAAE,OAAoB,EAAE;IAC7C,OAAO,CAAC,UAA6B,EAAE,EAAE;QACvC,OAAO,IAAI,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAC3C,CAAC,CAAA;AACH,CAAC"}
|
package/dist/src/upnp-nat.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { serviceCapabilities } from '@libp2p/interface';
|
|
1
|
+
import { serviceCapabilities, serviceDependencies } from '@libp2p/interface';
|
|
2
2
|
import type { UPnPNATComponents, UPnPNATInit, UPnPNAT as UPnPNATInterface } from './index.js';
|
|
3
3
|
import type { Gateway, UPnPNAT as UPnPNATClient } from '@achingbrain/nat-port-mapper';
|
|
4
4
|
import type { Startable } from '@libp2p/interface';
|
|
@@ -12,9 +12,11 @@ export declare class UPnPNAT implements Startable, UPnPNATInterface {
|
|
|
12
12
|
private readonly mapIpAddressesDebounced;
|
|
13
13
|
private readonly gatewayFinder;
|
|
14
14
|
private readonly portMappers;
|
|
15
|
+
private readonly autoConfirmAddress;
|
|
15
16
|
constructor(components: UPnPNATComponents, init: UPnPNATInit);
|
|
16
17
|
readonly [Symbol.toStringTag] = "@libp2p/upnp-nat";
|
|
17
18
|
readonly [serviceCapabilities]: string[];
|
|
19
|
+
get [serviceDependencies](): string[];
|
|
18
20
|
isStarted(): boolean;
|
|
19
21
|
start(): Promise<void>;
|
|
20
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upnp-nat.d.ts","sourceRoot":"","sources":["../../src/upnp-nat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAgC,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"upnp-nat.d.ts","sourceRoot":"","sources":["../../src/upnp-nat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAgC,MAAM,mBAAmB,CAAA;AAI1G,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7F,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAA;AACrF,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAG1D,qBAAa,OAAQ,YAAW,SAAS,EAAE,gBAAgB;IACzD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,OAAO,CAAS;IACjB,iBAAiB,EAAE,aAAa,CAAA;IACvC,OAAO,CAAC,kBAAkB,CAAC,CAAiB;IAC5C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAmB;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;gBAE/B,UAAU,EAAE,iBAAiB,EAAE,IAAI,EAAE,WAAW;IAgC7D,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,sBAAqB;IAElD,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAEvC;IAED,IAAI,CAAC,mBAAmB,CAAC,IAAK,MAAM,EAAE,CAQrC;IAED,SAAS,IAAK,OAAO;IAIf,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;IAa7B;;OAEG;IACG,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;IAQ5B,mBAAmB,CAAE,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI;IAejD,cAAc,IAAK,OAAO,CAAC,IAAI,CAAC;CAWvC"}
|
package/dist/src/upnp-nat.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { upnpNat } from '@achingbrain/nat-port-mapper';
|
|
2
|
-
import { serviceCapabilities, setMaxListeners, start, stop } from '@libp2p/interface';
|
|
2
|
+
import { serviceCapabilities, serviceDependencies, setMaxListeners, start, stop } from '@libp2p/interface';
|
|
3
3
|
import { debounce } from '@libp2p/utils/debounce';
|
|
4
|
-
import { DEFAULT_PORT_MAPPING_TTL } from './constants.js';
|
|
5
4
|
import { GatewayFinder } from './gateway-finder.js';
|
|
6
5
|
import { UPnPPortMapper } from './upnp-port-mapper.js';
|
|
7
6
|
export class UPnPNAT {
|
|
@@ -14,16 +13,19 @@ export class UPnPNAT {
|
|
|
14
13
|
mapIpAddressesDebounced;
|
|
15
14
|
gatewayFinder;
|
|
16
15
|
portMappers;
|
|
16
|
+
autoConfirmAddress;
|
|
17
17
|
constructor(components, init) {
|
|
18
18
|
this.log = components.logger.forComponent('libp2p:upnp-nat');
|
|
19
19
|
this.components = components;
|
|
20
20
|
this.init = init;
|
|
21
21
|
this.started = false;
|
|
22
22
|
this.portMappers = [];
|
|
23
|
+
this.autoConfirmAddress = init.autoConfirmAddress ?? false;
|
|
23
24
|
this.portMappingClient = init.portMappingClient ?? upnpNat({
|
|
24
25
|
description: init.portMappingDescription ?? `${components.nodeInfo.name}@${components.nodeInfo.version} ${components.peerId.toString()}`,
|
|
25
|
-
ttl: init.portMappingTTL
|
|
26
|
-
autoRefresh: init.portMappingAutoRefresh
|
|
26
|
+
ttl: init.portMappingTTL,
|
|
27
|
+
autoRefresh: init.portMappingAutoRefresh,
|
|
28
|
+
refreshThreshold: init.portMappingRefreshThreshold
|
|
27
29
|
});
|
|
28
30
|
// trigger update when our addresses change
|
|
29
31
|
this.mapIpAddressesDebounced = debounce(async () => {
|
|
@@ -44,6 +46,14 @@ export class UPnPNAT {
|
|
|
44
46
|
[serviceCapabilities] = [
|
|
45
47
|
'@libp2p/nat-traversal'
|
|
46
48
|
];
|
|
49
|
+
get [serviceDependencies]() {
|
|
50
|
+
if (!this.autoConfirmAddress) {
|
|
51
|
+
return [
|
|
52
|
+
'@libp2p/autonat'
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
47
57
|
isStarted() {
|
|
48
58
|
return this.started;
|
|
49
59
|
}
|
|
@@ -82,7 +92,9 @@ export class UPnPNAT {
|
|
|
82
92
|
}
|
|
83
93
|
async mapIpAddresses() {
|
|
84
94
|
try {
|
|
85
|
-
await Promise.all(this.portMappers.map(async (mapper) => mapper.mapIpAddresses(
|
|
95
|
+
await Promise.all(this.portMappers.map(async (mapper) => mapper.mapIpAddresses({
|
|
96
|
+
autoConfirmAddress: this.autoConfirmAddress
|
|
97
|
+
})));
|
|
86
98
|
}
|
|
87
99
|
catch (err) {
|
|
88
100
|
this.log.error('error mapping IP addresses - %e', err);
|
package/dist/src/upnp-nat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upnp-nat.js","sourceRoot":"","sources":["../../src/upnp-nat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"upnp-nat.js","sourceRoot":"","sources":["../../src/upnp-nat.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,9 @@ export interface UPnPPortMapperComponents {
|
|
|
10
10
|
logger: ComponentLogger;
|
|
11
11
|
addressManager: AddressManager;
|
|
12
12
|
}
|
|
13
|
+
export interface MapPortsOptions {
|
|
14
|
+
autoConfirmAddress?: boolean;
|
|
15
|
+
}
|
|
13
16
|
export declare class UPnPPortMapper {
|
|
14
17
|
private readonly gateway;
|
|
15
18
|
private readonly externalAddress;
|
|
@@ -29,7 +32,7 @@ export declare class UPnPPortMapper {
|
|
|
29
32
|
* Return any eligible multiaddrs that are not mapped on the detected gateway
|
|
30
33
|
*/
|
|
31
34
|
private getUnmappedAddresses;
|
|
32
|
-
mapIpAddresses(): Promise<void>;
|
|
35
|
+
mapIpAddresses(options?: MapPortsOptions): Promise<void>;
|
|
33
36
|
/**
|
|
34
37
|
* Some ISPs have double-NATs, there's not much we can do with them
|
|
35
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upnp-port-mapper.d.ts","sourceRoot":"","sources":["../../src/upnp-port-mapper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"upnp-port-mapper.d.ts","sourceRoot":"","sources":["../../src/upnp-port-mapper.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,mBAAmB,CAAA;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAGhE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,4BAA4B,CAAC,EAAE,MAAM,CAAA;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAA;CACrC;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,eAAe,CAAA;IACvB,cAAc,EAAE,cAAc,CAAA;CAC/B;AAOD,MAAM,WAAW,eAAe;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,OAAO,CAAS;gBAEX,UAAU,EAAE,wBAAwB,EAAE,IAAI,EAAE,kBAAkB;IAkBrE,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;IASvB,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;IAe5B;;;OAGG;IACH,OAAO,CAAC,UAAU;IAalB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkDtB,cAAc,CAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA4D/D;;OAEG;IACH,OAAO,CAAC,wBAAwB;CAWjC"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { isIPv4
|
|
1
|
+
import { isIPv4 } from '@chainsafe/is-ip';
|
|
2
2
|
import { InvalidParametersError, start, stop } from '@libp2p/interface';
|
|
3
|
+
import { isLinkLocal } from '@libp2p/utils/multiaddr/is-link-local';
|
|
3
4
|
import { isLoopback } from '@libp2p/utils/multiaddr/is-loopback';
|
|
4
5
|
import { isPrivate } from '@libp2p/utils/multiaddr/is-private';
|
|
5
6
|
import { isPrivateIp } from '@libp2p/utils/private-ip';
|
|
7
|
+
import { multiaddr } from '@multiformats/multiaddr';
|
|
6
8
|
import { QUICV1, TCP, WebSockets, WebSocketsSecure, WebTransport } from '@multiformats/multiaddr-matcher';
|
|
7
9
|
import { dynamicExternalAddress } from './check-external-address.js';
|
|
8
|
-
import { DoubleNATError
|
|
10
|
+
import { DoubleNATError } from './errors.js';
|
|
9
11
|
export class UPnPPortMapper {
|
|
10
12
|
gateway;
|
|
11
13
|
externalAddress;
|
|
@@ -64,17 +66,27 @@ export class UPnPPortMapper {
|
|
|
64
66
|
/**
|
|
65
67
|
* Return any eligible multiaddrs that are not mapped on the detected gateway
|
|
66
68
|
*/
|
|
67
|
-
getUnmappedAddresses(multiaddrs,
|
|
69
|
+
getUnmappedAddresses(multiaddrs, publicAddresses) {
|
|
68
70
|
const output = [];
|
|
69
71
|
for (const ma of multiaddrs) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
const stringTuples = ma.stringTuples();
|
|
73
|
+
const address = `${stringTuples[0][1]}`;
|
|
74
|
+
// ignore public IPv4 addresses
|
|
75
|
+
if (isIPv4(address) && !isPrivate(ma)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
// ignore any addresses that match the interface on the network gateway
|
|
79
|
+
if (publicAddresses.includes(address)) {
|
|
72
80
|
continue;
|
|
73
81
|
}
|
|
74
82
|
// ignore loopback
|
|
75
83
|
if (isLoopback(ma)) {
|
|
76
84
|
continue;
|
|
77
85
|
}
|
|
86
|
+
// ignore link-local addresses
|
|
87
|
+
if (isLinkLocal(ma)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
78
90
|
// only IP based addresses
|
|
79
91
|
if (!(TCP.exactMatch(ma) ||
|
|
80
92
|
WebSockets.exactMatch(ma) ||
|
|
@@ -83,66 +95,57 @@ export class UPnPPortMapper {
|
|
|
83
95
|
WebTransport.exactMatch(ma))) {
|
|
84
96
|
continue;
|
|
85
97
|
}
|
|
86
|
-
const { port,
|
|
87
|
-
if (
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (this.mappedPorts.has(`${host}-${port}-${transport}`)) {
|
|
98
|
+
const { port, transport } = ma.toOptions();
|
|
99
|
+
if (this.mappedPorts.has(`${port}-${transport}`)) {
|
|
91
100
|
continue;
|
|
92
101
|
}
|
|
93
102
|
output.push(ma);
|
|
94
103
|
}
|
|
95
104
|
return output;
|
|
96
105
|
}
|
|
97
|
-
async mapIpAddresses() {
|
|
106
|
+
async mapIpAddresses(options) {
|
|
98
107
|
try {
|
|
99
108
|
const externalHost = await this.externalAddress.getPublicIp();
|
|
100
|
-
let ipType = 4;
|
|
101
|
-
if (isIPv4(externalHost)) {
|
|
102
|
-
ipType = 4;
|
|
103
|
-
}
|
|
104
|
-
else if (isIPv6(externalHost)) {
|
|
105
|
-
ipType = 6;
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
throw new InvalidIPAddressError(`Public address ${externalHost} was not an IPv4 address`);
|
|
109
|
-
}
|
|
110
109
|
// filter addresses to get private, non-relay, IP based addresses that we
|
|
111
110
|
// haven't mapped yet
|
|
112
|
-
const addresses = this.getUnmappedAddresses(this.addressManager.getAddresses(),
|
|
111
|
+
const addresses = this.getUnmappedAddresses(this.addressManager.getAddresses(), [externalHost]);
|
|
113
112
|
if (addresses.length === 0) {
|
|
114
113
|
this.log('no private, non-relay, unmapped, IP based addresses found');
|
|
115
114
|
return;
|
|
116
115
|
}
|
|
117
|
-
this.log('
|
|
116
|
+
this.log('discovered public IP %s', externalHost);
|
|
118
117
|
this.assertNotBehindDoubleNAT(externalHost);
|
|
119
118
|
for (const addr of addresses) {
|
|
120
119
|
// try to open uPnP ports for each thin waist address
|
|
121
|
-
const {
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
const { port, host, transport, family } = addr.toOptions();
|
|
121
|
+
// don't try to open port on IPv6 host via IPv4 gateway
|
|
122
|
+
if (family === 4 && this.gateway.family !== 'IPv4') {
|
|
124
123
|
continue;
|
|
125
124
|
}
|
|
126
|
-
|
|
125
|
+
// don't try to open port on IPv4 host via IPv6 gateway
|
|
126
|
+
if (family === 6 && this.gateway.family !== 'IPv6') {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const key = `${host}-${port}-${transport}`;
|
|
130
|
+
if (this.mappedPorts.has(key)) {
|
|
127
131
|
// already mapped this port
|
|
128
132
|
continue;
|
|
129
133
|
}
|
|
130
134
|
try {
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
const externalPort = await this.gateway.map(port, {
|
|
134
|
-
localAddress: host,
|
|
135
|
-
protocol: transport === 'tcp' ? 'tcp' : 'udp'
|
|
136
|
-
});
|
|
137
|
-
this.mappedPorts.set(key, {
|
|
138
|
-
externalHost,
|
|
139
|
-
externalPort
|
|
135
|
+
const mapping = await this.gateway.map(port, host, {
|
|
136
|
+
protocol: transport === 'tcp' ? 'TCP' : 'UDP'
|
|
140
137
|
});
|
|
141
|
-
this.
|
|
142
|
-
this.addressManager.addPublicAddressMapping(
|
|
138
|
+
this.mappedPorts.set(key, mapping);
|
|
139
|
+
this.addressManager.addPublicAddressMapping(mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport === 'tcp' ? 'tcp' : 'udp');
|
|
140
|
+
this.log('created mapping of %s:%s to %s:%s for protocol %s', mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport);
|
|
141
|
+
if (options?.autoConfirmAddress === true) {
|
|
142
|
+
const ma = multiaddr(`/ip${family}/${host}/${transport}/${port}`);
|
|
143
|
+
this.log('auto-confirming IP address %a', ma);
|
|
144
|
+
this.addressManager.confirmObservedAddr(ma);
|
|
145
|
+
}
|
|
143
146
|
}
|
|
144
147
|
catch (err) {
|
|
145
|
-
this.log.error('failed to create mapping
|
|
148
|
+
this.log.error('failed to create mapping for %s:%d for protocol - %e', host, port, transport, err);
|
|
146
149
|
}
|
|
147
150
|
}
|
|
148
151
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upnp-port-mapper.js","sourceRoot":"","sources":["../../src/upnp-port-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"upnp-port-mapper.js","sourceRoot":"","sources":["../../src/upnp-port-mapper.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/upnp-nat",
|
|
3
|
-
"version": "2.0.12-
|
|
3
|
+
"version": "2.0.12-92cc74082",
|
|
4
4
|
"description": "UPnP NAT hole punching",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/upnp-nat#readme",
|
|
@@ -50,21 +50,21 @@
|
|
|
50
50
|
"test:electron-main": "aegir test -t electron-main"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@achingbrain/nat-port-mapper": "^
|
|
53
|
+
"@achingbrain/nat-port-mapper": "^4.0.0",
|
|
54
54
|
"@chainsafe/is-ip": "^2.0.2",
|
|
55
|
-
"@libp2p/interface": "2.2.1-
|
|
56
|
-
"@libp2p/interface-internal": "2.1.1-
|
|
57
|
-
"@libp2p/utils": "6.2.1-
|
|
58
|
-
"@multiformats/multiaddr": "^12.
|
|
59
|
-
"@multiformats/multiaddr-matcher": "^1.
|
|
55
|
+
"@libp2p/interface": "2.2.1-92cc74082",
|
|
56
|
+
"@libp2p/interface-internal": "2.1.1-92cc74082",
|
|
57
|
+
"@libp2p/utils": "6.2.1-92cc74082",
|
|
58
|
+
"@multiformats/multiaddr": "^12.3.3",
|
|
59
|
+
"@multiformats/multiaddr-matcher": "^1.6.0",
|
|
60
60
|
"p-defer": "^4.0.1",
|
|
61
61
|
"race-signal": "^1.1.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@libp2p/crypto": "5.0.7-
|
|
65
|
-
"@libp2p/logger": "5.1.4-
|
|
66
|
-
"@libp2p/peer-id": "5.0.8-
|
|
67
|
-
"aegir": "^
|
|
64
|
+
"@libp2p/crypto": "5.0.7-92cc74082",
|
|
65
|
+
"@libp2p/logger": "5.1.4-92cc74082",
|
|
66
|
+
"@libp2p/peer-id": "5.0.8-92cc74082",
|
|
67
|
+
"aegir": "^45.0.5",
|
|
68
68
|
"sinon-ts": "^2.0.0"
|
|
69
69
|
},
|
|
70
70
|
"sideEffects": false
|
package/src/constants.ts
CHANGED
package/src/gateway-finder.ts
CHANGED
|
@@ -34,8 +34,13 @@ export class GatewayFinder extends TypedEventEmitter<GatewayFinderEvents> {
|
|
|
34
34
|
|
|
35
35
|
// every five minutes, search for network gateways for one minute
|
|
36
36
|
this.findGateways = repeatingTask(async (options) => {
|
|
37
|
-
for await (const gateway of this.portMappingClient.findGateways(
|
|
38
|
-
|
|
37
|
+
for await (const gateway of this.portMappingClient.findGateways({
|
|
38
|
+
...options,
|
|
39
|
+
searchInterval: 10000
|
|
40
|
+
})) {
|
|
41
|
+
if (this.gateways.some(g => {
|
|
42
|
+
return g.id === gateway.id && g.family === gateway.family
|
|
43
|
+
})) {
|
|
39
44
|
// already seen this gateway
|
|
40
45
|
continue
|
|
41
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -86,11 +86,29 @@ export interface UPnPNATInit {
|
|
|
86
86
|
*/
|
|
87
87
|
portMappingAutoRefresh?: boolean
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* How long before a port mapping expires to refresh it in ms
|
|
91
|
+
*
|
|
92
|
+
* @default 60_000
|
|
93
|
+
*/
|
|
94
|
+
portMappingRefreshThreshold?: number
|
|
95
|
+
|
|
89
96
|
/**
|
|
90
97
|
* A preconfigured instance of a NatAPI client can be passed as an option,
|
|
91
98
|
* otherwise one will be created
|
|
92
99
|
*/
|
|
93
100
|
portMappingClient?: UPnPNATClient
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Any mapped addresses are added to the observed address list. These
|
|
104
|
+
* addresses require additional verification by the `@libp2p/autonat` protocol
|
|
105
|
+
* or similar before they are trusted.
|
|
106
|
+
*
|
|
107
|
+
* To skip this verification and trust them immediately pass `true` here
|
|
108
|
+
*
|
|
109
|
+
* @default false
|
|
110
|
+
*/
|
|
111
|
+
autoConfirmAddress?: boolean
|
|
94
112
|
}
|
|
95
113
|
|
|
96
114
|
export interface UPnPNATComponents {
|
package/src/upnp-nat.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { upnpNat } from '@achingbrain/nat-port-mapper'
|
|
2
|
-
import { serviceCapabilities, setMaxListeners, start, stop } from '@libp2p/interface'
|
|
2
|
+
import { serviceCapabilities, serviceDependencies, setMaxListeners, start, stop } from '@libp2p/interface'
|
|
3
3
|
import { debounce } from '@libp2p/utils/debounce'
|
|
4
|
-
import { DEFAULT_PORT_MAPPING_TTL } from './constants.js'
|
|
5
4
|
import { GatewayFinder } from './gateway-finder.js'
|
|
6
5
|
import { UPnPPortMapper } from './upnp-port-mapper.js'
|
|
7
6
|
import type { UPnPNATComponents, UPnPNATInit, UPnPNAT as UPnPNATInterface } from './index.js'
|
|
@@ -19,6 +18,7 @@ export class UPnPNAT implements Startable, UPnPNATInterface {
|
|
|
19
18
|
private readonly mapIpAddressesDebounced: DebouncedFunction
|
|
20
19
|
private readonly gatewayFinder: GatewayFinder
|
|
21
20
|
private readonly portMappers: UPnPPortMapper[]
|
|
21
|
+
private readonly autoConfirmAddress: boolean
|
|
22
22
|
|
|
23
23
|
constructor (components: UPnPNATComponents, init: UPnPNATInit) {
|
|
24
24
|
this.log = components.logger.forComponent('libp2p:upnp-nat')
|
|
@@ -26,11 +26,13 @@ export class UPnPNAT implements Startable, UPnPNATInterface {
|
|
|
26
26
|
this.init = init
|
|
27
27
|
this.started = false
|
|
28
28
|
this.portMappers = []
|
|
29
|
+
this.autoConfirmAddress = init.autoConfirmAddress ?? false
|
|
29
30
|
|
|
30
31
|
this.portMappingClient = init.portMappingClient ?? upnpNat({
|
|
31
32
|
description: init.portMappingDescription ?? `${components.nodeInfo.name}@${components.nodeInfo.version} ${components.peerId.toString()}`,
|
|
32
|
-
ttl: init.portMappingTTL
|
|
33
|
-
autoRefresh: init.portMappingAutoRefresh
|
|
33
|
+
ttl: init.portMappingTTL,
|
|
34
|
+
autoRefresh: init.portMappingAutoRefresh,
|
|
35
|
+
refreshThreshold: init.portMappingRefreshThreshold
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
// trigger update when our addresses change
|
|
@@ -56,6 +58,16 @@ export class UPnPNAT implements Startable, UPnPNATInterface {
|
|
|
56
58
|
'@libp2p/nat-traversal'
|
|
57
59
|
]
|
|
58
60
|
|
|
61
|
+
get [serviceDependencies] (): string[] {
|
|
62
|
+
if (!this.autoConfirmAddress) {
|
|
63
|
+
return [
|
|
64
|
+
'@libp2p/autonat'
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return []
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
isStarted (): boolean {
|
|
60
72
|
return this.started
|
|
61
73
|
}
|
|
@@ -102,7 +114,9 @@ export class UPnPNAT implements Startable, UPnPNATInterface {
|
|
|
102
114
|
async mapIpAddresses (): Promise<void> {
|
|
103
115
|
try {
|
|
104
116
|
await Promise.all(
|
|
105
|
-
this.portMappers.map(async mapper => mapper.mapIpAddresses(
|
|
117
|
+
this.portMappers.map(async mapper => mapper.mapIpAddresses({
|
|
118
|
+
autoConfirmAddress: this.autoConfirmAddress
|
|
119
|
+
}))
|
|
106
120
|
)
|
|
107
121
|
} catch (err: any) {
|
|
108
122
|
this.log.error('error mapping IP addresses - %e', err)
|
package/src/upnp-port-mapper.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { isIPv4
|
|
1
|
+
import { isIPv4 } from '@chainsafe/is-ip'
|
|
2
2
|
import { InvalidParametersError, start, stop } from '@libp2p/interface'
|
|
3
|
+
import { isLinkLocal } from '@libp2p/utils/multiaddr/is-link-local'
|
|
3
4
|
import { isLoopback } from '@libp2p/utils/multiaddr/is-loopback'
|
|
4
5
|
import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
|
|
5
6
|
import { isPrivateIp } from '@libp2p/utils/private-ip'
|
|
7
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
6
8
|
import { QUICV1, TCP, WebSockets, WebSocketsSecure, WebTransport } from '@multiformats/multiaddr-matcher'
|
|
7
9
|
import { dynamicExternalAddress } from './check-external-address.js'
|
|
8
|
-
import { DoubleNATError
|
|
10
|
+
import { DoubleNATError } from './errors.js'
|
|
9
11
|
import type { ExternalAddress } from './check-external-address.js'
|
|
10
12
|
import type { Gateway } from '@achingbrain/nat-port-mapper'
|
|
11
13
|
import type { ComponentLogger, Logger } from '@libp2p/interface'
|
|
@@ -28,6 +30,10 @@ interface PortMapping {
|
|
|
28
30
|
externalPort: number
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
export interface MapPortsOptions {
|
|
34
|
+
autoConfirmAddress?: boolean
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
export class UPnPPortMapper {
|
|
32
38
|
private readonly gateway: Gateway
|
|
33
39
|
private readonly externalAddress: ExternalAddress
|
|
@@ -98,12 +104,20 @@ export class UPnPPortMapper {
|
|
|
98
104
|
/**
|
|
99
105
|
* Return any eligible multiaddrs that are not mapped on the detected gateway
|
|
100
106
|
*/
|
|
101
|
-
private getUnmappedAddresses (multiaddrs: Multiaddr[],
|
|
107
|
+
private getUnmappedAddresses (multiaddrs: Multiaddr[], publicAddresses: string[]): Multiaddr[] {
|
|
102
108
|
const output: Multiaddr[] = []
|
|
103
109
|
|
|
104
110
|
for (const ma of multiaddrs) {
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
const stringTuples = ma.stringTuples()
|
|
112
|
+
const address = `${stringTuples[0][1]}`
|
|
113
|
+
|
|
114
|
+
// ignore public IPv4 addresses
|
|
115
|
+
if (isIPv4(address) && !isPrivate(ma)) {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ignore any addresses that match the interface on the network gateway
|
|
120
|
+
if (publicAddresses.includes(address)) {
|
|
107
121
|
continue
|
|
108
122
|
}
|
|
109
123
|
|
|
@@ -112,6 +126,11 @@ export class UPnPPortMapper {
|
|
|
112
126
|
continue
|
|
113
127
|
}
|
|
114
128
|
|
|
129
|
+
// ignore link-local addresses
|
|
130
|
+
if (isLinkLocal(ma)) {
|
|
131
|
+
continue
|
|
132
|
+
}
|
|
133
|
+
|
|
115
134
|
// only IP based addresses
|
|
116
135
|
if (!(
|
|
117
136
|
TCP.exactMatch(ma) ||
|
|
@@ -123,13 +142,9 @@ export class UPnPPortMapper {
|
|
|
123
142
|
continue
|
|
124
143
|
}
|
|
125
144
|
|
|
126
|
-
const { port,
|
|
127
|
-
|
|
128
|
-
if (family !== ipType) {
|
|
129
|
-
continue
|
|
130
|
-
}
|
|
145
|
+
const { port, transport } = ma.toOptions()
|
|
131
146
|
|
|
132
|
-
if (this.mappedPorts.has(`${
|
|
147
|
+
if (this.mappedPorts.has(`${port}-${transport}`)) {
|
|
133
148
|
continue
|
|
134
149
|
}
|
|
135
150
|
|
|
@@ -139,66 +154,59 @@ export class UPnPPortMapper {
|
|
|
139
154
|
return output
|
|
140
155
|
}
|
|
141
156
|
|
|
142
|
-
async mapIpAddresses (): Promise<void> {
|
|
157
|
+
async mapIpAddresses (options?: MapPortsOptions): Promise<void> {
|
|
143
158
|
try {
|
|
144
159
|
const externalHost = await this.externalAddress.getPublicIp()
|
|
145
160
|
|
|
146
|
-
let ipType: 4 | 6 = 4
|
|
147
|
-
|
|
148
|
-
if (isIPv4(externalHost)) {
|
|
149
|
-
ipType = 4
|
|
150
|
-
} else if (isIPv6(externalHost)) {
|
|
151
|
-
ipType = 6
|
|
152
|
-
} else {
|
|
153
|
-
throw new InvalidIPAddressError(`Public address ${externalHost} was not an IPv4 address`)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
161
|
// filter addresses to get private, non-relay, IP based addresses that we
|
|
157
162
|
// haven't mapped yet
|
|
158
|
-
const addresses = this.getUnmappedAddresses(this.addressManager.getAddresses(),
|
|
163
|
+
const addresses = this.getUnmappedAddresses(this.addressManager.getAddresses(), [externalHost])
|
|
159
164
|
|
|
160
165
|
if (addresses.length === 0) {
|
|
161
166
|
this.log('no private, non-relay, unmapped, IP based addresses found')
|
|
162
167
|
return
|
|
163
168
|
}
|
|
164
169
|
|
|
165
|
-
this.log('
|
|
170
|
+
this.log('discovered public IP %s', externalHost)
|
|
166
171
|
|
|
167
172
|
this.assertNotBehindDoubleNAT(externalHost)
|
|
168
173
|
|
|
169
174
|
for (const addr of addresses) {
|
|
170
175
|
// try to open uPnP ports for each thin waist address
|
|
171
|
-
const {
|
|
176
|
+
const { port, host, transport, family } = addr.toOptions()
|
|
172
177
|
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
// don't try to open port on IPv6 host via IPv4 gateway
|
|
179
|
+
if (family === 4 && this.gateway.family !== 'IPv4') {
|
|
175
180
|
continue
|
|
176
181
|
}
|
|
177
182
|
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
// don't try to open port on IPv4 host via IPv6 gateway
|
|
184
|
+
if (family === 6 && this.gateway.family !== 'IPv6') {
|
|
180
185
|
continue
|
|
181
186
|
}
|
|
182
187
|
|
|
183
|
-
|
|
184
|
-
const key = `${host}-${port}-${transport}`
|
|
185
|
-
this.log('creating mapping of key %s', key)
|
|
188
|
+
const key = `${host}-${port}-${transport}`
|
|
186
189
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
if (this.mappedPorts.has(key)) {
|
|
191
|
+
// already mapped this port
|
|
192
|
+
continue
|
|
193
|
+
}
|
|
191
194
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
try {
|
|
196
|
+
const mapping = await this.gateway.map(port, host, {
|
|
197
|
+
protocol: transport === 'tcp' ? 'TCP' : 'UDP'
|
|
195
198
|
})
|
|
196
|
-
|
|
197
|
-
this.
|
|
198
|
-
|
|
199
|
-
|
|
199
|
+
this.mappedPorts.set(key, mapping)
|
|
200
|
+
this.addressManager.addPublicAddressMapping(mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport === 'tcp' ? 'tcp' : 'udp')
|
|
201
|
+
this.log('created mapping of %s:%s to %s:%s for protocol %s', mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport)
|
|
202
|
+
|
|
203
|
+
if (options?.autoConfirmAddress === true) {
|
|
204
|
+
const ma = multiaddr(`/ip${family}/${host}/${transport}/${port}`)
|
|
205
|
+
this.log('auto-confirming IP address %a', ma)
|
|
206
|
+
this.addressManager.confirmObservedAddr(ma)
|
|
207
|
+
}
|
|
200
208
|
} catch (err) {
|
|
201
|
-
this.log.error('failed to create mapping
|
|
209
|
+
this.log.error('failed to create mapping for %s:%d for protocol - %e', host, port, transport, err)
|
|
202
210
|
}
|
|
203
211
|
}
|
|
204
212
|
} catch (err: any) {
|
package/LICENSE
DELETED