net-natpmp

This is a NAT-PMP client implementation in ruby which allows to interact with routers that support this feature.

If follows closely the specifications described in RFC 6886.

Usage

require 'net/natpmp'

# First we need to create a client instance
# For now, the gateway needs to be specified manually.
client = Net::NATPMP.client(gw: '10.2.0.1')

Specifying the gateway manually is a deliberate choice as it's mainly used to set a port mapping on a router/firewall which is not part of the local network but rather a VPN which allows port forwarding through NAT-PMP. ie. ProtonVPN, PIA, NordVPN, you know the deal.

Pulling the local gateway might be a feature added later.

# Query the remote gateway for it's external address
client.external_address
=> External address: 1.2.3.4

# Get the address as a string
client.external_address.to_s
=> "1.2.3.4"

# Let's set up a port mapping
# These arguments are the defaults. proto can be :udp or :tcp
client.map_port(proto: :udp, inside_port: 0, outside_port: 0, lifetime: 7200)
=> Port mapping: 37351 -> udp:37351 (lifetime: 60)
# The lifetime in the response is received by the remote gateway
# In this case, the gateway only allows for 60 second maps
mapping = _
=> Port mapping: 37351 -> udp:37351 (lifetime: 60)
mapping.inside_port
=> 37351
mapping.outside_port
=> 37351
mapping.proto
=> :udp
mapping.lifetime
=> 60

We can also destroy a mapping forcefully without waiting for it to expire

# The protocol and port argument must match the mapping protocol
# and internal port requested initially
client.destroy_mapping(proto: :udp, port: 37351)
=> Port mapping: 0 -> udp:37351 (lifetime: 0)

TODO

The protocol is extremely simple with only 2 actual querries but it would be useful to implement the following:

  • Use the local default gateway of the host running the application if the gateway is not specified when creating the Net::NATPMP client