Is it possible to expose TCP tunnel in Linux as special character device?
socat
can do do this and many other things with things resembling "streams"
Something using this basic idea should do it for you:
Machine1$ socat tcp-l:54321,reuseaddr,fork pty,link=/tmp/netchardev,waitslave
Machine2$ socat pty,link=/tmp/netchardev,waitslave tcp:machine1:54321
(adapted from Examples Page)
If you want to encrypt, you could use a variation of ssl-l:54321,reuseaddr,cert=server.pem,cafile=client.crt,fork
on machine1, and something like ssl:server-host:1443,cert=client.pem,cafile=server.crt
on machine2
(More about socat ssl)
Message-passing needs to be implemented at a higher layer; TCP does not have a notion of a message -- the TCP connections transfer streams of octets.
You can achieve something sort-of like what you request with nc
and named pipes, see man mkfifo
; or check socat
as Alex Stragies indicates.
Without a middle-layer service, the basic problems are (1) that data cannot be written to the network unless there is somebody at the other end listening for it, and (2) that TCP connections are bi-directional.
Because you cannot write data to the network unless somebody is listening for it, you must always start the listener before you can send data. (In a message passing system the process handling the messages will provide some sort of buffering.)
Your example can be easily rewritten:
First start a listener on machine2 (the destination):
nc -l 1234 | ...some processing with the received data...
In your example, this would be
nc -l 1234 | cat
This will block and wait for somebody to send some data to port 1234.
Then you can send some data from machine1 (the source):
...make up some data... | nc machine2 1234
In your example, this would be
echo "Hello" | nc machine2 1234
If you want to process the received data in some way and respond you can use the coprocessing facility of the shell. For example, this is a very simple (and very stubborn) web server:
#! /bin/bash
while :; do
coproc ncfd { nc -l 1234; }
while :; do
read line <&${ncfd[0]} || break
line="$(
echo "$line" |
LC_ALL=C tr -cd ' -~'
)"
echo >&2 "Received: \"$line\""
if [ "$line" = "" ]; then
echo >&${ncfd[1]} "HTTP/1.0 200 OK"
echo >&${ncfd[1]} "Content-Type: text/html"
echo >&${ncfd[1]} "Connection: close"
echo >&${ncfd[1]} ""
echo >&${ncfd[1]} "<title>It works!</title>"
echo >&${ncfd[1]} "<center><b>It works!</b></center>"
echo >&${ncfd[1]} "<center>-- $(date +%Y-%m-%d\ %H:%M:%S) --</center>"
break
fi
done
kill %%
sleep 0.1
done
See how the bi-directional communication is achieved between the main body of the script and the coprocess using the file descriptors in the array $ncfd
.
If you simply want to connect two computers using a basic program like nc you can redirect from/to /dev/tcp/<host>/<port>
.
These are not actual devices but a fiction created by bash, so things like cat /dev/tcp/foo/19
won't work, but cat < /dev/tcp/foo/19
will.