43

Assume a legacy Linux application listening on a UNIX domain socket /tmp/foo.

In addition to communicating with this legacy application over the UNIX domain socket mechanism I want to be able to connect to it via a TCP-connection on port say 1234.

What is the easiest way to bind to TCP port 1234 and then redirect all incoming connections to the UNIX domain socket /tmp/foo?

0

5 Answers 5

67

Turns out socat can be used to achieve this:

socat TCP-LISTEN:1234,reuseaddr,fork UNIX-CLIENT:/tmp/foo

And with a bit of added security:

socat TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,su=nobody,range=127.0.0.0/8 UNIX-CLIENT:/tmp/foo

These examples have been tested and work as expected.

Sign up to request clarification or add additional context in comments.

7 Comments

socat, netcat, either way. You could even wrap stunnel around it for more layers of complexity!
If anybody wants to use that to share docker socket, he should remove su=nobody part
To share the docker socket, simply tell the Docker daemon to listen to a local port by passing -H tcp://127.0.0.1:4321 (note that it allows access to the docker daemon for anyone that can open a connection to 127.0.0.1. No uid/gid checks or anything, but that is also true for the netcat/socat approach)
@swordofpain Do you know how to do that with Docker for Mac? I have "Automatically start Docker when you log in" enabled, and there does not seem to be an option in preferences to listen on a socket instead of the Unix socket.
AFAIK, Docker for Mac virtualizes a linux kernel that does the container stuff. OSX's kernel isn't involved, really. That means that the docker daemon is running inside the VM, and that the configuration must be done there. Though probably whatever frontend they supply probably already talks to the daemon through the API, meaning that there already should be a listening socket for that. The main difference would be that it won't be listening on localhost, but on the virtual network interface of the VM, of which you would have to find the IP address. Hope this helps.
|
24

Easiest? Probably Netcat (aka nc):

nc -l 1234 | nc -U /tmp/foo

The first command listens on port 1234 for incoming connections, and pipes the resulting data to the second command. The second connects to the Unix domain socket /tmp/foo, and writes its input to that socket. Note that this will only accept a single connection, and exit as soon as that connection is dropped. If you want to keep listening for more connections, use the -k option:

nc -lk 1234 | nc -U /tmp/foo

You can test that this is working by setting up a listener for that socket in one terminal:

nc -lUk /tmp/foo

And writing to it in another:

nc localhost 1234

socat, as recommended by knorv, is more capable, but more complicated to use.

5 Comments

seems like nc under ubuntu (quantal) doesn't support unix sockets :(
@gucki Really? You don't have the nc -U option? I don't have a Quantal machine to test on, but on Precise nc has the -U option, and what I said in my comment works fine. Have you tried exactly what I wrote? If you aren't finding that nc works for you, I would recommend trying socat; it can do a lot more than nc, with much finer grained control of how it works, but it is a bit more complicated to figure out how to use.
Yes, I just tested again (netcat 1.10-40): nc -l 1234 | nc -U /tmp/foo gives nc: invalid option -- 'U' and nc -h for help. socat works fine :)
@gucki Looks like there are two nc packages on Ubuntu. netcat-traditional and netcat-openbsd. netcat-openbsd is the one I have installed, and seems to have more features than netcat-traditional. You can install them both at once, with nc and netcat symlinked to one or the other.
The problem with this approach is that the resulting pipeline is unidirectional. If we expect a response from the process listening on the unix-domain socket, the only way to communicate it via a TCP socket is socat which will forward the response back to us.
3

You should be able to bind to TCP 1234, get a socket fd for /tmp/foo and use the select call to 'listen' for data on both 1234, and /tmp/foo. Any data written to 1234, you rewrite to /tmp/foo and vice-versa.

You now act as a proxy and transfer data back and forth.

And here is a web-page which might help: http://osr507doc.sco.com/en/netguide/dusockC.io_multiplexing.html

Comments

1

In additons to @knorv's answer: with xinetd it can work like a daemon

# cat /etc/xined.d/mysrv
service mysrv
{
 disable = no
 type = UNLISTED
 socket_type = stream
 protocol = tcp
 wait = no
 server = /usr/bin/socat
 server_args = STDIN UNIX-CLIENT:/tmp/mysocket.sock
 bind = 127.0.0.1
 port = 1234
}

Comments

0

Not tried it : but it looks like 'lighttpd' can do this for you:

http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore

2 Comments

Unfortunately lighttpd is massive overkill for what the poster wants.
Does this really work for arbitrary TCP and not only for HTTP?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.