3

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).
  • 1
    "sending data directly to the network card" — after I saw this phrasing repeatedly in a few of your recent posts, I feel the need to correct it. It's not sending anything directly to any network card. It's just sending packets to the network stack in the usual way. Whether or not they go to network cards and if so which ones depends on the usual routing function. – Celada Jul 22 '15 at 14:42
  • You are right, @Celada. Even when having more than one NIC, the command is the same. I have changed it to a simpler "directly to network". Thanks you. – Sopalajo de Arrierez Jul 22 '15 at 15:02
8

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.

| improve this answer | |
  • 2
    Debian configured Bash with --disable-net-redirections some time ago. I like a discussion: bash: PATCH support TCP/UDP service names, bash: net redirections doesn't work, bash: /dev/tcp should be enabled by default. "This kind of feature should not be part of a shell but a special. tool. And that tool has existed for years already, it's called netcat.":) – Evgeny Vereshchagin Jul 22 '15 at 11:27
  • 1
    Is there any way to know if this feature is included in a shell? Apart from trying to do something like echo -e "\xff">/dev/udp/255.255.255.255/4000 . Maybe some kernel flag? – Sopalajo de Arrierez Jul 22 '15 at 12:43
  • for Bash you can check these strings: /dev/tcp/, /dev/udp/. i.e. strings path/to/bash | grep -E '/dev/(tcp|udp)/' – Evgeny Vereshchagin Jul 22 '15 at 14:00
  • 3
    @SopalajodeArrierez No kernel flag since this has nothing to do with the kernel. I don't think there's a convenient way. Bash for example doesn't set a variable to indicate this. You can run something like : </dev/tcp/localhost/99999 and see what error message you get (“Connection refused” if the feature is supported, “No such file or directory” if it isn't). – Gilles 'SO- stop being evil' Jul 22 '15 at 14:16
  • @SopalajodeArrierez, use a @Gilles's solution. Strings method is unreliable:) Bash can be configured with --enable-net-redirections but /dev/(tcp|udp)/host/port not supported without networking – Evgeny Vereshchagin Jul 22 '15 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.