Getting a ‘Client.Timeout exceeded while awaiting headers’ error from my self-hosted discovery server on my Android phone while the phone is on a VPN. Same VPN works fine from my laptop with Syncthing and my discovery server. Discovery server is reverse-proxied behind Nginx (both in Docker containers). The discovery server otherwise works great with all our phones and computers. This has been going on for awhile, but I unfortunately don’t remember how long Just didn’t have time to look into it…
Discovery server was built from Master about 6 days ago, so should be current. Syncthing Android is v0.13.2 (most current available).
When the phone is on Wifi but NOT on the VPN, I can see its POST requests to the discovery server about every 30 minutes, just like all the other devices. The GET requests for its status by all other devices return a code 200 (successful).
When the phone is on Wifi and on the VPN there are NO POST requests visible from the phone. In addition, after the 30 min elapses without a POST, the discovery server starts returning a 404 to the other clients GET requesting status. I’m assuming this means that the phone gets dropped from the database since it’s not checking in regularly.
Laptop on the same wifi network and on a VPN connection works fine with all GET/POSTs visible in the logs. It’s the privateinternetaccess VPN so both devices have different exit IP addresses.
Edit: just to clarify…I see 3/3 for ‘discovery’ when not on VPN on the phone and 2/3 when the VPN is on.
Sorry man, I’m confused… I would expect all traffic from the phone to go through the VPN connection and out to the internet and then the discovery server. The global discovery requests are just more HTTP/S traffic, right? Why would the VPN be “eating” outgoing http requests from Syncthing while passing http requests from everything else?
I tried a different VPN client (OpenVPN Android version instead of the default PIA client). Same result.
I’m still confused as to how it can be a VPN issue when every other internet connected app on the phone works normally over the VPN? DNS is the same for everything…it’s not a per app setting that I’m aware of.
Was there a Syncthing-Android change between .12 and .13? It used to work correctly.
What else can I do to help troubleshoot this? I’m running out of ideas
Edit: pasting the discovery server URL string with a device ID into Firefox returns the correct response when I’m on the VPN connection.
Well, crap. Apparently this has something to do with the connection at work I was using last night. I’m never on the VPN at home, so didn’t test it until I came home. Of course…works fine over the VPN through my home wifi. Guess I’ll have to go test it on other connections, then figure out what’s different about being on the VPN over work wifi that works with (apparently) everything but Syncthing discovery
There is definitely an issue…tested on several other Wifi networks and saw the same results as above. I also switched from my self-hosted discovery server to the ‘default’ discovery servers and saw the same timeout. I’m guessing it’s probably working at home because I’m on a fast connection.
I’m wondering if the connection times out when the discovery server is queried just because of the slightly slower VPN connection.
I see the timeout is set at requestTimeout = 5 * time.Second in lib/discover/global.go. Would there be a downside to raising that by a bit (10*time.Second?).
I can attempt to compile an APK to test with that change if you think that’s a reasonable change without any negative side effects for other use cases.
I spun up a DO instance and tried, but it doesn’t seem easily possible (that I’m aware of) like it used to be with the old discovery server. I used the SSL certs generated by syncthing -generate=. and entered the discovery server IP address into Syncthing as https://xxx.xxx.xxx.xxx/v2/id=?<server id> but Syncthing threw a certificate validation error about ‘not containing any IP SANs’. I’m assuming this is due to the numeric IP. Tried using the -http flag without the certs, but that also threw errors because I don’t think it’s supposed to be used ‘bare’ like that without the proxy in front of it.
I also tried re-compiling the APK, increasing the requestTimeout to 10 and 20 seconds but that didn’t help either
You’re probably right that it’s some kind of DNS lookup issue, probably taking longer than it should over the VPN. It’s doesn’t seem to be a VPN client problem…tried a couple of different clients. Doesn’t seem to be a PIA issue…spun up my own openvpn server and saw the same results. I’m 80% sure this worked a few months ago, but I can’t easily prove it
Guess I’m out for now unless you guys have any other suggestions or someone smarter than me has the same issue and manages to figure a workaround.
So we do very nasty hacks for dns resolution on android, which might break under vpn. If you have the ID pinned, it shouldn’t complain about SSL certificates, but I am too drunk and too far from a computer to verify. It might an insecure flag, but best is to check the source.
Good for you being drunk and not at a computer! (I’m going to a bachelor party tomorrow)
Yeah, it looks like you patched the go source as part of the DNS resolution fix. It works inside a VPN…sometimes (ok, in one place so far: home). I’m happy to be guinea pig if you have other ideas to test out…
I haven’t looked at the source yet, but when I tried the -http flag, I still had the ID pinned in the URL.
Don’t use -http on the discovery server unless you’re fronting it with a proxy like Nginx and that proxy sends the expected headers and so on. Discovery over actual http isn’t supported and that flag is for proxied setups only. What you want to do in the minimal, most insecure case is:
Run the discovery server with a self signed certificate for whatever name (but not a numeric IP - those are magic in TLS certificates), such as one that Syncthing has generated.
Let Syncthing use it using https://192.0.2.42/?insecure to disable the certificate verification (or using the proper ?id=...).
However…using the numeric IP address for the discovery server on my cell phone behind the VPN still garnered the ‘Client.Timeout exceeded’ error message. Worked fine from laptop behind VPN on the same Wifi network (i.e. I can see the POST and GET messages from the laptop in the discovery server output).