Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router doesn't accept UPNP_AddPinhole due to strict IPv6 source address verification #731

Closed
laanwj opened this issue Apr 27, 2024 · 12 comments

Comments

@laanwj
Copy link
Contributor

laanwj commented Apr 27, 2024

i'm trying to use UPNP_AddPinhole to add IPv6 pinholes. However, this fails with 606 (Action not authorized).

The source of the problem is that the LAN interface has multiple IPv6 addresses:

3: wlx...: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether ....  brd ff:ff:ff:ff:ff:ff
    inet6 2a10:..../64 scope global dynamic noprefixroute 
       valid_lft 5608sec preferred_lft 2008sec
    inet6 fdbd:.../64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::.../64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

upnpDiscover and UPNP_GetValidIGD give me an http://[fdbd:...]:5000/rootDesc.xml URL for the router.

However, i try to open a pinhole port on the 2a10:.... address, that is globally routable.

Curious thing is that the router runs miniupnpd. So i checked the miniupnpd source and the error 606 originates in PinholeVerification, which checks (as far as i understand) that the source address of the AddPinhole command is the same as the address that the pinhole is requested for. This failss the address mismatches, after all it's connecting from a fdbd:.. address.

The miniupnp API does not provide a way to set the requester address.

FWIW i've tried to hack UPNP_AddPinhole to connect using a socket that is already bind()ed to the correct IPv6 address. This appears to work as a workaround. But i feel there should be a way within the API to accomplish it.

@miniupnp
Copy link
Owner

That is probably a bug in miniupnpd that advertises itself on the local address and not the globally routable one.

Or miniupnpc that should first try globally routable address and then fallback to local address.

@miniupnp
Copy link
Owner

@laanwj

  1. can you look for the message "HTTP IPv6 address given to control points : " in miniupnpd logs ?
  2. which versions of miniupnpc and miniupnpd are you running ?

@laanwj
Copy link
Contributor Author

laanwj commented Apr 28, 2024

Thank you!

That is probably a bug in miniupnpd that advertises itself on the local address and not the globally routable one.

Could be! The first thing i tried was to hack the (client side) ssdpDiscoverDevices so that the discovery UDP packet would be sent from the right address, thinking i could maybe fool it to send the response from the right one. But this didn't do anything 😄

can you look for the message "HTTP IPv6 address given to control points : " in miniupnpd logs ?

Startup looks like this:

Apr 27 17:28:46 turris miniupnpd[3591]: HTTP listening on port 5000
Apr 27 17:28:46 turris miniupnpd[3591]: HTTP IPv6 address given to control points : [fdbd:e513:6c8d::1]
Apr 27 17:28:46 turris miniupnpd[3591]: Listening for NAT-PMP/PCP traffic on port 5351
Apr 27 17:28:55 turris miniupnpd[3591]: private/reserved address 192.168.178.X is not suitable for external IP

(The IPv4 warning is correct--it gets only a private IPv4 from DHCP, but gets two IPv6 ranges: one globally routable and one in the private ULA range, apparently)

which versions of miniupnpc and miniupnpd are you running ?

The router is running TurrisOS, which is basically a OpenWRT distribution. The miniupnpd is extrememly new.

BusyBox v1.35.0 (2024-04-02 01:04:13 UTC) built-in shell (ash)

      ______                _         ____  _____
     /_  __/_  ____________(_)____   / __ \/ ___/
      / / / / / / ___/ ___/ / ___/  / / / /\__
     / / / /_/ / /  / /  / (__  )  / /_/ /___/ /
    /_/  \__,_/_/  /_/  /_/____/   \____//____/

 -----------------------------------------------------
 TurrisOS 7.0.0, Turris Omnia
 -----------------------------------------------------
root@turris:~# miniupnpd --version
miniupnpd 2.3.3 Apr  2 2024
using netfilter(iptables) backend

On the client i am building miniupnpc statically from source (latest master). i also tried with debian testing's version, 2.2.6, no difference.

@laanwj
Copy link
Contributor Author

laanwj commented Apr 28, 2024

The scenario i'm also worried about here: what if there were multiple routable IPv6 addresses, and the goal was to create pinholes on all of them? The strict check effectively limits pinholing to the advertised IPv6 address per IGD.

That is, unless the client is changed to make the AddPinhole bind to some (maybe the intClient) address before sending the request.

@miniupnp
Copy link
Owner

The scenario i'm also worried about here: what if there were multiple routable IPv6 addresses, and the goal was to create pinholes on all of them? The strict check effectively limits pinholing to the advertised IPv6 address per IGD.

I'm afraid this scenario is not supported by the UPnP IGD standard.

@miniupnp
Copy link
Owner

@laanwj could you try with branch 731-ipv6-routable-address ?

@laanwj
Copy link
Contributor Author

laanwj commented Apr 29, 2024

I'm afraid this scenario is not supported by the UPnP IGD standard.

That's, awful. One practical example would be the Fritz!Box which gives you two routable IPv6 addresses. For one of them it refuses to open a pinhole for anyway (because it's a temporary address), but still, it's quite common for IPv6 routers to deal out many different addresses, and the only way to be sure seems to be to try to open a pinhole on all of them.

@laanwj could you try with branch 731-ipv6-routable-address ?

Sure, will try!

@miniupnp
Copy link
Owner

miniupnp commented May 8, 2024

@laanwj could you try with branch 731-ipv6-routable-address ?

Sure, will try!

So ?

About UPnP IGD, it is supposed to address Internet <=> LAN issues. So it should use the public internet address.
fc00::/7 addresses are routable "internally", but are not supposed to be public.

@miniupnp
Copy link
Owner

@laanwj have you been able to test ?

@laanwj
Copy link
Contributor Author

laanwj commented May 28, 2024

Sorry! i've been distracted by PCP implementation issues and other things. Will get back to this, this week. Have to figure out how to actually build software myself for the router.

@laanwj
Copy link
Contributor Author

laanwj commented May 28, 2024

Looks like it works! With that patch:

May 28 15:18:37 turris miniupnpd[20668]: HTTP listening on port 5000
May 28 15:18:37 turris miniupnpd[20668]: HTTP IPv6 address given to control points : [2a10:XXXX:XXXX:fc::1]
May 28 15:18:37 turris miniupnpd[20668]: Listening for NAT-PMP/PCP traffic on port 5351
  http://[2a10:XXXX:XXXX:fc::1]:5000/rootDesc.xml
URL: http://[2a10:XXXX:XXXX:fc::1]:5000/ctl/IP6FCtl
UPnP: AddPinhole successful

@miniupnp
Copy link
Owner

it looks great ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants