NAT port mapping

This commit is contained in:
Ștefan Talpalaru 2019-04-17 03:56:28 +02:00
parent 91bf7630ae
commit d4aff04cbd
No known key found for this signature in database
GPG Key ID: CBF7934204F1B6F9
10 changed files with 72 additions and 10 deletions

10
.gitmodules vendored
View File

@ -128,3 +128,13 @@
url = https://github.com/status-im/nim-libp2p.git
ignore = dirty
branch = master
[submodule "vendor/nim-result"]
path = vendor/nim-result
url = https://github.com/arnetheduck/nim-result.git
ignore = dirty
branch = master
[submodule "vendor/nim-nat-traversal"]
path = vendor/nim-nat-traversal
url = https://github.com/status-im/nim-nat-traversal.git
ignore = dirty
branch = master

View File

@ -83,7 +83,7 @@ TOOLS_DIRS := premix tests
# comma-separated values for the "clean" target
TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
.PHONY: all $(TOOLS) deps github-ssh build-nim update status ntags ctags nimbus testsuite test clean mrproper fetch-dlls test-libp2p-daemon
.PHONY: all $(TOOLS) deps github-ssh build-nim update status ntags ctags nimbus testsuite test clean mrproper fetch-dlls test-libp2p-daemon nat-libs libminiupnpc.a libnatpmp.a
# default target, because it's the first one that doesn't start with '.'
all: $(TOOLS) nimbus
@ -100,7 +100,7 @@ $(TOOLS): | build deps
$(ENV_SCRIPT) nim c $(NIM_PARAMS) -o:build/$@ "$${TOOL_DIR}/$@.nim"
# a phony target, because teaching `make` how to do conditional recompilation of Nim projects is too complicated
nimbus: | build deps
nimbus: | build deps nat-libs
echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim nimbus $(NIM_PARAMS) nimbus.nims
@ -114,6 +114,14 @@ build:
# and a check for the actual compiler build
deps: $(NIM_BINARY) $(NIMBLE_DIR) nimbus.nims
nat-libs: | libminiupnpc.a libnatpmp.a
libminiupnpc.a: | deps
+ $(MAKE) -C vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc $@ $(HANDLE_OUTPUT)
libnatpmp.a: | deps
+ $(MAKE) -C vendor/nim-nat-traversal/vendor/libnatpmp $@ $(HANDLE_OUTPUT)
#- depends on Git submodules being initialised
#- fakes a Nimble package repository with the minimum info needed by the Nim compiler
# for runtime path (i.e.: the second line in $(NIMBLE_DIR)/pkgs/*/*.nimble-link)
@ -147,6 +155,8 @@ test-reproducibility:
clean:
rm -rf build/{nimbus,$(TOOLS_CSV),all_tests,test_rpc,*.exe} vendor/go/bin \
$(NIMBLE_DIR) $(NIM_BINARY) $(NIM_DIR)/nimcache nimcache
+ $(MAKE) -C vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc clean $(HANDLE_OUTPUT)
+ $(MAKE) -C vendor/nim-nat-traversal/vendor/libnatpmp clean $(HANDLE_OUTPUT)
# dangerous cleaning, because you may have not-yet-pushed branches and commits in those vendor repos you're about to delete
mrproper: clean

View File

@ -9,3 +9,5 @@
passL = "-Wl,--no-insert-timestamp"
@end
--threads:on

View File

