Shell – What are the Linux shells that allow network traffic management (sending/receiving data to/from `/dev/tcp/host/port`) via redirectors

io-redirectionnetworkingshell

Following this Bash tutorial, I have succeded in obtaining the code of a web page issuing simple commands by using this method:

$ exec 3<>/dev/tcp/www.google.com/80
$ echo -e "GET / HTTP/1.1\n\n" >&3
$ cat <&3

Indeed, I get the basic Google html site code:

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.es/?gfe_rd=cr&ei=HsiuVafkLpGt8weX7o-YAg
Content-Length: 258
Date: Tue, 21 Jul 2015 22:30:54 GMT
Server: GFE/2.0
Alternate-Protocol: 80:quic,p=0

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.es/?gfe_rd=cr&amp;ei=HsiuVafkLpGt8weX7o-YAg">here</A>.
</BODY></HTML>

This trick is very useful for me. For example, I have succeeded in using it to send Magic Packets (Wake on LAN) ( a similar example ) .

What shells do allow this way of sending data directly to the network by using simple commands and redirectors?
Apart from Bash, of course.

This info be used for knowing if these systems would have this capability:

  • routers with embedded Linux
  • common Android shells.
  • iOS (iPhone/iPad) shells.
  • other embedded devices running some kind of Linux (NAS, Compulab's Utilite, Odroid… etc).

Best Answer

This is a feature of ATT ksh93 that was added in bash 2.04. None of the other common shells have it, in particular you won't find it in any of the dash variants, in pdksh or mksh (as of July 2015), in any of the BusyBox or Android variants, or in zsh¹ or fish. Bash can be compiled without this feature (see --enable-net-redirections), so it may be absent from embedded devices, even if they have bash.

To test whether the feature is present, you can check the error message when trying to open a TCP port for the discard service: both bash and ksh say “Connection refused” (or the command returns immediately if you have a discard service on your local machine), which you wouldn't see if this doesn't attempt to make some network connection.

: </dev/tcp/127.0.0.1/9

One reason this isn't a common feature is that a lot of network protocols require two-way communication with careful handling of who talks when, which shells aren't very convenient for. Another reason is that for the simple cases, pipes involving netcat, socat or socket also work. These programs handle binary data and can be servers as well as clients. Most protocols that can be handled in a simple way have specialized tools, wake-on-LAN excepted.

echo -e "GET / HTTP/1.1\n\n" | nc www.google.com 80

echo -e "GET / HTTP/1.1\n\n" | socat - TCP:www.google.com:80

(socket doesn't really work as a HTTP client since it doesn't close its write of the connection on the end of input.)

For scripting:

case $(export LANGUAGE=C LC_ALL=C; { : </dev/tcp/127.0.0.1/9; } 2>&1) in
  ""|*"Connection refused"*) echo "/dev/tcp is present";;
  *)
    if type nc >/dev/null 2>/dev/null; then
      echo "netcat is present"
    elif type socat >/dev/null 2>/dev/null; then
      echo "socat is present"
    else
      echo "I can't do TCP"
    fi
esac

¹ Zsh has a different way of using UDP and TCP sockets.

Related Question