PCP (natutils v0.1.0)
Port Control Protocol v2 Client (PCPv2, rfc6887) implementation to control routers NAT port mapping
The code has been tested on my Fritzbox, on my network, on my planet..
It would be interesting to build a bit of stats around this. Feel free to report about supporting routers.
Summary
Functions
Open a port map in the router Network Address Translation (NAT) table
Types
short_integer()
@type short_integer() :: 0..65535
Functions
open_port_map(inner_port, outer_mapped_port, router_ip_addr \\ Utils.router_ip_addr(), wan_ip_addr \\ Utils.public_ip_addr())
@spec open_port_map( inner_port :: short_integer(), outer_mapped_port :: short_integer(), router_ip_addr :: :inet.ip4_address(), wan_ip_addr :: :inet.ip4_address() ) :: {:ok, {external_assigned_address :: :inet.ip4_address(), external_assigned_port :: short_integer(), lifetime :: integer()}} | {:error, :not_authorized_or_refused}
Open a port map in the router Network Address Translation (NAT) table:
{local address, inner_port} <-> {wan_ip_addr, outer_mapped_port}
The function sends a PCP MAP
IANA OpCode message to the router to open an external port and map it into an internal local
port and local address.
Local address is inferred from local router address (it's assumed to be in the same network).
Router address is inferred from the default route or can be explicitly provided.
WAN address is inferred from a STUN message exchanged with Google, or it can be explicitly provided.
The Function returns the assigned external IP address and port and the lifetime of the mapping in seconds.
Example:
iex> PCP.open_port_map(5555,5555)
{:ok, {{200,1,2,3}, 5555, 120}}
Note: The assigned external port and IP can differ from the ones specified in the request, for example in the case where the external port is already assigned to another ongoing communication. Make sure to always inspect the result to know which port has been assigned to you.