@libp2p/upnp-nat 2.0.12-4761dd701 → 2.0.12-48e9cfa56
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 +5 -1
- package/dist/src/upnp-port-mapper.d.ts.map +1 -1
- package/dist/src/upnp-port-mapper.js +57 -44
- 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 +71 -52
- 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,10 +32,11 @@ 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
|
*/
|
|
36
39
|
private assertNotBehindDoubleNAT;
|
|
40
|
+
private isIPAddress;
|
|
37
41
|
}
|
|
38
42
|
//# sourceMappingURL=upnp-port-mapper.d.ts.map
|
|
@@ -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;AAK7E,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;IAiDtB,cAAc,CAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA8D/D;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -1,11 +1,14 @@
|
|
|
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';
|
|
11
|
+
const MAX_DATE = 8_640_000_000_000_000;
|
|
9
12
|
export class UPnPPortMapper {
|
|
10
13
|
gateway;
|
|
11
14
|
externalAddress;
|
|
@@ -64,85 +67,88 @@ export class UPnPPortMapper {
|
|
|
64
67
|
/**
|
|
65
68
|
* Return any eligible multiaddrs that are not mapped on the detected gateway
|
|
66
69
|
*/
|
|
67
|
-
getUnmappedAddresses(multiaddrs,
|
|
70
|
+
getUnmappedAddresses(multiaddrs, publicAddresses) {
|
|
68
71
|
const output = [];
|
|
69
|
-
for (const ma of multiaddrs) {
|
|
70
|
-
// ignore
|
|
71
|
-
if (
|
|
72
|
+
for (const { multiaddr: ma, type } of multiaddrs) {
|
|
73
|
+
// only consider transport addresses, ignore mapped/observed addrs
|
|
74
|
+
if (type !== 'transport') {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const stringTuples = ma.stringTuples();
|
|
78
|
+
const address = `${stringTuples[0][1]}`;
|
|
79
|
+
// ignore public IPv4 addresses
|
|
80
|
+
if (isIPv4(address) && !isPrivate(ma)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// ignore any addresses that match the interface on the network gateway
|
|
84
|
+
if (publicAddresses.includes(address)) {
|
|
72
85
|
continue;
|
|
73
86
|
}
|
|
74
87
|
// ignore loopback
|
|
75
88
|
if (isLoopback(ma)) {
|
|
76
89
|
continue;
|
|
77
90
|
}
|
|
78
|
-
//
|
|
79
|
-
if (
|
|
80
|
-
WebSockets.exactMatch(ma) ||
|
|
81
|
-
WebSocketsSecure.exactMatch(ma) ||
|
|
82
|
-
QUICV1.exactMatch(ma) ||
|
|
83
|
-
WebTransport.exactMatch(ma))) {
|
|
91
|
+
// ignore link-local addresses
|
|
92
|
+
if (isLinkLocal(ma)) {
|
|
84
93
|
continue;
|
|
85
94
|
}
|
|
86
|
-
|
|
87
|
-
if (
|
|
95
|
+
// only IP based addresses
|
|
96
|
+
if (!this.isIPAddress(ma)) {
|
|
88
97
|
continue;
|
|
89
98
|
}
|
|
90
|
-
|
|
99
|
+
const { port, transport } = ma.toOptions();
|
|
100
|
+
if (this.mappedPorts.has(`${port}-${transport}`)) {
|
|
91
101
|
continue;
|
|
92
102
|
}
|
|
93
103
|
output.push(ma);
|
|
94
104
|
}
|
|
95
105
|
return output;
|
|
96
106
|
}
|
|
97
|
-
async mapIpAddresses() {
|
|
107
|
+
async mapIpAddresses(options) {
|
|
98
108
|
try {
|
|
99
109
|
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
110
|
// filter addresses to get private, non-relay, IP based addresses that we
|
|
111
111
|
// haven't mapped yet
|
|
112
|
-
const addresses = this.getUnmappedAddresses(this.addressManager.
|
|
112
|
+
const addresses = this.getUnmappedAddresses(this.addressManager.getAddressesWithMetadata(), [externalHost]);
|
|
113
113
|
if (addresses.length === 0) {
|
|
114
114
|
this.log('no private, non-relay, unmapped, IP based addresses found');
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
|
-
this.log('
|
|
117
|
+
this.log('discovered public IP %s', externalHost);
|
|
118
118
|
this.assertNotBehindDoubleNAT(externalHost);
|
|
119
119
|
for (const addr of addresses) {
|
|
120
120
|
// try to open uPnP ports for each thin waist address
|
|
121
|
-
const {
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
const { port, host, transport, family } = addr.toOptions();
|
|
122
|
+
// don't try to open port on IPv6 host via IPv4 gateway
|
|
123
|
+
if (family === 4 && this.gateway.family !== 'IPv4') {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
// don't try to open port on IPv4 host via IPv6 gateway
|
|
127
|
+
if (family === 6 && this.gateway.family !== 'IPv6') {
|
|
124
128
|
continue;
|
|
125
129
|
}
|
|
126
|
-
|
|
130
|
+
const key = `${host}-${port}-${transport}`;
|
|
131
|
+
if (this.mappedPorts.has(key)) {
|
|
127
132
|
// already mapped this port
|
|
128
133
|
continue;
|
|
129
134
|
}
|
|
130
135
|
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
|
|
136
|
+
const mapping = await this.gateway.map(port, host, {
|
|
137
|
+
protocol: transport === 'tcp' ? 'TCP' : 'UDP'
|
|
140
138
|
});
|
|
141
|
-
this.
|
|
142
|
-
this.addressManager.addPublicAddressMapping(
|
|
139
|
+
this.mappedPorts.set(key, mapping);
|
|
140
|
+
this.addressManager.addPublicAddressMapping(mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport === 'tcp' ? 'tcp' : 'udp');
|
|
141
|
+
this.log('created mapping of %s:%s to %s:%s for protocol %s', mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport);
|
|
142
|
+
if (options?.autoConfirmAddress === true) {
|
|
143
|
+
const ma = multiaddr(`/ip${family}/${host}/${transport}/${port}`);
|
|
144
|
+
this.log('auto-confirming IP address %a', ma);
|
|
145
|
+
this.addressManager.confirmObservedAddr(ma, {
|
|
146
|
+
ttl: MAX_DATE - Date.now()
|
|
147
|
+
});
|
|
148
|
+
}
|
|
143
149
|
}
|
|
144
150
|
catch (err) {
|
|
145
|
-
this.log.error('failed to create mapping
|
|
151
|
+
this.log.error('failed to create mapping for %s:%d for protocol - %e', host, port, transport, err);
|
|
146
152
|
}
|
|
147
153
|
}
|
|
148
154
|
}
|
|
@@ -162,5 +168,12 @@ export class UPnPPortMapper {
|
|
|
162
168
|
throw new InvalidParametersError(`${publicIp} is not an IP address`);
|
|
163
169
|
}
|
|
164
170
|
}
|
|
171
|
+
isIPAddress(ma) {
|
|
172
|
+
return TCP.exactMatch(ma) ||
|
|
173
|
+
WebSockets.exactMatch(ma) ||
|
|
174
|
+
WebSocketsSecure.exactMatch(ma) ||
|
|
175
|
+
QUICV1.exactMatch(ma) ||
|
|
176
|
+
WebTransport.exactMatch(ma);
|
|
177
|
+
}
|
|
165
178
|
}
|
|
166
179
|
//# sourceMappingURL=upnp-port-mapper.js.map
|
|
@@ -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-48e9cfa56",
|
|
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-48e9cfa56",
|
|
56
|
+
"@libp2p/interface-internal": "2.1.1-48e9cfa56",
|
|
57
|
+
"@libp2p/utils": "6.2.1-48e9cfa56",
|
|
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-48e9cfa56",
|
|
65
|
+
"@libp2p/logger": "5.1.4-48e9cfa56",
|
|
66
|
+
"@libp2p/peer-id": "5.0.8-48e9cfa56",
|
|
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,17 +1,21 @@
|
|
|
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'
|
|
12
|
-
import type { AddressManager } from '@libp2p/interface-internal'
|
|
14
|
+
import type { AddressManager, NodeAddress } from '@libp2p/interface-internal'
|
|
13
15
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
14
16
|
|
|
17
|
+
const MAX_DATE = 8_640_000_000_000_000
|
|
18
|
+
|
|
15
19
|
export interface UPnPPortMapperInit {
|
|
16
20
|
gateway: Gateway
|
|
17
21
|
externalAddressCheckInterval?: number
|
|
@@ -28,6 +32,10 @@ interface PortMapping {
|
|
|
28
32
|
externalPort: number
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
export interface MapPortsOptions {
|
|
36
|
+
autoConfirmAddress?: boolean
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
export class UPnPPortMapper {
|
|
32
40
|
private readonly gateway: Gateway
|
|
33
41
|
private readonly externalAddress: ExternalAddress
|
|
@@ -98,12 +106,25 @@ export class UPnPPortMapper {
|
|
|
98
106
|
/**
|
|
99
107
|
* Return any eligible multiaddrs that are not mapped on the detected gateway
|
|
100
108
|
*/
|
|
101
|
-
private getUnmappedAddresses (multiaddrs:
|
|
109
|
+
private getUnmappedAddresses (multiaddrs: NodeAddress[], publicAddresses: string[]): Multiaddr[] {
|
|
102
110
|
const output: Multiaddr[] = []
|
|
103
111
|
|
|
104
|
-
for (const ma of multiaddrs) {
|
|
105
|
-
// ignore
|
|
106
|
-
if (
|
|
112
|
+
for (const { multiaddr: ma, type } of multiaddrs) {
|
|
113
|
+
// only consider transport addresses, ignore mapped/observed addrs
|
|
114
|
+
if (type !== 'transport') {
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const stringTuples = ma.stringTuples()
|
|
119
|
+
const address = `${stringTuples[0][1]}`
|
|
120
|
+
|
|
121
|
+
// ignore public IPv4 addresses
|
|
122
|
+
if (isIPv4(address) && !isPrivate(ma)) {
|
|
123
|
+
continue
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ignore any addresses that match the interface on the network gateway
|
|
127
|
+
if (publicAddresses.includes(address)) {
|
|
107
128
|
continue
|
|
108
129
|
}
|
|
109
130
|
|
|
@@ -112,24 +133,19 @@ export class UPnPPortMapper {
|
|
|
112
133
|
continue
|
|
113
134
|
}
|
|
114
135
|
|
|
115
|
-
//
|
|
116
|
-
if (
|
|
117
|
-
TCP.exactMatch(ma) ||
|
|
118
|
-
WebSockets.exactMatch(ma) ||
|
|
119
|
-
WebSocketsSecure.exactMatch(ma) ||
|
|
120
|
-
QUICV1.exactMatch(ma) ||
|
|
121
|
-
WebTransport.exactMatch(ma)
|
|
122
|
-
)) {
|
|
136
|
+
// ignore link-local addresses
|
|
137
|
+
if (isLinkLocal(ma)) {
|
|
123
138
|
continue
|
|
124
139
|
}
|
|
125
140
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (family !== ipType) {
|
|
141
|
+
// only IP based addresses
|
|
142
|
+
if (!this.isIPAddress(ma)) {
|
|
129
143
|
continue
|
|
130
144
|
}
|
|
131
145
|
|
|
132
|
-
|
|
146
|
+
const { port, transport } = ma.toOptions()
|
|
147
|
+
|
|
148
|
+
if (this.mappedPorts.has(`${port}-${transport}`)) {
|
|
133
149
|
continue
|
|
134
150
|
}
|
|
135
151
|
|
|
@@ -139,66 +155,61 @@ export class UPnPPortMapper {
|
|
|
139
155
|
return output
|
|
140
156
|
}
|
|
141
157
|
|
|
142
|
-
async mapIpAddresses (): Promise<void> {
|
|
158
|
+
async mapIpAddresses (options?: MapPortsOptions): Promise<void> {
|
|
143
159
|
try {
|
|
144
160
|
const externalHost = await this.externalAddress.getPublicIp()
|
|
145
161
|
|
|
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
162
|
// filter addresses to get private, non-relay, IP based addresses that we
|
|
157
163
|
// haven't mapped yet
|
|
158
|
-
const addresses = this.getUnmappedAddresses(this.addressManager.
|
|
164
|
+
const addresses = this.getUnmappedAddresses(this.addressManager.getAddressesWithMetadata(), [externalHost])
|
|
159
165
|
|
|
160
166
|
if (addresses.length === 0) {
|
|
161
167
|
this.log('no private, non-relay, unmapped, IP based addresses found')
|
|
162
168
|
return
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
this.log('
|
|
171
|
+
this.log('discovered public IP %s', externalHost)
|
|
166
172
|
|
|
167
173
|
this.assertNotBehindDoubleNAT(externalHost)
|
|
168
174
|
|
|
169
175
|
for (const addr of addresses) {
|
|
170
176
|
// try to open uPnP ports for each thin waist address
|
|
171
|
-
const {
|
|
177
|
+
const { port, host, transport, family } = addr.toOptions()
|
|
172
178
|
|
|
173
|
-
|
|
174
|
-
|
|
179
|
+
// don't try to open port on IPv6 host via IPv4 gateway
|
|
180
|
+
if (family === 4 && this.gateway.family !== 'IPv4') {
|
|
175
181
|
continue
|
|
176
182
|
}
|
|
177
183
|
|
|
178
|
-
|
|
179
|
-
|
|
184
|
+
// don't try to open port on IPv4 host via IPv6 gateway
|
|
185
|
+
if (family === 6 && this.gateway.family !== 'IPv6') {
|
|
180
186
|
continue
|
|
181
187
|
}
|
|
182
188
|
|
|
183
|
-
|
|
184
|
-
const key = `${host}-${port}-${transport}`
|
|
185
|
-
this.log('creating mapping of key %s', key)
|
|
189
|
+
const key = `${host}-${port}-${transport}`
|
|
186
190
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
if (this.mappedPorts.has(key)) {
|
|
192
|
+
// already mapped this port
|
|
193
|
+
continue
|
|
194
|
+
}
|
|
191
195
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
196
|
+
try {
|
|
197
|
+
const mapping = await this.gateway.map(port, host, {
|
|
198
|
+
protocol: transport === 'tcp' ? 'TCP' : 'UDP'
|
|
195
199
|
})
|
|
196
|
-
|
|
197
|
-
this.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
+
this.mappedPorts.set(key, mapping)
|
|
201
|
+
this.addressManager.addPublicAddressMapping(mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport === 'tcp' ? 'tcp' : 'udp')
|
|
202
|
+
this.log('created mapping of %s:%s to %s:%s for protocol %s', mapping.internalHost, mapping.internalPort, mapping.externalHost, mapping.externalPort, transport)
|
|
203
|
+
|
|
204
|
+
if (options?.autoConfirmAddress === true) {
|
|
205
|
+
const ma = multiaddr(`/ip${family}/${host}/${transport}/${port}`)
|
|
206
|
+
this.log('auto-confirming IP address %a', ma)
|
|
207
|
+
this.addressManager.confirmObservedAddr(ma, {
|
|
208
|
+
ttl: MAX_DATE - Date.now()
|
|
209
|
+
})
|
|
210
|
+
}
|
|
200
211
|
} catch (err) {
|
|
201
|
-
this.log.error('failed to create mapping
|
|
212
|
+
this.log.error('failed to create mapping for %s:%d for protocol - %e', host, port, transport, err)
|
|
202
213
|
}
|
|
203
214
|
}
|
|
204
215
|
} catch (err: any) {
|
|
@@ -220,4 +231,12 @@ export class UPnPPortMapper {
|
|
|
220
231
|
throw new InvalidParametersError(`${publicIp} is not an IP address`)
|
|
221
232
|
}
|
|
222
233
|
}
|
|
234
|
+
|
|
235
|
+
private isIPAddress (ma: Multiaddr): boolean {
|
|
236
|
+
return TCP.exactMatch(ma) ||
|
|
237
|
+
WebSockets.exactMatch(ma) ||
|
|
238
|
+
WebSocketsSecure.exactMatch(ma) ||
|
|
239
|
+
QUICV1.exactMatch(ma) ||
|
|
240
|
+
WebTransport.exactMatch(ma)
|
|
241
|
+
}
|
|
223
242
|
}
|
package/LICENSE
DELETED