Fun with Unix domain sockets
simonwillison.net
simonwillison.net
Wouldn't that mess it up?
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...
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.)
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.
Remember, anything you put on localhost can be reached by your browser (unless you use iptables with the pid owner check) and arbitrary webpages you are on can hit those endpoints in the background.
The solution you are offering is worse both from a security and a usability standpoint.
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.
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...
It's reliable, and very convenient.
Unix sockets skip all of tcp though, so I'd recommend them vs loopback, if possible. I hear Linux short circuits a lot of tcp for loopback, but there's probably still a bunch of connection state that doesn't need to be there. FreeBSD runs normal tcp on loopback, and you can get packet loss if you overrun the buffer, and congestion collapse and the whole nine yards. Great for validating the tcp stack, not the best for performance; better to skip it.
This discussion [1] sheds some light on the matter, but does not fully explain the reasons for differing behaviour across OS's.
[1]: https://serverfault.com/questions/293874/why-cant-i-ping-an-...
# ping -c 1 10.10.10.10
1 packets transmitted, 0 received
# ip addr add 10.10.10.1/24 dev lo
# ping -c 1 10.10.10.10
64 bytes from 10.10.10.10: time=0.023 ms
1 packets transmitted, 1 receivedAs opposed to a normal interface where only the specific address is a local address, but the rest of the network specified are accessible through that interface.
Maybe one /8 wasn't enough addresses for you, so you added more? Doesn't seem like an unreasonable way to behave, even if it's different than BSD behavior; it certainly makes it easier to use lots of loopback addresses.
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.
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.
(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...)
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.
"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...
https://www.enricozini.org/blog/2021/debian/run-a-webserver-...
That’s one useful nugget of information! I had no idea.
0. https://gist.github.com/moderation/5d9c5352842ca068781f367a6...
It’s a Saturday and all, so yeah, I’m challenging you (for fun, not because I don’t think it’s possible).
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.
socat TCP-LISTEN:4000,fork UNIX-CONNECT:/run/yoursock
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 .
Does this mean you can send a Unix domain socket via a Unix domain socket?
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?
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?