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

Types

Link to this type

short_integer()

@type short_integer() :: 0..65535

Functions

Link to this function

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.