PCP ipv4 port forwarding on CGNAT/dslite VDSL

Hello OpenWRT Community,

I recently switched from a Fritzbox 7590 AX to an Zyxel T56 with Openwrt and I am really happy with it. Learning Openwrt is a long process, but it is really rewarding.

Something I am currently stuck on, is port forwarding on my shared ipv4 address.
My vdsl provider is allowing port forwardings on the shared IPv4 (dslite) address via PCP. It is never the port you request, but they assign you a random port that is free.
With the Fritzbox I can confirm that PCP works and I get a random port on the public IPv4 address opened. ("Could not open port 443, opened port XXXX instead")

I tried to recreate this in OpenWRT with miniupnd. But it is not yet fully working.
This is the config and the logs:

Logs (The XX are my correct, real, shared IPv4)


Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: system uptime is 93445 seconds
Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: mnl_socket bound, port_id=14304
Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: Reloading rules from lease file
Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: version 2.3.7 starting NAT-PMP/PCP UPnP-IGD ext if ds-dsl_6_4 BOOTID=1739646785
Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: specific IPv6 ext if pppoe-dsl
Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: STUN: Performing with host=stun.l.google.com and port=19302 ...
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: resolve_stun_host: stun.l.google.com:19302 => 74.125.250.129:19302
Sat Feb 15 20:13:05 2025 daemon.info miniupnpd[14304]: perform_stun: local ports 39280 41548 37133 35758
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: waiting 3 secs and 0 usecs
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: received responses: 1
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: waiting 3 secs and 0 usecs
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: received responses: 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: waiting 3 secs and 0 usecs
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: received responses: 3
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: waiting 3 secs and 0 usecs
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: wait_for_stun_responses: received responses: 4
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5280, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5470, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c566c, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5868, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5280, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5470, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c566c, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5280, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5470, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: table_cb(0x7fea1c5280, 0x7fea1c6280) fw4 upnp_forward 2
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: XOR-MAPPED-ADDRESS XX.XXX.XX.XXX:16892
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: XOR-MAPPED-ADDRESS XX.XXX.XX.XXX:16893
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: XOR-MAPPED-ADDRESS XX.XXX.XX.XXX:16894
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sat Feb 15 20:13:05 2025 daemon.debug miniupnpd[14304]: parse_stun_response: XOR-MAPPED-ADDRESS XX.XXX.XX.XXX:16895
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: perform_stun: #0 external address or port changed
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: perform_stun: #1 external address or port changed
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: perform_stun: #2 external address or port changed
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: perform_stun: #3 external address or port changed
Sat Feb 15 20:13:05 2025 daemon.warn miniupnpd[14304]: STUN: ext interface ds-dsl_6_4 with private IP address 192.0.0.2 is now behind restrictive or symmetric NAT with public IP address XX.XXX.XX.XXX which does not support port forwarding
Sat Feb 15 20:13:05 2025 daemon.warn miniupnpd[14304]: NAT on upstream router blocks incoming connections set by miniupnpd
Sat Feb 15 20:13:05 2025 daemon.warn miniupnpd[14304]: Turn off NAT on upstream router or change it to full-cone NAT 1:1 type
Sat Feb 15 20:13:05 2025 daemon.warn miniupnpd[14304]: Port forwarding is now disabled
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: HTTP listening on port 5000
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: HTTP IPv6 address given to control points : [YYYY:YYY:YYYY:YYY::1]
Sat Feb 15 20:13:05 2025 daemon.notice miniupnpd[14304]: Listening for NAT-PMP/PCP traffic on port 5351

Config:

config upnpd 'config'
	option enabled '1'
	option internal_iface 'lan'
	option upnp_lease_file '/var/run/miniupnpd.leases'
	option use_stun '1'
	option stun_host 'stun.l.google.com'
	option stun_port '19302'
	option uuid '345afaaa-b937-48cc-9e08-b157XXX
	option igdv1 '1'
	option log_output '1'

config perm_rule
	option comment 'Test'
	option int_addr '192.168.1.1'
	option int_ports '1-65535'
	option ext_ports '1-65535'
	option action 'allow'