@ -9,7 +9,7 @@
import
parseopt, strutils, macros, os, times,
chronos, eth/[keys, common, p2p], chronicles, nimcrypto/hash,
chronos, eth/[keys, common, p2p, net/nat], chronicles, nimcrypto/hash,
./db/select_backend,
./vm/interpreter/vm_forks
@ -132,6 +132,8 @@ type
networkId*: uint ## Network ID as integer
ident*: string ## Server ident name string
nodeKey*: PrivateKey ## Server private key
nat*: NatStrategy ## NAT strategy
externalIP*: string ## user-provided external IP
DebugConfiguration* = object
## Debug configuration object
@ -474,6 +476,23 @@ proc processNetArguments(key, value: string): ConfigStatus =
config.net.nodeKey = res
elif skey == "ident":
config.net.ident = value
elif skey == "nat":
case value.toLowerAscii:
of "any":
config.net.nat = NatAny
of "upnp":
config.net.nat = NatUpnp
of "pmp":
config.net.nat = NatPmp
of "none":
config.net.nat = NatNone
else:
if isIpAddress(value):
config.net.externalIP = value
config.net.nat = NatNone
else:
error "not a valid NAT mechanism, nor a valid IP address", value
result = ErrorParseOption
else:
result = EmptyOption
@ -551,6 +570,7 @@ proc initConfiguration(): NimbusConfiguration =
result.net.bindPort = 30303'u16
result.net.discPort = 30303'u16
result.net.ident = NimbusIdent
result.net.nat = NatAny
const dataDir = getDefaultDataDir()
@ -592,6 +612,7 @@ NETWORKING OPTIONS:
--discport:<value> Network listening UDP port (defaults to --port argument)
--maxpeers:<value> Maximum number of network peers (default: 25)
--maxpendpeers:<value> Maximum number of pending connection attempts (default: 0)
--nat:<value> NAT port mapping mechanism (any|none|upnp|pmp|<external IP>) (default: "any")
--nodiscover Disables the peer discovery mechanism (manual peer addition)
--v5discover Enables the experimental RLPx V5 (Topic Discovery) mechanism
--nodekey:<value> P2P node private key (as hexadecimal string)

View File

@ -2,5 +2,4 @@
-d:"chronicles_sinks=textlines[file]"
-d:"chronicles_runtime_filtering=on"
-d:nimDebugDlOpen
--threads:on

View File

@ -8,11 +8,12 @@
# those terms.
import
os, strutils, net, eth/keys, db/[storage_types, db_chain, select_backend],
os, strutils, net, options,
eth/keys, db/[storage_types, db_chain, select_backend],
eth/common as eth_common, eth/p2p as eth_p2p,
chronos, json_rpc/rpcserver, chronicles,
eth/p2p/rlpx_protocols/[eth_protocol, les_protocol],
eth/p2p/blockchain_sync,
eth/p2p/blockchain_sync, eth/net/nat,
config, genesis, rpc/[common, p2p, debug, whisper], p2p/chain,
eth/trie/db
@ -43,8 +44,6 @@ proc start(): NimbusObject =
setLogLevel(conf.debug.logLevel)
if len(conf.debug.logFile) != 0:
discard defaultChroniclesStream.output.open(conf.debug.logFile, fmAppend)
else:
discard defaultChroniclesStream.output.open(stdout)
## Creating RPC Server
if RpcFlags.Enabled in conf.rpc.flags:
@ -63,6 +62,23 @@ proc start(): NimbusObject =
address.ip = parseIpAddress("0.0.0.0")
address.tcpPort = Port(conf.net.bindPort)
address.udpPort = Port(conf.net.discPort)
if conf.net.nat == NatNone:
if conf.net.externalIP != "":
# any required port redirection is assumed to be done by hand
address.ip = parseIpAddress(conf.net.externalIP)
else:
# automated NAT traversal
let extIP = getExternalIP(conf.net.nat)
# TODO: dynamic IPs are common, so our external IP might change while the
# program is running. How can we update our advertised enode address and any
# other place that might use this external IP?
if extIP.isSome:
address.ip = extIP.get()
let extPorts = redirectPorts(tcpPort = address.tcpPort,
udpPort = address.udpPort,
description = NIMBUS_NAME & " " & NIMBUS_VERSION)
if extPorts.isSome:
(address.tcpPort, address.udpPort) = extPorts.get()
createDir(conf.dataDir)
let trieDB = trieDB newChainDb(conf.dataDir)
@ -133,6 +149,9 @@ when isMainModule:
## Pring Nimbus header
echo NimbusHeader
## show logs on stdout until we get the user's logging choice
discard defaultChroniclesStream.output.open(stdout)
## Processing command line arguments
if processArguments(message) != ConfigStatus.Success:
echo message

View File

@ -1,4 +1,3 @@
-d:chronicles_line_numbers
-d:"chronicles_sinks=textblocks"
--threads:on

2
vendor/nim-eth vendored

@ -1 +1 @@
Subproject commit a6be6426ab60b43a1a71c9fc96e0cba9c54154fa
Subproject commit 3db5f4c5dd47fc6a6b8624572935a813d6e3930d

1
vendor/nim-nat-traversal vendored Submodule

@ -0,0 +1 @@
Subproject commit 0bcb394f5787bde62e3c275e185498e2de20d637

1
vendor/nim-result vendored Submodule

@ -0,0 +1 @@
Subproject commit ca56ea36b8dd7f644305c383dbebd28c1e44399b