New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gui: add advance config port mapping to gui #7017
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this! I have some specific comments below
There's a tradeoff here between having to configure the |
I think that it may be better to have a more descriptive name for this in the Advanced Configuration. "Web Ui" as such does not really mean anything, as we are in the Web UI right now, are we not 😉? Maybe I would also suggest using capitals for |
To be honest, I'd prefer if this used probing, as otherwise, I can't see this being a feature that will get any use, because I can't see people finding it and enabling it. |
I'm open to port scanning, but I'm just a little lost on where to start. I see libraries with javascript implementation of port sweeping, but I did not know if adding a library is the best decision. Does anybody now of any javascript port sweeping articles? If I had to write it from scratch, I would send a GET request to a range of ports until a success header with X-Syncthing-Id return. |
I don't think we want port scan, but we probably want to check if we can reach a web server on the other ip on the right port before showing it in the ui. No point showing something that is unreachable. |
i thought port scanning and probing were similar. My mistake. Does anyone have any suggestion about the probing technique. I am suggesting doing a http get request on a range of ports until the 200 response with X-Syncthing-id |
Ok, this is how I would do it, I guess it's up for other maintainers to agree/disagree. You don't need to do it on a range of ports. For LAN scenarios where the GUI is listening on 0.0.0.0, this will "Just work", for cases where people are behind a NAT and what not, this won't work, but we don't expect it to without additional human effort. There is still the whole "I have a million devices, I don't want a million requests upon accessing the UI", so there should probably be a switch to disable this all together. |
Yes. Probe, with a default port. A large off switch to not do it at all. |
What range of ports should it look for the gui in? |
You don't need to look for a range. It's a single port preconfigured like you have now, defaulting to 8384 |
Im confused. I thought @calmh just said to probe. I thought probe meant to look for the gui over a range of ports. |
No. Probe the configured port. If it works, show the link. |
Understood. |
I am getting a cors error when trying to make a head request to connected machines. I am sure this could be fix by me adding remote devices to the CORS policy, but it seems like a big security design decision that I would like to make sure it okay before continuing. |
I guess getting a cors error is a form of success, it's not a timeout. Not sure if you have a way to tell from what the browser returns tho. |
it seems I need to set username and password to make request to machines with an authorization set up as well. |
So we don't need the request to succeed, we just need to know if there is anything on the other side or not, hence we're fine to get a 401 or a cors error, as long as it's not a timeout. This might have some relevant info: |
I am not finished. Sometimes the link shows up correctly. Other times I think it is showing the address of a machine port forwarding to the device. it seems the $scope.connections address is not always the real address of the device. |
If it's connected via relay etc, it doesn't make sense to do the port check. so I'd check what connection type you have. |
I did not see any documentation on the connectioninfo.type. it seems to me if the connectionInfo.type is "tcp-server", than this means the connection type is the actually the device. If the type is "tcp-client", it represent a relay. Is this feature only going to work when port forwarding is not on. Is there a way to track down the final destination? |
There should be no difference for you between tcp server and tcp client. To be honest, the only time when you should not bother is when the connection type starts with relay |
Strip off the zone identifier from link-local addresses before probing. They will still fail if the browser does not allow link-local IPv6 connections, but this at least avoids the "malformed URL" error message, which is really a bug in AngularJS.
Not handling link-local IPv6 addresses correctly is definitely a bug in AngularJS and also hard to catch in our code. The error message stack trace is contains only entries from the file angular.js:
I could only avoid that by removing the zone identifier before the probing request. That yields an invalid address, which makes the browser's CORS check fail. That in turn avoids displaying a dysfunctional link. Ideally, if the Angular "malformed URL" bug was fixed, we should stop doing that, so at least compliant browsers without that limitation can actually work with the (properly encoded) address. |
Does the check fail all the time? Then we could just skip if there is a zone identifier without probing. |
Depends on the browser, so really hard to say. |
* main: lib/folder: Clear pull errors when nothing is needed anymore (syncthing#7093) lib/api: Fix debug endpoints (ref syncthing#7001) (syncthing#7092) gui, man, authors: Update docs, translations, and contributors lib/config: Sanity checks on MaxConcurrentWrites (ref syncthing#7064) (syncthing#7069) lib/ur: Fix panics in failure-reporting (fixes syncthing#7090) (syncthing#7091) lib/ur: Fix panics in failure-reporting (fixes syncthing#7090) (syncthing#7091) build: Update dependencies (syncthing#7088) lib: Remove USE_BADGER experiment (syncthing#7089) build: Update notify (fixes syncthing#7063) (syncthing#7080) lib/api: Fix /rest/config path and add methods to cors (ref syncthing#7001) (syncthing#7081) lib/api: Allow OPTIONS method in CORS preflight request handling (ref syncthing#7017) (syncthing#7079) gui: Fix another undefined variable access (fixes syncthing#7077) (syncthing#7078) lib/config: Check for "msdos" when detecting FAT FS in Android (syncthing#7072) gui, man, authors: Update docs, translations, and contributors
lgtm (except for a tiny merge conflict). With the untrusted PR merged, the changes here need to be copied over to the file in |
I will merge in main tonight. Hope that's still in time for the next rc? |
Adjust protobuf field for deviceconfiguration. Untrusted was added as no. 17, so move remote_gui_port to 18.
Merge conflicts fixed and incorporated the HTML changes to the |
Sorry, overlooked that |
Strange merge failure, moved the addition to a different section somehow?!
No good doing things in a hurry. That was some kind of very strange merge conflict from the untrusted branch I suppose. Now the HTML code inserted by this PR is in the right spot again, so the link actually shows up correctly. Sorry again for this confusion. |
$scope.idToRemoteGUI[id] = ""; | ||
continue; | ||
} | ||
var newAddress = "http://" + replaceAddressPort(connections[id].address, port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just handle the error?
We can set upgrade insecure url in the options request header. Is this acceptable?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade-Insecure-Requests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will see if it solves it tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a Really Hard Problem.
Content-Security-Policy basically always disallows mixed content (HTTP request from a script loaded through HTTPS). There are some additional headers to control that, but apparently can only further restrict access.
On the other hand, doing probe requests to HTTPS directly will fail almost always. Either the remote GUI uses the auto-generated self-signed TLS certificate, or it has a proper TLS cert, which does not match the IP address we're using to construct the remote GUI address (only the cert domain name). Either case leads to the browser blocking the request because of an insecure connection.
One solution on the browser side would be to bypass CSP for OPTIONS requests completely, since these provide no displayed content and therefore pose no security threat. Still a possible privacy problem though.
What we could do on the Syncthing side is looking at the argument of the request error callback. If the request was blocked by the browser already, that err
argument is null
. Generating an http://
link in that case still works because clicking on that is not blocked by CSP (as tested under Firefox). Such a check produces some false-positives, though, as there are many reasons why the browser could have blocked. The OPTIONS method not being allowed in the preflight request (on versions before #7079 was implemented) exhibits the same err === null
condition for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should remove the probing in its entirety and just generate an url with the hope of it being useful. I very much wanted the probing approach to work but it seems to be low value...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, ironically browsers have become a rather difficult environment for network programming. I'm also quite disappointed by all these restrictions, but they do make sense in the name of security within a WWW browsing world.
Especially the problem with link-local IPv6 addresses being unsupported is very unfortunate. They are very common as a Syncthing connection on LANs, but often unpredictable. If using Bonjour / mDNS or similar, browsers will happily make such connections, but not with IPv6 literals :-( That's still a problem even without trying to probe, but maybe more bearable.
* main: (42 commits) gui: Initialise sharing when accepting new device (fixes syncthing#7113) (syncthing#7114) gui: Initialise sharing when accepting new device (fixes syncthing#7113) (syncthing#7114) lib/model: Prevent test deadlock (syncthing#7110) lib/api, lib/db: Add file debug endpoint (syncthing#7095) gui: Add advance config port mapping to gui (fixes syncthing#4824) (syncthing#7017) lib/tlsutil: Add O and OU to generated certificates (fixes syncthing#7108) (syncthing#7109) all: Add untrusted folders behind feature flag (ref syncthing#62) (syncthing#7055) build: Update notify (fixes syncthing#5360) (syncthing#7106) lib/model: Fix locking when resending cluster-configs (syncthing#7107) gui: Remove superfluous translate in previous (ref syncthing#7102) gui: Add warning when JavaScript is disabled in Web browser (fixes syncthing#7099) (syncthing#7102) lib/model: Add done chan to track folder-lifetime (fixes syncthing#6664) (syncthing#7094) lib/model: Send indexes for newly shared folder (fixes syncthing#7098) (syncthing#7100) lib/folder: Clear pull errors when nothing is needed anymore (syncthing#7093) lib/api: Fix debug endpoints (ref syncthing#7001) (syncthing#7092) gui, man, authors: Update docs, translations, and contributors lib/config: Sanity checks on MaxConcurrentWrites (ref syncthing#7064) (syncthing#7069) lib/ur: Fix panics in failure-reporting (fixes syncthing#7090) (syncthing#7091) lib/ur: Fix panics in failure-reporting (fixes syncthing#7090) (syncthing#7091) build: Update dependencies (syncthing#7088) ...
This removes the probing for the remote side, instead making it so we simply construct the address based on the currently connected address, if any, and let the user sort out whether it works or not.
Purpose
#4824
Gives the user the opportunity to display a link to web gui remote machines. The user can choose the port and set if the link will display.
Testing
I just check to see if the link was shown depending on the setting.
Screenshots
Documentation
syncthing/docs#573
Authorship
Your name and email will be added automatically to the AUTHORS file
based on the commit metadata.