Protocol Overview¶
erlang-nat supports multiple NAT traversal protocols to ensure maximum compatibility with different router implementations.
Protocol Comparison¶
| Feature | UPnP IGD v1 | UPnP IGD v2 | NAT-PMP | PCP |
|---|---|---|---|---|
| RFC | - | - | RFC 6886 | RFC 6887 |
| Transport | HTTP/SOAP | HTTP/SOAP | UDP | UDP |
| Port | 1900 (SSDP) | 1900 (SSDP) | 5351 | 5351 |
| IPv6 | No | No | No | Yes |
| Dynamic Port Alloc | Limited | Yes | Yes | Yes |
| Lease Duration | Yes | Yes | Yes | Yes |
| Router Support | Wide | Growing | Apple/Some | Modern |
Discovery Priority¶
When nat:discover/0 is called, protocols are tried in parallel. The first successful response wins:
discover()
|
+-------+-------+-------+-------+
| | | | |
UPnP v2 UPnP v1 NAT-PMP PCP
| | | |
+-------+-------+-------+
|
First Success
|
Store Context
Protocol Selection¶
The discovered protocol is automatically selected based on what the NAT device supports. You don't need to choose a specific protocol.
However, if you need to use a specific protocol, you can use the protocol modules directly:
%% Use NAT-PMP specifically
case natpmp:discover() of
{ok, Gateway} ->
natpmp:add_port_mapping(Gateway, tcp, 8080, 8080);
{error, _} ->
%% NAT-PMP not available
error
end.
Protocol Modules¶
Each protocol has its own module with a consistent interface:
| Module | Protocol | Description |
|---|---|---|
natupnp_v1 |
UPnP IGD v1 | Universal Plug and Play (legacy) |
natupnp_v2 |
UPnP IGD v2 | Universal Plug and Play (modern) |
natpmp |
NAT-PMP | NAT Port Mapping Protocol |
natpcp |
PCP | Port Control Protocol |
Common Interface¶
All protocol modules implement these functions:
%% Discovery
-spec discover() -> {ok, Context} | {error, term()}.
%% Address retrieval
-spec get_external_address(Context) -> {ok, string()} | {error, term()}.
-spec get_device_address(Context) -> {ok, string()} | {error, term()}.
-spec get_internal_address(Context) -> {ok, string()}.
%% Port mapping
-spec add_port_mapping(Context, Protocol, InternalPort, ExternalPort) -> Result.
-spec add_port_mapping(Context, Protocol, InternalPort, ExternalPort, Lifetime) -> Result.
-spec delete_port_mapping(Context, Protocol, InternalPort, ExternalPort) -> ok | {error, term()}.
Router Compatibility¶
High Compatibility (UPnP)¶
Most consumer routers support UPnP IGD:
- Linksys/Cisco
- Netgear
- ASUS
- TP-Link
- D-Link
- Most ISP-provided routers
Apple Devices (NAT-PMP)¶
Apple routers and AirPort devices use NAT-PMP:
- AirPort Express
- AirPort Extreme
- Time Capsule
Modern Routers (PCP)¶
Newer routers may support PCP, especially those with IPv6 support:
- Carrier-grade NAT (CGNAT)
- Enterprise routers
- Some modern consumer routers
Troubleshooting¶
No NAT Discovered¶
- UPnP Disabled: Check router settings to enable UPnP
- Firewall: Ensure SSDP (UDP 1900) and HTTP are not blocked
- Multiple NATs: Double-NAT scenarios may not work
- Direct Connection: You may not be behind NAT
Port Mapping Fails¶
- Port Restricted: Some routers block privileged ports (<1024)
- Port in Use: Another mapping may exist for that port
- Quota Exceeded: Router may limit number of mappings
- Protocol Disabled: Specific protocol may be disabled on router
IP Address Changes¶
External IP may change due to:
- DHCP Renewal: ISP assigned new IP
- Router Reboot: NAT device restarted
- CGNAT: Carrier-grade NAT reassignment
Use the event system to detect IP changes.