Support HTTP over unix domain sockets
Categories
(Core :: Networking, enhancement, P5)
Tracking
()
People
(Reporter: erikjensen, Unassigned)
Details
(Whiteboard: [necko-triaged])
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Steps to reproduce:
Many daemons provide a web-based UI for configuration and observation. Additionally, many web development environments involve running a server locally.
Today, such services listen for TCP connections on localhost. This is generally fine for single-user systems, but can run into problems for multi-user systems. The first issue is that there's no access control, so any user on the system can connect to the port to connect to a service run by another user. For configuration GUIs, this can be worked around by implementing authentication in the GUI itself with its own password, but it's far from ideal. Restricting access to local dev webserver doesn't really have a good solution. The second issue is port contention. If two users want to run the same service, they have to ensure they are using different ports.
Unix domain sockets can solve both of these problems. The former is solved by using file permissions to ensure that only the user running the service can connect. The latter is solved by placing sockets in directories owned by the user (e.g., $XDG_RUNTIME_DIR, or their home directory), ensuring that there's no conflict with other users.
As a concrete example, a shared family computer might have multiple users who would like to have Syncthing running in the background. To make this work, each currently has to select a different port for the GUI, and ensure they have a password set in the Syncthing GUI itself to prevent other users from connecting to and configuring their instance. Syncthing already supports listening on a unix domain socket instead of using TCP, so the only thing missing is browser support.
Actual results:
There is no way (that I could find) to connect to a server via a unix domain socket in Firefox.
Expected results:
It should be possible to tell Firefox to connect to a unix domain socket speaking HTTP. One possible URL format might be http://localhost:[/run/user/1000/syncthing.sock]/, where the socket path is wrapped in square brackets and replaces the TCP port. (This would be a special case for localhost.)
Another option might to use a custom URL scheme, like unix+http://[/run/user/1000/syncthing.sock]/
This could be provided by Firefox out of the box, or an extensibility mechanism could be added to allow the functionality to be provided by an add-on.
| Reporter | ||
Comment 1•5 years ago
|
||
Note: The idea for the former URL format was taken from this post: https://web.archive.org/web/20190321081447/https://plus.google.com/110699958808389605834/posts/DyoJ6W6ufET
Comment 2•5 years ago
|
||
Bugbug thinks this bug should belong to this component, but please revert this change in case of error.
Comment 3•5 years ago
|
||
While we do have a few instances of PR_AF_LOCAL and AF_UNIX sprinkled in our codebase, I think getting this to actually work would be a bit difficult, for very little benefit.
I am inclined to WONTFIX this - similar to Chrome.
Neither off the URL formats work well, since they clash with the URL Spec - the first one breaks port parsing, the second IPv6 parsing. If we were to do this, I expect we'd need a new scheme for this.
Unix domain sockets is a pretty niche thing to do - I expect anyone who's going to use that can easily set up a proxy for that instead.
See also:
https://daniel.haxx.se/blog/2008/04/14/http-over-unix-domain-sockets/
https://bugs.chromium.org/p/chromium/issues/detail?id=451721
| Reporter | ||
Comment 4•5 years ago
|
||
I would argue that the main reason it seems niche is because of the lack of browser support. Running local web servers for development or configuration GUIs certainly isn't niche, and unix domain sockets provide a number of advantages over localhost TCP, including access control by default, namespacing in the filesystem, not needing to assign and remember unique, otherwise meaningless numbers for each service / instance, et cetera. The fact that several servers already support serving to unix domain sockets even without browser support suggests to me that there is both interest and utility in this functionality. They're even now supported on all major OS's.
I'm not sure I understand the parsing problem, as I would have thought the leading '/' for the socket path would be a sufficient disambiguator. Is the concern that existing Javascript might not work with the new format?
Thanks.
Comment 5•5 years ago
|
||
(In reply to Erik Jensen from comment #4)
I'm not sure I understand the parsing problem, as I would have thought the leading '/' for the socket path would be a sufficient disambiguator. Is the concern that existing Javascript might not work with the new format?
So the way the standard is currently defined does not allow for anything except numbers to be in the place of the port, or an IPv6 address instead of the host. I suggest opening a new issue on the spec to discuss this topic. It may be a good place to measure interest from other browsers too,
| Reporter | ||
Comment 6•5 years ago
|
||
I created https://github.com/whatwg/url/issues/577
Comment 7•2 years ago
|
||
This will be unsafe and cause confused deputy vulnerabilities. These already exist on localhost + port services thanks to a conflict of assumptions: "local-only daemons", but also browsers being able to access localhost + port. Independently each piece is working according to specification, but combined, there's a vulnerability. Unix domain sockets, by not being available in the browser, are generally considered the safer path around this for now.
A particularly damning example is how Guile supported a live REPL you could connect to, localhost + port in your editor. Except it turns out since browsers also could access localhost + port, this turned into a confused deputy vulnerability: https://lists.gnu.org/archive/html/guile-user/2016-10/msg00007.html
The mitigation, notably, was to switch to unix domain sockets... because the browser wasn't assumed to have access to them.
Object capability security could allow for a secure way to pass around file handles on the operating system, but ACL protections won't work here. The permissions of the user means that the browser can now access all the things the user can access, and this turns into a dangerous situation because the browser acts "as you". It's notoriously difficult to prevent 3rd party websites from accessing localhost + port: dns rebinding attacks, etc.
Please don't do this without considering an object capability security approach. ACLs are not enough.
Comment 8•2 years ago
|
||
This would easily become safe by limiting things to user-navigation top-level frames. The same-origin policy could be only allowing a UDS website to connect to its own UDS, and have UDS fetch, iframes, etc. if they match the parent frame.
Comment 9•5 months ago
|
||
agreed; isn't this the purpose of the same-origin policy? you wouldn't allow a third-party website to POST to localhost anyway, let alone a local socket, right?
| Comment hidden (advocacy) |
Comment 11•2 months ago
|
||
Fabrice implemented this in b2g a few years ago: https://github.com/capyloon/gecko-b2g/commit/aedd3800e8b492e682f50e3946160a790545f303
We don't have plans to support this in Firefox in the near future, but feel free to try out the patches locally/in your favorite fork.
Description
•