Kubo is using UPnP instead of manually configured port forward

In my home network’s modem settings I gave my node’s computer a reserved LAN IPv4 and forwarded port 4001 for TCP and UDP (the settings didn’t differentiate between the forwarded port number and the port being forwarded to). However, ipfs id lists the external IPv4 with a random port that changes each daemon startup for both TCP and UDP. I’m assuming that is the effect of UPnP. Inconsistently it will also list the correct forwarded address except for TCP only.

Later I’ll link to a thread where someone suggested that the double port forwarding is problematic but didn’t explain how to fix it. Will disabling UPnP in the config file fix this without messing up something else?

What I’m trying to accomplish is give my node a permanent (as can be w/o dynamic DNS) multi address to use for bootstrapping. It occurred to me that 4001 port forward might work even if Kubo doesn’t know it’s working since it’s being forwarded to a correct address. I could also use an IPv6 address, but I don’t know how v6 assignment works or how often it will change.

Hmmm, a lot to unpack:

First, anyone who knows anything about security will tell you, never enable UPnP on your router, it’s a security disaster.

Second, yes, if you have set up port forwarding, go ahead and set DisableNatPortMap to true (I certainly have).

Third, with IPv6, modern stacks will give you two separate addresses (1 that never changes, and 1 that changes regularly that you use to call out. read about SLAAC for details). When listing your addresses, they are marked as secured (the permanent one) and temporary (the one that changes all the time). Since you are receiving calls, you must use the permanent one.

Now, you need to set up your swarm in the config. Make sure to include localhost for both IPv4 and IPv6, then the local IPv4 address and the public-permanent IPv6 address. For IPv4, make sure the ports are the same on both ends of the port-mapping.

Here is what mine looks like (I modified my IPv6 for privacy):