similiar topics:

1 Like

Set one of front IPs as default, at least upnp will start and 1/n connections will succeed.
REF: https://github.com/miniupnp/miniupnp/issues/705#issuecomment-2429247837

With STUN enabled I get these lines. 83.136.14.146 is my (changed) public IPv4.
Are the Ports 20545-20548 the ports that are available to me? (They change everytime I restart upnp)

Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: XOR-MAPPED-ADDRESS 83.136.14.146:20545
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: XOR-MAPPED-ADDRESS 83.136.14.146:20546
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: XOR-MAPPED-ADDRESS 83.136.14.146:20547
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: Type 0x0101, Length 12, Magic Cookie 2112a442
Sun Feb 16 08:56:38 2025 daemon.debug miniupnpd[31863]: parse_stun_response: XOR-MAPPED-ADDRESS 83.136.14.146:20548

With STUN disabled and external_ip hardcoded, I geta much shorter log:

Sun Feb 16 09:05:24 2025 daemon.info miniupnpd[2661]: system uptime is 139783 seconds
Sun Feb 16 09:05:24 2025 daemon.info miniupnpd[2661]: mnl_socket bound, port_id=2661
Sun Feb 16 09:05:24 2025 daemon.info miniupnpd[2661]: Reloading rules from lease file
Sun Feb 16 09:05:24 2025 daemon.info miniupnpd[2661]: version 2.3.7 starting NAT-PMP/PCP UPnP-IGD ext if ds-dsl_6_4 BOOTID=1739693124
Sun Feb 16 09:05:24 2025 daemon.info miniupnpd[2661]: specific IPv6 ext if pppoe-dsl
Sun Feb 16 09:05:24 2025 daemon.notice miniupnpd[2661]: HTTP listening on port 5000
Sun Feb 16 09:05:24 2025 daemon.notice miniupnpd[2661]: HTTP IPv6 address given to control points : [2001:9e8:f758:6300::1]
Sun Feb 16 09:05:24 2025 daemon.notice miniupnpd[2661]: Listening for NAT-PMP/PCP traffic on port 5351

How can I "ask" the PCP server which ports I can use?

Call your provider, read them requirements from https://www.rfc-editor.org/rfc/rfc6888 and ask what goes wrong.

I was able to successfully open ports on my public shared IPv4 with the following library.

I will try to crosscompile it for openwrt.
exmaple command:

./pcp -d -s 192.0.0.1 -i :2564 -e 88.135.14.123 -3 192.0.0.2

Most likely then it should also work with miniupnp somehow, but I did not get it working, yet.

Are you sure that miniupnpd even supports opening ports via PCP on an upstream router? Because this open issue suggests it does not: https://github.com/miniupnp/miniupnp/issues/299

Assuming your provider is 1&1 (as far as I know it is the only one in Germany doing this DS-Lite + PCP thing), you could probably make your life much easier by asking them to provide a dual stack connection for you.

You might be right, I just saw that natpmp/pcp is an option to enable/disable in openwrt. But maybe this is only for the server and not the client.

My provider maxxim is part of the drillisch/1und1 group and therefore should be technically identical. But I asked the provider multiple time if dual stack is possible (even for money) and they declined each time.

Getting libpcp/pcp cross compiled as package sounds like a good exercise. Then I would just need a crontab to renew the mapping every hour or so.

miniupnp is not pcp client, but if you manage to teach it new tricks check with upstream.

I guess the "for money" option in this case would be to switch to 1&1 directly. But if the PCP client works and is sufficient for your use case, it seems like getting that packaged is the more sensible choice.

pcp should support two modes according the pr Add PCP support by libpcp · Pull Request #41 · miniupnp/miniupnp

PCP in miniupnpd It's not enabled in openwrt default build
I've faced same ds-lite problem using Orange ISP here in Poland .But Orange allow me to use two pppoe sessions one ipv4 (public) only. And one ipv6 only (login name with /ipv6 suffix). ipv6 session is the same as for ds-lite but without ds-lite package installed.
One thing to make it work was add 60s delay to /lib/netifd/ppp6-up.
Maybe this will work for your ISP.