Is it possible to run Syncthing entirely over SSH (or VPN)?

Hello. I just joined and this is my first post. I have been reading the Syncthing docs today and I want to know if anyone has tried anything like this. We are all connected via SSH tunnels through a hardened bastion host. (It is a set of forward and reverse tunnels that connect all devices, even those behind firewalls.) That bastion host has no HTTP/HTTPS services (or any other services except SSH and we are not allowed to add any or open any other ports).

Could we run Syncthing within that type of network? My first guess is that it would be like local discovery mode only. But the address of every device is simply syncuser@localhost with a unique port number, and the connection is SSH protocol, of course. Can that work with Syncthing?

Alternatively, is anyone running it entirely over a VPN? We do not have a VPN setup, so I would prefer to utilize our existing SSH network, if possible.

You can set device addresses to tcp://some-ip:some-port to make Syncthing connect as you please, without discovery. You can point it to a port forward or a VPN address. It will be difficult to get it to work with discovering addresses and ports automatically.

Thanks for your reply. I don’t think we need the discovery, so that part should be OK.

Would you recommend autossh? Or how about sshuttle (https://sshuttle.readthedocs.io/en/stable/overview.html)?

Is there anything else we need to know to configure TCP over SSH in Syncthing? It sounds like you are saying that if the SSH tunnels are set up (they are), not much is required to make Syncthing connect over them.

I just found this page: https://docs.syncthing.net/users/tunneling.html

Hi @calmh I have this working with 2 devices, based on the SSH Tunneling page.

Could you help me with an example of how to extend that from 2 devices to say 4 or 5? (Or even an example for 3, I guess.)

Also, I’m a little confused by one thing. I had to use this for my tunnel:

ssh -i ~/.keys/somekey.pem \
  -L 127.0.0.1:22001:127.0.0.1:22001 \
  -R 127.0.0.1:22000:127.0.0.1:22000 \
  syncguy@hostb

Notice how that differs in a subtle but important way from the example at the SSH Tunneling page.

In my mind, each device should have a unique port number, and it should be the same on both sides of the tunnel. Do I have this misconfigured? (It is working. And in my setup, the -R and -L don’t matter. They could both be R or L.)

Thank you.

EDIT: this is a more complete example of my config:

$ ssh -i ~/.ssh/id_syncthing_ed25519 \
  -L 127.0.0.1:22445:127.0.0.1:22445 \
  -R 127.0.0.1:22222:127.0.0.1:22222 \
  syncguy@hostb

hosta:
Listen Addresses: tcp://127.0.0.1:22222
Remote device: hostb: tcp://127.0.0.1:22445

hostb:
Listen Addresses: tcp://127.0.0.1:22445
Remote device: hosta: tcp://127.0.0.1:22222

I have no recommendations on the ssh tunnelling stuff. In fact my recommendation would be “don’t”. But if you have to, you know how to point Syncthing at a tcp port now. :slight_smile:

1 Like

I did get it working with 3 devices using the same approach as above. I am still a bit confused about the difference between my tunnel config and the example given in Syncthing docs. I hope someone will comment.

Another curious issue. Even though all my devices have addresses on the 127.0.0.1 network, when I add this config, the GUI reports that the devices are disconnected.

<allowedNetwork>127.0.0.1<\/allowedNetwork>

When I remove that setting, things work again. Any idea what I’m doing wrong? I did not find the answer at https://docs.syncthing.net/advanced/device-allowednetworks.html

Looks like you need a netmask (“127.0.0.1/32”).

Another trick you may or may not have considered is that local host is actually all of 127/8. You can add as many arbitrary alias IPs to lo0 as you want, like 127.2.40.22. Since these are different addresses you can have different processes all bind port 22000 on one of these addresses. This can be useful when simulating multiple remote hosts and still keeping ports usual…

It might make things easier for you to use a specific local address for each remote tunnel and bind to 22000 on each of them, and just tell Syncthing about the IP numbers. For example.

I used to do this (via a tool) when connecting to lots of things behind a bastion host. Each thing behind the host got a local IP, with its real IP just having the first octet replaced by 127. Then the services tunnelled from there so ssh, http, etc would work as expected just with a slightly different IP. For bonus points, you can tweak the name resolution in /etc/hosts and this is all transparent.

But Syncthing connections are already encrypted and certificate authenticated so, again, don’t. :wink:

2 Likes

Thank you. That’s all a big help! Syncthing is great. Thanks for your continued work on it.

1 Like

Just an update: I’m doing some testing and the SSH stuff is working well.