Hi, I have been using Syncthing for sometime and for what it’s capable of, it certainly fits my needs to sync data between my devices.
But recently I had some concerns and questions, and these are:
Syncthing uses hashes of each device’s public key, generated from their respective private keys, to recognize and authenticate each other. But how does each trusted device verify each other that they possesses their respective private keys used to generate their own public keys?
And can having a mismatched public and private key (let’s say an unauthorized device generates it’s own private/public key pair, but replaces their public key with one from an authorized device either through physical access or brute-forcing the authorized device’s public key from it’s SHA-256 Base32-encoded device ID) allow access to any of my devices that trust that one authorized device using their public key?
For my own use case, which is to sync data locally on a local area network or through the Internet explicitly via a VPN that I self-hosted, I have disabled NAT traversal, relaying, and global discovery. But after looking around, it seems that STUN is left enabled even if NAT traversal is disabled.
Is it true that this is the case? I’m worried that even if I had disabled NAT traversal and other options except for local discovery, any of my devices could still expose themselves to direct connections over the Internet, which is not what I want.
I want to say that I love these kind of questions - they demonstrate a great amount of awareness and technical security understanding.
I am on the phone right now, so formatting might suffer a bit. Sorry for that.
It’s actually a hash of the entire certificate (which contains the public key), but fundamentally this is correct.
Proof of key posession is a fundamental part of the TLS handshake. During an mTLS handshake both parties sign random/handshake-dependent values with their certificate private keys.
I am not sure if I understand this correctly.
Device IDs are not really secret, they can be obtained by TLS scanners fairly easily. Having a device’s public key is not dangerous. You still need the corresponding private key, which is infeasible to brute force according to current known cryptographic knowledge.
Bruteforcing all possible SHA256 hashes is also completely infeasible for today’s computers. If it were to became possible every TLS secured application would need replacement/upgrade.
I thought STUN is turned off with NAT traversal, but I may have misremembered.
No, I don’t think there is any issue. If you want to be on the safe side you should block incoming external connections to syncthing with a firewall (this applies to all applications). But even without I don’t see a big deal with that.
It’s from a very old version released ~5 years ago but it’s the only thing that I could find here that answers my question on whether STUN gets disabled if NAT traversal is disabled. As the user who posted it back then did disable NAT traversal and yet his Syncthing installation appears to still trying to contact one of the default STUN servers.
Although on the device authentication and certificates part of my questions, I now felt somewhat relieved by the answer. Thanks for that one.
Yeah, I guess it’s possible that STUN is still on as long as QUIC is enabled or STUN is not explicitly turned off. For local networks you probably don’t need QUIC, so setting your Sync Protocol Listen Addresses to just tcp://:22000should also get rid off STUN (I think).
Ok then. But I think it should be considered that since STUN is still within a category of tools for allowing access through NAT (in this case for hole punching where UPnP or NAT-PMP does not work), it should also be disabled if the user explicitly disables NAT traversal.
And it could also be nice to have some of these features:
Limit by a particular IP range or Wi-Fi network where a device can accept new devices while allowing pre-authorized/added devices to be accessible from anywhere (only allow adding new device from specific LAN network only and reject outside requests, but allow access for added devices from anywhere, either another LAN network or through the Internet)
Limit what interfaces it’s accessible from, even if Syncthing were to be started accidentally. (On Android it exists with the “Run on mobile data” option, but it has to be kept enabled if you want Syncthing to run through a VPN with mobile data, so maybe another option like “Run on specific VPNs”?)
If someone were to accidentally start Syncthing on mobile data without being connected to a VPN of choice, then they may allow Syncthing to be accessible directly over their cellular connection which some might not want.
Also again about device IDs and authentication, can the entire thing, with the device ID and the private/public key pair be seen as the following:
The device ID, based from the hash of the public key certificate, which itself is based from the private key, is used to identify who a particular device/installation is, like a username.
The public key certificate (also refered here as “public key”) is used as part of mTLS and later for confirming if a device with a particular device ID is really who they say they are, is like a password of sort (but it doesn’t need to be kept secret, like the device ID, right?)
The private key is used to confirm that the public key certificate given, which can be used to encrypt something that can be decrypted only with the corresponding private key, is like a second factor of authentication. Proving that the presented public key certificate and the public key contained within indeed belongs to that connecting device since anything encrypted with it can be decrypted only by that device and the decrypted information can be rencrypted with the public key of the other end confirming everything.
So with all that, it can be said that Syncthing requires authentication that proves that a particular device really has been authorized to access data shared by the other device, and vice-versa. And not like a webpage where there is a page that says "Password: " without any username or multi-factor authentication, which is what I was actually worried about. That a public key, even with a non-matching private key, is what that is needed to access and write data from and to a Syncthing-running device. Which has been proven false by requiring the private key to be used.
With all said, it seems good to me. Thanks for the quick answers, but I do still want to hear from others about this, at least until till the topic is closed automatically due to inactivity.
If you mean the two above, I don’t really understand how number one (limited address range for “new” devices) would work (or why it’s desirable, really), and for number two you can set the network address to bind to. Doing interface names instead is trickier as that’s not how the underlying APIs work, we’d need to periodically poll the interface list to get addresses and then bind to those addresses, which sounds like it would suck…