UPNP NAT and Port Forwarding detection

Since version 3.2.7, TomP2P supports port forwarding detection and port forwarding settings via UPNP and NAT-PMP. Such a port forwarding is important if peers are behind NAT to be reachable. If a peer is behind a NAT without port forwarding, the peer cannot participate in the P2P network.

Port Forwarding Detection

TomP2P can detect if there is already an existing port forwarding rule in place. First the peer behind the NAT needs to conact a well-known peer (typically the bootstrap peer). This peer reports back how the peer is seen behind the NAT. With this information the peer behind the NAT can guess how the port forwarding rule might look like. It is a guess, since the peer assumes that the internal and external port is the same. In cases where internal and external ports is not the same, there is the option to set the external port manually.

Automatic Port Forwarding Setting

With UPNP and NAT-PMP, TomP2P can set the port forwarding rules on the router automatically. This happens during the port forwarding detection. As soon as TomP2P knows how other peers see a peer, and the peer detects that it is behind a NAT, it tries to set the port forwarding. The configuration in TomP2P for the port forwarding allows to enable or disable it with P2PConfiguration.setBehindFirewall(). Since the default behavior to announced the external IP changed in 3.2.7, a peer needs to discover its external IP address before it can participate (boostrap) in the network:

Peer peer = new PeerMaker(new Number160(rnd)).setPorts(4001).setBindings(b).makeAndListen();
PeerAddress pa = new PeerAddress(Number160.ZERO, {boostrap IP}, 4000, 4000);
peer.getP2PConfiguration().setBehindFirewall(true);
//find out how the other peers see me
FutureDiscover fd = peer.discover().setPeerAddress(pa).start();
fd.awaitUninterruptibly();
if (fd.isSuccess()) {
	System.out.println("found that my outside address is "+ fd.getPeerAddress());
} else {
	System.out.println("failed " + fd.getFailedReason());
}
peer.boostrap().start();