C/C++ new tool: remusock -- remote Unix socket access

Zirias

Aspiring Daemon

Reaction score: 462
Messages: 961

I think I finished my new tool, the one that caused me to ask about O_NONBLOCK behavior with Unix sockets recently :) Although the usecase is very specific, I'll still announce it here just in case anyone could need something similar.

What it does is pretty simple: It provides access to a Unix socket on a remote machine. For that, you have to run two instances of it, on both machines. One will act as a client to a Unix socket, one will provide a Unix socket and listen on it. The instances are connected via a single TCP connection, and it's your choice in which direction this connection is made. In case the TCP server instance is the Unix socket client instance, you can have multiple instances on different machines acting as Unix socket servers and connect all to this instance, to provide the same Unix socket to multiple machines. For obvious reasons, this isn't possible when the TCP connection is made in the opposite direction.

Code:

Features:
  • All Unix socket connections between two instances are tunneled through a single TCP connection
  • You can specify owner uid/gid and mode of a socket you're providing
  • When started as root, it will run as the given socket owner (drop privileges)
  • Idle TCP connections are "pinged" from time to time and disconnected if unresponsive
  • The TCP client end will try to re-establish a lost connection from time to time
Portability:
  • Should work on any modern POSIX system, confirmed on FreeBSD and Linux
  • In particular, it needs pselect() and the netdb functions getaddrinfo() and getnameinfo()
  • Won't work on Windows as it uses some POSIX functions that don't exist there and also expects Unix semantics for local sockets (e.g. that they can be unlink()ed)
Only my own scenario (the socket server also acting as the TCP server, with one other instance connecting to it) is thoroughly tested in a "production" environment. So, bug reports welcome :)

In this first version, there's neither TLS nor any form of authentication. The simple reason is: I don't need it, I use this over a VPN. So, here's also a question: Would anyone have a usecase for such a tool using a public network, IOW, would it make sense to add TLS and authentication?
 
OP
Zirias

Zirias

Aspiring Daemon

Reaction score: 462
Messages: 961

In case anyone's interested in the source, you might wonder about one or another thing...
  • Despite being written in C, it follows a (simple) OOP design. That means for anything that isn't a singleton, it (almost) always uses dynamic memory allocations, which translates to using the "heap" on any system I know. This might have a little performance impact indeed, but IMHO, it's much easier to get your logic correct that way.
  • The API for connections, clients and servers might look a bit more complex than it would have to be. There's a "readOffset" parameter. I did this to avoid any buffer copies while tunnelling. My simple tunnel protocol needs to prepend metadata (client number and message length) to anything forwarded on the TCP connection, and if there's space reserved for it in the buffer, there's no need for copying.
  • There's a simple threadpool included, which seems unnecessary for a simple service using pselect(). The reason to introduce it was logging via syslog. Unfortunately, (local) syslog can block indefinitely in theory, and there is no "async" API to use instead. So, to "fake" async in your own program, you need threads. Once this threadpool was there anyways, I reused it to allow hostname lookups for remote connections with getnameinfo(), which could also block indefinitely.
 

kpedersen

Daemon

Reaction score: 848
Messages: 1,844

I like it. We have a gpu debug tool that listens on a UNIX socket, I wonder if I can use this in order to access that tool from within a VM. Since it is over standard TCP, I don't see why not.
 
OP
Zirias

Zirias

Aspiring Daemon

Reaction score: 462
Messages: 961

Glad to see there might indeed be a usecase other than mine ;) Please let me know whether it works :)
 

mjollnir

Aspiring Daemon

Reaction score: 334
Messages: 749

Now you see: you're one of those developers to be glad to realize others like and use your work ;)
 
OP
Zirias

Zirias

Aspiring Daemon

Reaction score: 462
Messages: 961

I never told otherwise ;) Still, this is a prime example for a tool I wrote cause I had a need myself! So if anyone would like it to do something that doesn't sound useful to me at all, I guess my motivation to do it would be pretty small ;)
 

leebrown66

Well-Known Member

Reaction score: 145
Messages: 427

Out of curiosity, did you look at socat? I've not used it like your needs, but it should be capable of the same thing. I used it to provide a listen queue for a script, which would otherwise drop multiple connection attempts, it's pretty versatile.
 
OP
Zirias

Zirias

Aspiring Daemon

Reaction score: 462
Messages: 961

leebrown66 socat was suggested to me on some IRC channel, after I started implementing this because I could sort out netcat, which definitely didn't fit the bill. I then looked at the socat manpage and it seemed to be a good alternative indeed. It had a minor weakness for my usecase, as it would require the TCP connection to go in the same direction as the Unix socket connections I want to tunnel. Of course, this would have been acceptable. What I couldn't figure out just reading the manpage was whether socat would forward multiple concurrent connections correctly. Maybe it would, but I decided to continue what I already started :)

In the end, my tool matches my personal usecase better: I can connect from my internal host (which provides the Unix socket) to my external host (which has clients needing that socket), and I don't have to worry about loss of the VPN connection because my tool automatically reconnects on TCP. But, of course, it's quite possible I could have come to an "almost as good" solution using just socat and some scripting, which would have taken a fraction of the time :)
 
Top