[HN Gopher] Fun with Unix domain sockets ___________________________________________________________________ Fun with Unix domain sockets Author : edward Score : 145 points Date : 2021-07-24 14:15 UTC (8 hours ago) (HTM) web link (simonwillison.net) (TXT) w3m dump (simonwillison.net) | DesiLurker wrote: | one 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. | [deleted] | galaxyLogic wrote: | I 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 | hughrr wrote: | Yes 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 wrote: | You can even send a Unix socket over itself. The kernel has to | be careful to handle that correctly. :) | loosescrews wrote: | Yes. 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 | nine_k wrote: | I 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. | jag327 wrote: | Firefox 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 wrote: | Op means typing a socket into the address bar. Using a socket | for proxying is not the same thing. | nine_k wrote: | It'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 wrote: | I don't see a field for this in the Connection Settings | dialog. Where do you type the socket name/path? | fao_ wrote: | You 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/Web... | signa11 wrote: | opnbsd's netcat can bind to af_unix endpoints, perhaps that can | brought to bear to solve this ? | gizdan wrote: | That still requires listening on tcp. | yrro wrote: | This 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 wrote: | >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... | | >Note: Firefox 84 and later support http://localhost and | 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. | rwmj wrote: | I 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/msg... | jerf wrote: | Check 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 wrote: | But 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 wrote: | It'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. | jerf wrote: | I don't have a problem running my test code on boxes with | hostile people logged in to them, nor do my socket | connections offer them anything they couldn't already do | if they have that level of access. You sound like you may | have a very particular problem, and if this is your | situation I'm not convinced "Unix sockets" are the answer | anyhow... you seem to have bigger problems with | unauthorized access. | krferriter wrote: | If call bind with port 0 in Linux or Windows or OSX the OS | will bind to a random unused port within the unrestricted | port range. Whether there is any forwarding or firewall | associated with that port is outside the scope of the code | that opens the port. If the application is assigned a | random port such as 55555 there could be forwarding or a | firewall on that port at the OS level that the application | is unaware of. If an application is opening random | listening ports it just needs to record that information | somewhere so clients can actually connect to it. In the | case of using this for testing localhost servers the | application can just print out the port number or save it | to a file so that you can look it up easily without going | through netstat or something. | | Opening a random listening port to serve content to clients | which initiate communications to it is less common than the | use case of initiating a communication to a listening port | elsewhere and sending content through that socket, though | both of these use cases open random local ports. | koolba wrote: | The annoying thing with Unix sockets is making sure to delete | them and recreate them. IIRC, there's no file system | equivalent of SO_REUSEPORT. | aktau wrote: | UNIX domain sockets also support an abstract namespace, not | a part of the filesystem [1]. | | An excerpt of [2]: | | > The abstract namespace socket allows the creation of a | socket connection which does not require a path to be | created. Abstract namespace sockets disappear as soon as | all open instances of the socket are removed. This is in | contrast to file-system paths, which need to have the | remove API invoked in code so that previous instances of | the socket connection are removed. | | It worked quite well when I tried it (also in addition to | using SO_PEERCRED for checking that the connecting user is | the same as the user running the listener in question). | | [1]: https://unix.stackexchange.com/a/206395/33652 | | [2]: https://www.hitchhikersguidetolearning.com/2020/04/25/ | abstra... | koolba wrote: | That's fantastic. Too bad it's Linux only though. Is | there an alternative for other systems outside of adding | a delete step first? | seiferteric wrote: | We 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. | inetknght wrote: | Unix 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? | lxtx wrote: | With Unix sockets you can even have in-order datagram semantics, | which I think is just neat! | colek42 wrote: | The 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. | Matthias247 wrote: | I 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. | yrro wrote: | You 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. | leephillips wrote: | "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. | z3t4 wrote: | On webide.se (free shell and web IDE) I use unix sockets alot!, | for example nginx proxy from https://foo.user.webide.se to | /home/user/socket/foo so that users can test their apps using | HTTPS/SSL as many browser features need a httpS URL to work. | Unix sockers are also used for accessing a shared mySQL server, | and an x11 server so you can test out "native" apps and run | Android emulator in the browser. | girishso wrote: | TIL | rogerdonut wrote: | HAProxy can as well (as well as listen on unix sockets) | moderation wrote: | And Envoy Proxy (with an example [0]) | | 0. https://gist.github.com/moderation/5d9c5352842ca068781f367 | a6... | phoyd wrote: | Now Docker should provide some way to bridge container ports to | UDS. That would be perfect. | TechBro8615 wrote: | You can bind mount the socket in a volume. You can also do | this with named volumes shared between containers. You'll | need to make sure the GID/UIDs match, but it works great. | It's often faster for inter service communication than the | Docker proxy. | yrro wrote: | Quick hack for you: | | socat TCP-LISTEN:4000,fork UNIX-CONNECT:/run/yoursock | colek42 wrote: | socat is the tool for this. No need for a full blown webserver. | RedShift1 wrote: | socat 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 wrote: | Are 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 wrote: | > 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). | marcosdumay wrote: | From a quick read of the manpage, I don't think it's | possible either, unless you mess with EXEC or create | multiple listeners to a single address. | | Anyway, the Linux kernel does have a builtin loadbalancer | in the form of shared sockets that you can socat outside | of the machine. But I wouldn't call that a socat | loadbalancer. | [deleted] ___________________________________________________________________ (page generated 2021-07-24 23:00 UTC)