Can the syncthing web GUI report authentication errors?

I have a fairly secure file syncing setup with except I have a couple of publicly visible static nodes and I want to take my security to the next level.

Since the file transfer protocol itself already uses pretty good encryption, based on a couple threads here I won’t need to do anything special for it.

The web GUI does worry me though since it’s effectively an open target for a long running brute force attack on the password. All I’d need to thwart this though is an automatic banning system like for example fail2ban. The long and short of it is that fail2ban is a service that will read a logfile for regexes that look like failed login attempts and if certain criteria are met (eg 10 login failures within a day) it will install a firewall rule or add it to a blocklist.

I doing a couple password failures on Syncthing web gui and nothing shows up in the log. Contrast this with an HTTP basic login failure at apache2 or nginx, which will show up in the log and i can setup a rule to count and block those.

Logging on failed authorization would be a simple addition. I can cook up a PR for it. Should it be a WARNING or rather INFO in the log?

I think you can do this with some reverse proxy in front of syncthing.

There is also a Login Attempt event generated on the Event API. If your banning system can poll that API with valid credentials, you could use that for monitoring.

1 Like

Yeah I was thinking of doing this as a fallback but the less complex the setup the better.

that sounds pretty cool! what would be the simplest way to view or output the event api as a logfile?

I’m able to construct a simple filter to output loginattempt events as follows:

curl -sL '' \
     -X GET -H "X-API-Key: MY_API_KEY" \
  | jq '.[]|select((.type == "LoginAttempt") and (.data.success | not))'

  "id": 956,
  "globalID": 975,
  "time": "2021-04-09T21:10:29.802014739Z",
  "type": "LoginAttempt",
  "data": {
    "success": false,
    "username": "myusername"

Couple missing points here:

  • login event does not have the IP address that I can use to block against
  • not sure the best way to have something like that streaming to a logfile

by the way this events API is pretty rad so if only I could extract the IP from this I might write some log listener but this is pretty awesome

1 Like

Another find, there’s an --audit --auditfile=FILENAME that I can use to output syncthing events. From there I can run a filter on that to see loginfailures.

If you are running syncthing as a unix service and you need to output this to a file or to the journal, you will need to add the above arguments to your syncthing@.service file. On Ubuntu, first copy your /usr/lib/systemd/system/syncthing@.service to /etc/systemd/system/syncthing@.service, then append to the end of the ExecStart line:

ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0 --audit --auditfile=-
# auditfile=- if you are happy with it outputting to the journal or below if you want it to a file
# ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0 --audit --auditfile=/var/log/syncthing-events.log

Still have the issue thought that the loginattempt event does not give the IP so unless that is released I’ll probably end up having to reverse proxy

There is a simple helper utility in the Syncthing source, which can be used like this:

./stevents -apikey MY_API_KEY -target -types LoginAttempt

A look at its source code should give you enough details to reimplement that in any other language as well, if you don’t want to fiddle with producing the stevents binary.

Adding the requests source IP address to the event sounds reasonable. What do other maintainers think of it and / or logging the attempts to the regular log?

Very interestingly, Syncthing also outputs device rejection events; this makes it possible to also apply fail2ban rule on the sync process itself in case you’re at that level.

DeviceRejected — Syncthing v1 documentation

But the event is deprecated in favor of device change events that dont seem to have the same meaning, so if you wanted to go that way I suspect there’s some dev work needed.

PendingDevicesChanged — Syncthing v1 documentation

I would suggest the systemctl edit ... subcommand instead. Not quite sure how it interacts with template@.service units, but at least it produces an override file to still enjoy future updates to the underlying .service file.

1 Like

whoa i had no idea that even existed :smiley:

The PendingDevicesChanged is a direct replacement for DeviceRejected, generated just at the same time. It just extends the event to signal devices which were previously reported as DeviceRejected, but should no longer be shown to the user. That happens when the device was actually added as a trusted device locally. You could use it to unblock the firewall rule for example.

Including the remote address in LoginAttempt events is proposed here:

1 Like

I’ve seen the PR, but I still feel this should be done/handled by a reverse proxy, because fail2ban etc already have scrapers for those.

Also, I don’t buy the complexity argument, as you’re trading off “setting up reverse proxy” complexity, which we know how to do and it’s documented, for “change how syncthing works and write a custom fail2ban scraper”, which seems like much higher complexity.

Also, there is suddenly a need for syncthing to have magical config flags to enable/disable handling of X-Forwarded-For etc based on whether it’s behind a reverse proxy or not. Seems like a lot more complexity (not just in your usecase, but also in syncthings code base) comapred to just setting up a reverse proxy.

@madumlao the PR is now merged and you can look forward to the remoteAddress field as part of the LoginAttempt event in the next release v1.16.0.

Hope that helps :slight_smile:

1 Like

Understand where you’re coming from, but if that’s the stance you’re taking, then we can go all the way and say syncthing web shouldn’t have basic auth at all and leave all authentication to a guarded reverse proxy. It seems reasonable to me that if you do (a) auth and (b) logging, then people will look for (c) some minimum level of auth logging. Having read the PR, I don’t see why people wouldn’t look for the “can of worms” case with X-Forwarded-For in the future anyways. That is, if you are logging authentication failures at all, people will wonder why you don’t have the IP. It would be like not logging the username.

As for why I might want to put firewall rules on syncthing auth logging specifically as opposed to apache - apache’s logging directives are somewhat limited for isolating applications. The ideal would be to have a separate set of logfiles for each VirtualHost, but even the reverse proxy guide in syncthing assumes that we are proxying by location (and I do not want a separate virtualhost for syncthing). Effectively, mixing in syncthing’s auth logging with the rest of the applications being monitored can cause false negatives if you have more than one application you have rules for.

That sounds very helpful - I’ll be looking forward to this on the next release.

I agree with @AudriusButkevicius on this one. Properly handling proxy headers is a can of worms which would also need additional configuration options on syncthing. You can’t just blindly take the values from this header as anyone could set it, so you’d have to configure a proxy whitelist as a bare minimum.

And all your points boil down to the fact that apache isn’t doing a good job for you.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.