I am running a Syncthing instance on my Raspberry Pi from my home connection. My home connection has a dynamic IP, so I use a dynamic DNS service (no-ip.com) to have a domain I can use to connect to it even if my home IP changes during a (forced) reconnect. My Raspberry Pi routes all outgoing traffic through a VPN and routes incoming traffic for Syncthing, nginx etc. over my regular connection, because my VPN does not support port forwarding – this part of my network configuration 100% works, the problem isn’t here.
The problem is that because the Raspberry Pi routes all outgoing traffic over the VPN, the servers Syncthing contacts to figure out my public IP address will return the VPN’s IP address instead (which does not support port forwarding, so clients will fail to connect to it).
Clients that have my Raspberry Pi’s device ID and do not explicitly specify “tcp://my-dynamic.domain” instead of “dynamic” in its “Addresses” section will fail to connect, because it will just attempt to connect to the VPN’s server IP address.
I figured that I’d just force Syncthing to advertise a specific global address instead of the automatically determined one. To that end I went to the advanced options, edited the Raspberry Pi’s device section (its own device section on the Raspberry Pi instance) and changed its “Addresses” field to just “tcp://my-dynamic.domain”. I was hoping that this will then be advertised to the global discovery server, today I found out however that this fails when a friend tried to connect to it and instead only got the VPN’s IP address (I checked in their device section).
Syncthing should announce its listening address to the discovery servers so I would expect that to work. When the listening address is unspecified (0.0.0.0) or private (192.168/24 etc) it will get replaced with the actual source address seen by the discovery server though.
So are you saying that specifying addresses that contains my dynamic DNS server’s domain in “Sync Protocol Listen Addresses” for the Raspberry Pi would fix the issue? Currently it is set to “default”. So something like: “tcp://my-dynamic.domain:22000” for example? Because it obviously translates the “default” (which according to docs is basically just “0.0.0.0” and relays) to my VPN’s IP address.
Yes. Though the announcement will use the resolved address and not the name. And the address will need to be a valid listening address. Maybe I misread your message but that’s where I thought you had entered it.
, in the “Advanced” section. I don’t think “tcp://my-dynamic.domain:22000” is a valid listening address, right? At least I’m not sure how my system would know if it can bind to that. I can try entering that and see.
Ah, yeah, entering something there for the local device has no effect.
If the name resolves to an address on this device i expect it to be a valid listen address. If it doesn’t, like if it’s a port forward somewhere, it won’t be.
Which is my VPN’s IP address and not the public address I want to actually advertise. Is there no way to override which IP address is advertised somehow?
I think no, large footgun potential and fairly small utility. But fee free to drum up more support or use cases for it and someone else may think it’s worth it.
Hm, I think I have a better chance of making this work if I just force traffic to some destination IPs (stun.syncthing.net) through an IP routing table then, so that my clearnet IP contacts the servers responsible for resolving my external IP address instead. Thank you for your quick support.
Luckily I made a tool for exactly this quite a while ago:
$ sudo vpn-whitelist stun.syncthing.net --ufw
stun.syncthing.net:
ip route add 139.59.84.212 via 192.168.178.1 dev eth0 table main
ufw allow out on eth0 to 139.59.84.212 comment 'Whitelist stun.syncthing.net (2020-05-09 18:45:48)'
ip route add 198.211.120.59 via 192.168.178.1 dev eth0 table main
ufw allow out on eth0 to 198.211.120.59 comment 'Whitelist stun.syncthing.net (2020-05-09 18:45:49)'
You need to do that for discovery servers, not just stun.
As stun is only used for quic and working out the external address.
You probably want TCP which leaves it to the discovery servers to look up the address.
Also, discovery servers will not be able to lookup the port (as we don’t reuse the same outgoing port for discovery and sync protocol), so it will use your <xternal address>:<default listen port which is 22000>. If your router doesn’t route port 22000 to you directly, it won’t work.
You need to do that for discovery servers, not just stun. As stun is only used for quic and working out the external address.
But aren’t the STUN servers used to resolve my external IP address, which is then advertised to the global discovery servers? I’m just asking because what I just did definitely works, I just confirmed this with my friend. The only issue was that my Syncthing instance advertised the wrong external IP address (the VPN IP address instead of my clearnet IP address). As long as the correct external IP address is determined, everything else works.
My router does forward the default ports, so that’s not an issue.
Am I correct in my assumption then, that the default global discovery servers are “discovery(-1).syncthing.net” and future ones will follow a similar pattern? I couldn’t find any concrete domains in the documentation. They currently seem to point to the same IP as “stun.syncthing.net”?