"Swarm": [

Now, aside from port-forwarding for IPv4, you also need to poke a hole in your firewall for IPv6.

1 Like

I think I know a lot about security and I disagree.
UPNP let malware open ports true, however if you don’t have an extremly severe firewall and proxy setup a malware can just connect to a 2C server, do hole punching, … to achieve the same effect.
And you most probably don’t have this setup at home.


Thanks, this clears a lot of things up but I still have questions.

Can you elaborate on that? I’m assuming you are referring to Address.Swarm rather than Swarm. The default values are 0:4001 for each combination of TCP and UDP. I’m guessing in this context it means TCP/UDP on port 4001 of all addresses it can listen on. However you overrode that so it means you are quite confident those are all the IP addresses your node will ever need.

If I understand SLAAC correctly, it will change if I connect to another LAN, my modems own IPv6 address does not get renewed, or a collision is detected (which probably won’t happen by chance, but in theory could happen by malice or error). It will not change merely by me switching between wifi and ethernet. It sounds like if I manually specify the IPv6 in Address.Swarm, I will by going from “The publicly reachable IPv6 address will likely change, but either way it will have an IPv6 address,” to “The publicly reachable IPv6 address probably won’t change and it probably will have an IPv6 address,” which is not a sacrifice I want to make.

My Kubo node knows it has the two publicly reachable IPv6 addresses (I’m assuming the long one is the SLAACP but shouldn’t it have an ff:fe somewhere in there?), but it only shows on ipfs id the one assigned by DHCPv6. From what I read this could be for privacy reasons, and I guess the reason you say I should specify the SLAAC address rather than the DHCP is to force Kubo to announce the SLAAC.

As long as:

  • Kubo (or my computer in general) doesn’t need to know port forwarding is on in order for connections to be forwarded to an address it is listening on.
  • ipfs id as well as the status pane on the GUI only reflects the addresses Kubo announces to, and not every address it is listening on.
  • Kubo does not need to announce and address to receive incoming connections from peers that have the multi-address manually set up.

then I think a better solution might be to:

  • Leave Address.Swarm as is (with zeros).
  • Set DisableNatPortMap to true.
  • Set Address.AppendAnnounce to the forwarded public IPv4 address.
  • For the other Kubo node that wants to use the Kubo node in question as a bootstrap address, add (keeping current addresses intact):
"/ip4/[modems ip]/udp/4001/quic/p2p/[PeerID]", 
"/ip4/[local reserved ipv4]/udp/4001/quic/p2p/[PeerID]"

Is this right?

I guess that is something I should look into separately. Either way, Kubo’s local peer discovery should work because mDNS does not rely on UPnP, right? And as long as I have manual port forwarding on, DisableNatPortMap shouldn’t interfere with anything?

Lol, a lot to unpack again :stuck_out_tongue:

Yes, I was referring to Addresses.Swarm. The type entries mean “use all available interfaces and addresses”. In my case, I’d rather control which ones it uses instead of letting it try to use all of them.

Correct, the permanent IPv6 address that SLAAC generates is dependent on the router it connects to, so if you change networks, the address will change (in the same way your IPv4 address will change). In my case, it’s a desktop machine connected to ethernet, so it’s not going to change networks on me. On a specific network, once generated, it’s “highly unlikely” to ever change (the address space is 64 bit wide, the odds of a collision are not worth considering). Switching between wifi and ethernet won’t change it, as long as you are connecting to the same router.

DHCPv6 is deprecated in favor of SLAAC. However, if you have a DHCPv6 service running on your LAN, and you can reserve specific addresses with it, it’s perfectly fine to use. If that’s what you wish to use and made sure the IPv6 address it gives you will always be the same, then use that one instead. It’s just as reliable.

  • yes and no. If your node receives a connection request on its local IPv4 address, it really doesn’t care where it came from (local LAN, or some port forwarded address). However, your node has to announce the addresses it’s reachable through, which means it has to understand your port forwarding (which it tries to do using AutoNAT). Another way is to force a specific announce (there are several ways of doing that).
  • correct. you can also use ipfs dht findpeer
  • yes and no. probably true for Bootstrap, but I’ve seen Peering.Peers override addresses with ones it looked up on the DHT

Sounds reasonable, but the real test is to check what ipfs id returns after the node has been running for a few minutes to make sure it is exactly what you want.

1 Like

Manual portforwarding isn’t enough, you need to tell other nodes what is your public ip and port, you can do this with the Swarm.AppendAnnounces field.


After testing, it seems my node was not addressable from what I think was the SLAAC address, but was addressable from the forwarded IP4. I tested this by removing the bootstraps from my other computer and used cellular tethering.

Did you add a rule to your firewall to let IPv6 traffic through to TCP/UDP 4001 at that IPv6 address? If not, that’s why it’s not reachable. Also, your cellular provider might just not support IPv6.

On my router? I have my IPv6 firewall on “minimal” preset which according to documentation allows p2p. It gives me a “custom” option as well, but when I select it it doesn’t actually let me customize anything.

On my PC? I don’t know if it even has a firewall.

I meant on the router. It’s highly possible the router’s firewall is blocking incoming calls on IPv6. An easy way to test it is to try and open a TCP connection from outside your network to that address. Like this:

> nc -6 2001:470:x:xxx:xxxx:xxxx:xxxx:xxxx 4001

As you can see, the node responds with /multistream/1.0.0, which tells you everything is working correctly.

1 Like

It took me a while but I have everything figured out.


You were right that the router was blocking all incoming IPv6 calls. I opened the admin interface a different way and it gave me just enough manual control over the firewall. Once I fixed that I connected over IPv6 easily. Before I did that I somehow turned stateful configuration off for the computer on the routers side which caused Kubo to advertise its SLAAC instead. I tried testing the IPv6 local link address which succeeded with nc but apparently the % isn’t compatible with MultiAddress, which might be worth addressing.


UPnP was the cause of the random forwarded ports. Each time Kubo launched, it reserved a new port, but it didn’t remove the old ones. After I disabled UPnP in the config file, seemingly random ports were still advertised, but this time the tcp and udp were usually different. All the ports previously reserved were still being forwarded. Only once I restarted the computer and the modem did it consistently advertise 4001.

Thanks for the help!

The IPv6 address with a % in it isn’t one of the SLAAC addresses, it’s the link local address and shouldn’t be used for anything (it’s used by your computer to discover and initially talk to your router to establish the SLAAC and DHCPv6 addresses, and is then never used again).

lemme give you an example from my computer:

> ifconfig en0
	ether 38:f9:d3:10:6f:49 
	inet6 fe80::855:8825:ab02:b395%en0 prefixlen 64 secured scopeid 0x4 
	inet6 2001:470:x:xxx:xxxx:xxxx:xxxx:xxxx prefixlen 64 autoconf secured 
	inet6 2001:470:x:xxx:yyyy:yyyy:yyyy:yyyy prefixlen 64 autoconf temporary 
	inet6 2001:470:x:xxx::zzzz prefixlen 64 dynamic 
	inet netmask 0xffffff00 broadcast
	nd6 options=201<PERFORMNUD,DAD>
	media: autoselect (1000baseT <full-duplex>)
	status: active

The “fe80” address is the link local, don’t use it for anything.
The address with all the Xs is the permanent (secured) SLAAC address.
The address with all the Ys is the temporary SLAAC address used to call out.
The address that ends in Zs is the DHCPv6 address the router assigned.

On my node, I use the address with all the Xs.

I’m glad everything is working now :slight_smile:

1 Like