status-im / nimbus-eth2

Nim implementation of the Ethereum Beacon Chain
https://nimbus.guide
Other
517 stars 222 forks source link

Improve external ip / nat configuration #2160

Open kdeme opened 3 years ago

kdeme commented 3 years ago

Current default is to use upnp / nat pmp to discover external ip and to configure the port forwarding ( =mapping). This is not useful for systems not behind NAT as thus not a great default for those configurations. Additionally, we might no want to recommend upnp first option either for those behind NAT?

Discoveryv5 can help figuring out the external IP when https://github.com/status-im/nim-eth/issues/207 gets implemented. When the user is behind NAT, it would still require for manual port mapping or to be used in combination with upnp/natpmp

Regarding the --nat option:

Default could still be any option.

Defaults:

Other clients:

kdeme commented 3 years ago

To make clear, in the current code with current options, the only real viable options are:

Systems not behind NAT:

Systems behind NAT:

Thinking about it further, the any option (defaulted), should basically allow for any of the two cases to work automatically. However, not guaranteed of course and issues may arise. It would be more important to have proper INF and WRN logs for this and educate the users into these message (in the book). This would mean still using the upnp/pmp solution default & also discv5 solution. Basically what LH is doing. (And perhaps we can also implement the none solution from above as backup).

unixpi commented 3 years ago

Thinking about it further, the any option (defaulted), should basically allow for any of the two cases to work automatically. However, not guaranteed of course and issues may arise. It would be more important to have proper INF and WRN logs for this and educate the users into these message (in the book). This would mean still using the upnp/pmp solution default & also discv5 solution. Basically what LH is doing.

As discussed offline, I think this is the cleanest approach.

cheatfate commented 3 years ago

I think before starting NAT mechanism we should check our interfaces and routing table using chronos utilities. This will allow us to detect situation when we already have public IP address and we do not need to start NAT mechanism.

https://github.com/status-im/nim-chronos/blob/master/tests/testnet.nim#L477-L482

Using getBestRoute with some globally available IP address will reveal you interface's address which will be used to connect to this IP address. If this IP address is globally routable you can use it as "extip".

The only problem is that currently chronos is missing primitive to check if specific IP is actually global routable IP address.

kdeme commented 3 years ago

Using getBestRoute with some globally available IP address will reveal you interface's address which will be used to connect to this IP address. If this IP address is globally routable you can use it as "extip".

Great, this is what I meant with:

* the routable interface could be searched for and its IP could be used, but this would not be necessary.

I wasn't aware that there was a getBestRoute call available in chronos already. It does seems to require sending an actual message, is that correct? Is there a version that just checks routable interface?

cheatfate commented 3 years ago

@kdeme this call do not send any messages, it just query OS for the BEST route. Because there could be many routable interfaces actually...

kdeme commented 3 years ago

The bulk of this feature is being implemented here: https://github.com/status-im/nim-eth/pull/323

The current (new) logic is as follows:

Additionally, external IP discovery should be added in discv5 protocol (and allowed to be disabled). This will help with dynamic IP that get changed and also in the case that external IP can not be found correctly (e.g. Container / VM usages or cases where the best route IP findings would go wrong?).

Now, some questions:

  1. The current --nat:... options stem from geth. Are these clear enough for the user? I think they are not very self explanatory and it might be rather difficult to understand what to use here. On the other hand, the default is any and that should be fine for the typical user. But we could decide to change to more individual based options however too, e.g. with the same default results (and keep the current options also available for a certain period for backwards compatibility)
  2. Currently port mapping is always 1:1. Should we also support a different port mapping on host device <-> external ports. (Perhaps this can be useful for certain Docker/VM setups? LH supports this from what I can see in the options)

Some different use cases:

I'm leaving out IPv6 cases for now.

chfast commented 10 months ago

From my experience PMP works better than UPNP because PMP can give you other external port in case the requested one is already taken. But seems nimbus is trying UPNP first and errors out without fallback to PMP.