I have 3 applications: a MasterServer, a Server and a Client.
The MasterServer is running on: 70.105.155.5:15555
(port forwarded with UPnP)
I create a server and let the MasterServer know I exist. The MasterServer keeps my public ip and port. The port that the MS gets is randomly assigned by my router (lets say: 70.105.155.5:16666). The server keeps messaging the MasterServer each 10sec to keep that same port open.
I open up the client, on which it asks the MasterServer for the public ip and port of a server. The MasterServer returns: 70.105.155.5:16666. I know 100% sure that the server's public port 16666 is still open because I can check that in my logs.
But all messages sent from Client => Server
are never received. At the same time the Server is still getting messages from MasterServer through 16666.
So this is really puzzling. Am I forgetting something? Is my understanding of NAT punch flawed?
Thanks for any help!
There are multiple issues here, and it depends on the router's security configuration too, often in ways the user cannot control. The general excuse is that it's a security precaution, but really firewalling and NAT are two separate concerns. Anyway, most home users are stuck with whatever they've got. They do usually have the option to explicitly map a port, and UPnP can help you too if the router supports it.
But going back to NAT, to begin with you're likely to have a problem if your server and client are sitting behind the same NAT, which seems to be the case given the addresses you quoted above. Most NATs only rewrite incoming packets from the public interface - so packets that physically arrive on the private interface, even if they're addressed to the public IP, won't be forwarded. To support this configuration in the wild you need the devices to advertise their private addresses to the MasterServer, and detect when they want to talk to other devices behind the same NAT, and if so, use the private address rather than going through the NAT. This is flawed in many ways, especially with nested NATs, but I think it's the best you can do.
Beyond that, in the more common case where all the devices are behind different NATs, some routers will only allow incoming traffic on a forwarding port if it's from the place they originally sent the outgoing traffic to (which resulted in the port opening up in the first place). Some also require it to come from the same source port on the remote device.
The workaround is for the MasterServer to do a bit more work. The gist is that it should tell both peers to send a packet to each other; these may or may not get through, but simply sending the packet out through the Server's NAT to the Client's public IP address may be enough to get the Server's NAT to correctly forward later packets from the Client. And vice versa.
In practice it is even more complicated, because the Server's NAT may use a different port when talking to Client to what it used when talking to MasterServer. So while this may open up a port for the Client to talk back to the Server, but it might not be the one the Client is expecting to use. If the NAT behaves like this, then you need to look at how predictable its choice of port numbering is. Some just increase one by one (but bear in mind there may be other devices behind the same NAT causing the number to jump more than one step at a time). For these ones, the Client needs to spam a range of Server ports to try to figure out which one got opened up. Again the MasterServer is in the best position to coordinate this.
Others seem totally random in port allocations, and there's not much you can do with those. But it's only terminal if both ends are behind these random NATs. So long as one end is more amenable to being opened up, the random end won't matter.
Also note that some NATs use a different outgoing port for each port on the target - this also makes prediction a lot harder, even in the case that the ports are not randomly assigned. Again, so long as one end of the connection is flexible, you can tolerate these NATs but in a peer-to-peer context they will be a nightmare in the end because they just can't talk to each other.