-
Notifications
You must be signed in to change notification settings - Fork 20.8k
p2p/nat: remove forceful port mapping in upnp #30265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Running Let's see what @fjl thinks. |
I just thought it could cause some problems if it deletes port mappings used by other users(processes) using the same upnp. Not sure about the full issue #1024 but the internal ip changing case is probably covered by |
Basically, the resources of NAT are not sufficient. Therefore, related protocols recommend minimizing the usage of NAT resources. I think it would be better to remove unused ports. |
I agree it would be better to remove unused ports. Still, I think deleting maybe-in-use port mappings is a much bigger problem. I'll add the code to delete ports that were abandoned by geth. |
Regarding the discussion on delete, it is not needed according to spec. Neither in UPnP IGDv1, nor in v2, nor in NAT-PMP. Implementations are notoriously buggy, so we might keep it as a workaround, but I would not use it as part of the base renewal mechanism, especially if we would risk side-effects. Also, we do set a lifetime (10 minutes, which is well below the recommended 1-2 hours), so delete should happen even without an explicit call if we shutdown abruptly, while we could easily call it in normal shutdown (I didn't yet check if it is happening). But even if it was not deleted, the new request should count as an overwrite. There are some corner cases. I will check what's handled and what's not:
We should also anticipate the renewal. Currently we are doing it with the same time as the lifetime, which can result in some service outage. Here are the relevant specs: SpecUPnP Internet Gateway Device v1 (IGD:1)https://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf UPnP Internet Gateway Device v2 (IGD:2).https://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v2-Service.pdf PMP spechttps://www.rfc-editor.org/rfc/rfc6886.txt PCP (PMP next version) spechttps://www.rfc-editor.org/rfc/rfc6887.txt RenawalAnd here are the relevant parts about renewal (called overwrite in UPnP) UPnP IGD v1
UPnP IGD v2
PMP
|
With UPnP IGD v2 it was random only if specified was unavailable. With UPnP IGD v1 it was disregarding the external port. Signed-off-by: Csaba Kiraly <[email protected]>
The default of addAnyPortMapping is what addPortMapping does, so no need to call it separately. Signed-off-by: Csaba Kiraly <[email protected]>
Signed-off-by: Csaba Kiraly <[email protected]>
c5a1ba7
to
ca79cd0
Compare
Was logging 0 instead of original port. Signed-off-by: Csaba Kiraly <[email protected]>
Make UPnP more robust - Once a random port was mapped, we try to stick to it even if a UPnP refresh fails. Previously we were immediately moving back to try the default port, leading to frequent ENR changes. - We were deleting port mappings before refresh as a possible workaround. This created issues in some UPnP servers. The UPnP (and PMP) specification is explicit about the refresh requirements, and delete is clearly not needed (see #30265 (comment)). From now on we only delete when closing. - We were trying to add port mappings only once, and then moved on to random ports. Now we insist a bit more, so that a simple failed request won't lead to ENR changes. Fixes #31418 --------- Signed-off-by: Csaba Kiraly <[email protected]> Co-authored-by: Felix Lange <[email protected]>
Here we are modifying the port mapping logic so that existing port mappings will only be removed when they were previously created by geth. The AddAnyPortMapping functionality has been adapted to work consistently between the IGDv1 and IGDv2 backends.
Make UPnP more robust - Once a random port was mapped, we try to stick to it even if a UPnP refresh fails. Previously we were immediately moving back to try the default port, leading to frequent ENR changes. - We were deleting port mappings before refresh as a possible workaround. This created issues in some UPnP servers. The UPnP (and PMP) specification is explicit about the refresh requirements, and delete is clearly not needed (see ethereum#30265 (comment)). From now on we only delete when closing. - We were trying to add port mappings only once, and then moved on to random ports. Now we insist a bit more, so that a simple failed request won't lead to ENR changes. Fixes ethereum#31418 --------- Signed-off-by: Csaba Kiraly <[email protected]> Co-authored-by: Felix Lange <[email protected]>
Since
addAnyPortMapping
is implemented, we don't needDeleteMapping
to remove an existing port mapping and make a forceful port mapping (which somewhat goes against the concept of upnp).Also there is some chance
n.randomPort()
inaddAnyPortMapping
returns an occupied port, so it's safer to try it couple of times. Three looks like enough according to libp2p.Edit: Fixed so it would only delete port mapping only if the external port was originally used by geth.