yimingliu / py-natpmp

a NAT-PMP library for Python
http://blog.yimingliu.com/2008/01/07/nat-pmp-client-library-for-python
Other
47 stars 19 forks source link

Wrong Public Port, Always Random #12

Open quantum77 opened 1 year ago

quantum77 commented 1 year ago

# python /home/bill/bin/natpmp_client.py -g 10.2.0.1 -u -l 60 56666 56666 PortMapResponse: version 0, opcode 129 (129), result 0, ssec 487075, private_port 56666, public port 35908, lifetime 60

Asked Yiming about this and he said something's wrong with my NAT. I don't know what to do with that. It's exactly the same problem as natpmpc has.

Also I -must- specify the gateway or else this script defaults to the LAN gateway rather than the WireGuard one. I don't understand how this can happen when the routing table is proper. The WG tunnel works fine.

yimingliu commented 1 year ago

As I noted in our private communications, the responsibility of actually assigning the port is part of the router's software stack. NATPMP, as a protocol, only specifies what to do to make a request.

This is from the spec

While a NAT gateway MUST NOT automatically create mappings for TCP when the client requests UDP, and vice versa, the NAT gateway MUST reserve the companion port so the same client can choose to map it in the future. For example, if a client requests to map TCP port 80, as long as the client maintains the lease for that TCP port mapping, another client with a different internal IP address MUST NOT be able to successfully acquire the mapping for UDP port 80.
The client normally requests the external port matching the internal port. If that external port is not available, the NAT gateway MUST return an available external port if possible, or return an error code if no external ports are available.

The fact your router returns a random port in response to a mapping request suggests the external port being requested is not available. The router, at that point, must return some port if any is available -- hence the randomness. Most NAT stacks will just pick any random port at that point to return.

There is little else I can offer here. This library implements the NAT-PMP protocol from the client end. The protocol does not guarantee you will get the public port you asked for, if it is already occupied in your router's NAT tables (either the TCP port or the UDP port -- since the companion is to be reserved also). The fact that natpmpc, an independent implementation of this protocol, behaves identically, suggests the issue is at the router, any static port mappings already in place, or its NAT implementation.

quantum77 commented 1 year ago

There is nothing actionable here. Maybe I should give more perspective.

I've set up a ProtonVPN to a remote endpoint. It is this tunnel that I need to NATPMP set up port-forwarding. On my side I'm using Deluge which has NAT-PMP enabled, so I should think that middleware is unnecessary. Yet it starts downloading but after 60 seconds stops. It has no "Port Issue".

My understanding at this point is that when I set the Incoming port in Deluge, it will look to that locally, which the middleware has set up. Then that middleware is connected o the random port on the other end, and it doesn't matter that that other port is different. It's NATting.

Some say you can set in the middleware both ports to '0' and Deluge will work fine, but I do not understand how that is supposed to work.

The whole idea is I need to be able to present a listening port at the VPN's endpoint, and have that translate through the tunnel to Deluge. The middleware sets up fine (with a different port on the far end) without error. Deluge starts up fine with no Port Issue and begind downloading like blazes, but after a minute stops like there's a port problem.