Syncthing handles NAT correctly but not strelay


I have a device running Syncthing smoothly, meaning that the port (22000) is automatically mapped (as I can see in the router interface). And the direct connection from other devices to this one works as well (even if the second device did not map a port itself).

When I run the syncthing-relay however, it fails with

main.go:214: Timeout out waiting for NAT mapping.

Failed to join request or check error

and indeed the ports (22067 and 22070) do not appear in the router interface.

Mapping the ports manually through something like:

upnpc -e strelay1 -a “$ip” 22070 22070 TCP 3600 upnpc -e strelay2 -a “$ip” 22067 22067 TCP 3600

(upnpc is from the miniupnpc package)

makes it work as expected (AFAICT).

I would have expected both syncthing and strelay to succeed and fail the same, however it seems that the logic to map the ports is different. Is that the case? Shouldn’t they behave the same?

Note that due to my hackish network configuration (I use a second router as a relay between my device and the main router where the mapping has to occur), upnpc still returns an error at the end and fails to check that the mapping is indeed there:

GetSpecificPortMappingEntry() failed with code 606 (Action not authorized)

but it still works.


The relay code has changed very little in a long time, and generally assumes living on a globally reachable address I think. It’s totally possible that it lacks a lot of NAT tricks present in Syncthing.

Shouldn’t the code be shared between the two, ideally?

The UPnP code is shared, so it should be no different than what syncthing does, as it’s the same code.

Other nat tricks are mostly for upd and what not.

You can run with STTRACE=nat,upnp env var to see the debug logs as to whats happening.

Could it be that strelay gives up earlier than syncthing, somehow?

When I run syncthing with STTRACE=nat,upnp, there’s a:

AddPortMapping: 500 Internal Server Error

but everything works fine.

I get the same output if I run strelay with the STTRACE env variable.

I should have mentioned that I’m using strelay 1.8.0, while syncthing is 1.10.0.

I guess if it works in syncthing, then it’s logs there are not really interesting.

The relay does print a message if it timed out.

Syncthing is however more reactive, as in, the mapping might take a long time or multiple attempts to acquire, but when it does, it reannounces itself to discovery servers, because it can function without it for other purposes.

Relay on the other hand needs to know this ahead of time to register itself with the pool, so it waits 12 seconds by default, if it didn’t get the UPnP mapping, then proceeds without one.

1 Like

Ok I see. My question then, or maybe “feature request”, would be: shouldn’t the relay’s UPnP mapping have the same successes and failures as the one in Syncthing? That would make it much more easier to have relays running on devices that are not on 24/7.

They could, but I think you should get the logs from the relay to understand why whats happening in the first place. Also, taking more than 2 seconds to get a port mapping sounds weird.

You can always setup a static port forward on the router to get to work reliably as well.