opnsense / opnsense/plugins

net/natpmp-client: NAT-PMP client plugin for provider assigned inbound ports

Open
#5,691 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
1.2k
Forks
863
Avg merge
2d 6h
Merged PRs (30d)
10

Description

Important notices
Before you add a new report, we ask you kindly to acknowledge the following:

Is your feature request related to a problem? Please describe.

Commercial VPN providers that offer an inbound port hand it out over NAT-PMP, and they change it
without notice — ProtonVPN grants 60 second leases. OPNsense can answer NAT-PMP requests
(os-upnp) but has no way to make one, so there is no supported way to obtain such a port or to keep
a rule pointing at it. What people do instead is a cron job around natpmpc that rewrites a rule
and reloads the filter, which races the ruleset it is editing and leaves the port forwarded to a
lease nobody renewed once the script dies.

Describe the solution you'd like

A NAT-PMP client plugin: a small daemon that requests and renews leases toward a gateway, and a
firewall hook that publishes a destination NAT rule following whatever public port the gateway
currently grants. The rules come from the plugin system rather than from config.xml, so they are
regenerated on every filter reload and are withheld the moment the daemon stops renewing.

I have written it and have been running it. Working and tested against a live ProtonVPN endpoint:
lease request, renewal and expiry; the redirect following the public port; an optional inbound pass
rule, off by default, with reply-to so replies leave through the tunnel; both rules withheld when
the daemon is not running; reached end to end from the internet.

Describe alternatives you've considered

  • os-upnp — the server side of the same protocol, not a client, and not extendable into one.
  • A shell script on cron. It works until the port changes: it cannot hand the new port to the
    ruleset without editing rules underneath a filter reload, and it has no way to take the redirect
    down when it stops running.
  • Speaking NAT-PMP from the plugin instead of driving natpmpc. Fewer moving parts, but it means
    writing protocol code where a maintained library already exists.

Additional context

Before writing more, I would rather ask whether this is wanted at all, and settle three things the
guidelines raise:

  1. The binary is in FreeBSD ports but not in the OPNsense package set. The plugin drives
    /usr/local/bin/natpmpc from net/libnatpmp (20250404). The port exists and the FreeBSD package
    installs cleanly, but PLUGIN_DEPENDS=libnatpmp fails the build because OPNsense does not build
    it. Would you consider adding it to opnsense/tools, or would you rather the plugin spoke the
    protocol itself and carried no dependency?
  2. Size. 22 files, about 2350 lines excluding licence headers — roughly 900 of Python for the
    daemon, 250 of PHP for the firewall hook, the rest MVC model, controllers, forms and the page.
    The guidelines say a large initial codebase cannot be reviewed. If this is over the line, I would
    rather hear what to cut than submit it as it stands.
  3. AI disclosure. Written and tested with Claude (Anthropic), model Opus 5. The design decisions,
    the testing on real hardware and this request are mine.

One design point worth flagging, since it is the part that opens the firewall: the inbound pass rule
is a per-mapping option and is off by default. The redirect alone changes nothing about what is
allowed in; the operator has to ask for the opening, and it is scoped to the internal host and port
rather than to the rotating public one.

Branch, as a single commit:
https://github.com/l0rdg3x/opnsense-plugins/tree/natpmp-client

Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the linked natpmp-client branch, starting with its Python daemon, PHP firewall hook, and MVC files, then check the CONTRIBUTING.md guidance. Confirm whether the libnatpmp dependency, 22-file scope, and firewall-rule behavior are acceptable; done requires maintainer agreement on those design and packaging questions.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, python
Domain
networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.