8 ms·
Fun with Unix domain sockets
- nine_k 5y agoI wish browsers could talk to Unix domain sockets (and maybe named pipes on Windows). That would allow to run web servers locally and more securely: domain sockets live on the file system with the usual access control means available, while binding to a port on localhost has no such easy and familiar control.
- seiferteric 5y agoWe recently used them at work to easily implement role based access control to an internal REST service since unix sockets have the useful ability of being able to tell which user is reading/writing to them. So you don't need to provide passwords or certificates because if the user is logged in on the system, they are already authorized.
- sethammons 5y agosu -u $otherUser Wouldn't that mess it up?
- seiferteric 5y agoYou need the other users password to do that, or be root, so it is not a problem. Also, in our system, non admin users don't have linux shell access anyway, they get a custom shell that uses the rest server as the backend. The admin user can get linux shell and run commands as other users or do whatever they want but that is expected.
- rwmj 5y agoI use this all the time for mocking / testing REST-ish services, since otherwise the test has to consume a port. Ports are limited in number, contended (eg. with real services or other tests), and may even be exposed to the public if your firewall is misconfigured. On the client side of the test Curl makes this easy with CURLOPT_UNIX_SOCKET_PATH. Agree with you about support in browsers. Here's a fun and little known fact about Unix domain sockets on Linux: They have two independent SELinux labels. One is the regular label stored in the filesystem, and the other has to be set by the process creating the socket (using setsockcreatecon). On an system with SELinux enforcing and a decent security policy you usually have to set both. I just posted a patch for qemu to allow the second one to be set: https://lists.nongnu.org/archive/html/qemu-block/2021-07/msg00714.html https://lists.nongnu.org/archive/html/qemu-block/2021-07/msg...
- jerf 5y agoCheck your local "listening" API. Unix permits you to just ask for "a port that is open", in a range defined by your kernel that is usually left untouched by everything else and will have no forwarding associated with it. Then you don't have to worry about the port selection process. However, this is a prime example of a feature that many people writing abstraction layers around networking leave out of their layer, due to either not knowing it exists or not knowing the use case and figuring that nobody could ever have a use for it. So you may very well find it is not available to you (or not available conveniently) in your preferred environment. (See also "what are all these weird TCP flags? Eh, I'm sure nobody needs them. Abstracted!") If you have Unix sockets working, by all means stick with them, but if you need sockets this feature can help. You can even run multiple such tests simultaneously because each instance will open it's own port safely. (I have test code in several projects trust does this.)
- kortilla 5y agoBut that’s a worse solution unless you feel the need to test the kernel’s tcp stack. You’re back to opening local ports that anyone on the box can access. You can work around that by isolating the tests into a container/namespace, but now you have more stuff to orchestrate. Finally, the problem with binding to 0 and letting the kernel pick a port is now you have to wait for that bind event to happen to know which port to connect to from your test side. With domain sockets you can set that up in advance and know how to communicate with the process under test without needing a different API to get its bound port number.
- rwmj 5y agoIt's definitely the last point which is the main problem. We can start the server side and tell it to pick a port, but then we have to somehow communicate that port to the test / client, and often that channel of communication doesn't really exist (or it's a hack like having the server print the port number on stdout - which is what qemu does). Unix domain sockets by contrast are an infinite private space that can be prepared in advance.
- 5y ago
- jag327 5y agoFirefox can talk to a unix socket. In your proxy settings specify the socket. E.g., it is how you can more safely proxy through tor (which also can listen on a socket), with firefox running inside a network name space without access to a network interface. Things like webrtc cannot leak your real IP.
- kortilla 5y agoOp means typing a socket into the address bar. Using a socket for proxying is not the same thing.
- nine_k 5y agoIt's still strictly better than no way at all! Using something like OmegaSwitcher, it's easy to configure some DNS suffix like `.local.test` to be mapped to local Unix sockets. Not as easy as built-in support, but at least doable.
- foresto 5y agoI don't see a field for this in the Connection Settings dialog. Where do you type the socket name/path?
- signa11 5y agoopnbsd’s netcat can bind to af_unix endpoints, perhaps that can brought to bear to solve this ?
- gizdan 5y agoThat still requires listening on tcp.
- yrro 5y agoThis a million times. Imagine how much less annoying e.g. syncthing UI would be! (Granted programs can sort of do this with TCP sockets too, at lwast on Linux: read from /proc/net/tcp/somepathicantremember and use that to find out the U credentials of the client currently connected to your server...)
- snthd 5y ago>Imagine how much less annoying e.g. syncthing UI would be! Assuming you mean the local web app needing an self-signed certificate... https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#when_is_a_context_considered_secure https://developer.mozilla.org/en-US/docs/Web/Security/Secure... >Note: Firefox 84 and later support http://localhost http://localhost and http://*.localhost http://*.localhost URLs as trustworthy origins (earlier versions did not, because localhost was not guaranteed to map to a local/loopback address). So if syncthing is reachable on a port on localhost you can just switch https off.
- fao_ 5y agoYou kind of can already, I know this isn't what you mean, but you can connect to unix sockets via a native application. "Native messaging enables an extension to exchange messages with a native application, installed on the user's computer. The native messaging serves the extensions without additional accesses over the web." https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/Web...
- pabs3 5y agoThere was a blog post about this recently: https://www.enricozini.org/blog/2021/debian/run-a-webserver-for-a-specific-user-only/ https://www.enricozini.org/blog/2021/debian/run-a-webserver-...
- pabs3 5y agoPersonally, I think I would add a browser extension forwarding fooapp:// to a native messaging process gatewaying to the socket.
- pabs3 5y agoRather than Unix sockets, I wonder if you could do something with TLS client certs. Use https to localhost, then require the user to generate a TLS client cert and somehow register that with the app.
- mongol 5y agoYes me too. What would it take to get there? Does the URL format allow for a socket to be specified, how would such a URL look? http:///path/to/socket:/uri-path http:///path/to/socket:/uri-path ? Would that be distinct enough?
- leephillips 5y ago“It turns out both nginx and Apache have the ability to proxy traffic to a Unix domain socket rather than to an HTTP port, which makes this a useful mechanism for running backend servers without attaching them to TCP ports.” That’s one useful nugget of information! I had no idea.
- rogerdonut 5y agoHAProxy can as well (as well as listen on unix sockets)
- moderation 5y agoAnd Envoy Proxy (with an example [0]) 0. https://gist.github.com/moderation/5d9c5352842ca068781f367a6e5f2a39 https://gist.github.com/moderation/5d9c5352842ca068781f367a6...
- colek42 5y agosocat is the tool for this. No need for a full blown webserver.
- RedShift1 5y agosocat is a "dumb" tool. With a proxy that understands HTTP you have a lot more influence over what goes where and for example not direct requests to a down backend instance.
- colek42 5y agoAre you challenging me to build a socat loadbalancer in bash? In all seriousness, I concur. But if you just need to redirect some data streams socat is a rock solid and simple solution.
- jsjohnst 5y ago> Are you challenging me to build a socat loadbalancer in bash? It’s a Saturday and all, so yeah, I’m challenging you (for fun, not because I don’t think it’s possible).
- deleted 5y ago[deleted]
- colek42 5y agoThe UDS API has a particular property that allows the receiver to know the PID of the caller. The SPIFFE/SPIRE project uses this to perform introspection of a process and distribute certificates based on the results of that inspection. It is a really great tool to use in systems engineering.
- yrro 5y agoYou can do this for TCP too by pulling out the info about the process that has connected to your socket from /proc. Not as nice an API but at least it's there.
- Matthias247 5y agoI think you can do even more and pass other file handles (FDs) through the socket, in order to provide the peer access to those resources.
- namibj 5y agoYeah, and when you add kernel TLS to the mix, you can handle the certificate part of TLS termination in a guarded user/process, which never needs to touch HTTP headers.
- DesiLurker 5y agoone lesser known facility I have used with UDS is called SCM_RIGHTS. It is used to send open file descriptors for actual files/shm regions/socket connections. the receiving process gets the same file handle as if translated into its process space by a dup by kernel. this is very useful for implementing things like graphics compositor where specialized memory regions need to be passed around to various processing stages.
- xfer 5y agoFor people curious: https://man7.org/linux/man-pages/man3/cmsg.3.html https://man7.org/linux/man-pages/man3/cmsg.3.html This is used by a lot of classic unix tools(dbus). The "modern" api for linux is https://man7.org/linux/man-pages/man2/pidfd_getfd.2.html https://man7.org/linux/man-pages/man2/pidfd_getfd.2.html .
- DesiLurker 5y agoits good to have that api but a significant difference is that it requires clients (and even servers) to know the pid of the process they are sending this fd to. this is unnecessary when you can make do with a socket connection (inherited of otherwise).
- lxtx 5y agoWith Unix sockets you can even have in-order datagram semantics, which I think is just neat!
- inetknght 5y agoUnix domain sockets are cool and awesome. It's all fun until some local application decides that it should bridge a third party server and some service on your system. Do you want your browser to facilitate Google talking to your docker daemon? What about your dbus?
- galaxyLogic 5y agoI read this from Wikipedia: "In addition to sending data, processes may send file descriptors across a Unix domain socket". Does this mean you can send a Unix domain socket via a Unix domain socket? https://en.wikipedia.org/wiki/Unix_domain_socket https://en.wikipedia.org/wiki/Unix_domain_socket
- loosescrews 5y agoYes. You can send any file descriptor. You might also be interested in socketpair[1], which creates a pair of FDs connected via an anonymous Unix domain socket. Sending a socketpair over a Unix domain socket is a nice way to establish a new channel of communication. [1] https://man7.org/linux/man-pages/man2/socketpair.2.html https://man7.org/linux/man-pages/man2/socketpair.2.html
- hughrr 5y agoYes although I inherited something that did this once for no good reason and it made me scratch my head for several hours before I understood it properly. YMMV on that.
- markjdb 5y agoYou can even send a Unix socket over itself. The kernel has to be careful to handle that correctly. :)
- galaxyLogic 5y agoThat is pretty far-out, conceptually. But in practice I assume there would be little need for that right? If you have the socket already and you get the same socket again from somebody else, would that give you any new capabilities? If a socket is shared among multiple actors, can a same message be read by all of them? Or does the first reader "remove" the message from it?
- lukeh 5y agoWe used LDAP over domain sockets with SO_PEERCRED many years ago, to tightly couple other services that needed different authorization to remote users.
- RajuVarghese 5y agoI recall using this on a SunOS 3.x system (BSD 4.2-based) to build a message passing system. Over the years I expected it to be used more often for machine-internal communication. I think it was overshadowed by its sibling the network socket because that could be used for local as well as network communication.