The Port Mapper project is a Java library that allows you to forward ports on NAT-enabled routers. Originally developed as part of the Peernetic project, Port Mapper has several distinct advantages over existing Java libraries that provide port forwarding functionality.
Port Mapper requires Java7 or later. In your Maven POM, add "portmapper" as a dependency.
<dependency>
<groupId>com.offbynull.portmapper</groupId>
<artifactId>portmapper</artifactId>
<version>2.0.6</version>
</dependency>
The following example attempts to forward some external port (55555 preferred) to internal port 12345 on the first port forwarding device it finds.
// Start gateways
Gateway network = NetworkGateway.create();
Gateway process = ProcessGateway.create();
Bus networkBus = network.getBus();
Bus processBus = process.getBus();
// Discover port forwarding devices and take the first one found
List<PortMapper> mappers = PortMapperFactory.discover(networkBus, processBus);
PortMapper mapper = mappers.get(0);
// Map internal port 12345 to some external port (55555 preferred)
//
// IMPORTANT NOTE: Many devices prevent you from mapping ports that are <= 1024
// (both internal and external ports). Be mindful of this when choosing which
// ports you want to map.
MappedPort mappedPort = mapper.mapPort(PortType.TCP, 12345, 55555, 60);
System.out.println("Port mapping added: " + mappedPort);
// Refresh mapping half-way through the lifetime of the mapping (for example,
// if the mapping is available for 40 seconds, refresh it every 20 seconds)
while(!shutdown) {
mappedPort = mapper.refreshPort(mappedPort, mappedPort.getLifetime());
System.out.println("Port mapping refreshed: " + mappedPort);
Thread.sleep(mappedPort.getLifetime() / 2L * 1000L);
}
// Unmap port 12345
mapper.unmapPort(mappedPort);
// Stop gateways
networkBus.send(new KillNetworkRequest());
processBus.send(new KillProcessRequest()); // can kill this after discovery
You can use the identify method on PortMapper implementations directly.
List<UpnpIgdPortMapper> upnpIgdMappers = UpnpIgdPortMapper.identify(networkBus);
List<NatPmpPortMapper> natPmpMappers = NatPmpPortMapper.identify(networkBus, processBus, additionalIps);
List<PcpPortMapper> pcpMappers = PcpPortMapper.identify(networkBus, processBus, additionalIps);
Several reasons. The Port Mapper project
Because of this, the code should be easily portable to other languages -- especially languages that don't have the same robust ecosystem that Java does.
The Port Mapper project aims to be resilient when it comes to faulty responses, especially when using UPnP-IGD. The code
Unfortunately, Java doesn't provide a built-in way to grab gateway addresses from the OS, nor does it allow you to do ICMP probing to find devices on path (e.g. set TTL to 1 and ping, the first device is very likely the gateway). As such, the Port Mapper project makes use of various OS-specific commands to find gateway addresses. You can find out which commands are used by looking through the source code.
Not at this time. Support may be added in the future.
Not at this time. Version 1 did support unsolicited PCP ANNOUNCEs, but it has since been removed because no devices seem to support it. If you're worried about not being notified of lost mappings, just make sure you refresh more often so that you catch the problem early (e.g. every 5 or 10 minutes).
Alternatives to Port Mapper include:
If you know of any other projects please let me know and I'll update this section.
Template adapted from http://keepachangelog.com/
All notable changes to this project will be documented in this file. This project adheres to Semantic Versioning.