When executing a command on a /dev/tcp/$host/$port
pseudo-device, Bash
opens a TCP connection to the associated socket.
Exemple using TCP
$ cat </dev/tcp/nist1.symmetricom.com/13
54496 08-01-31 02:30:53 00 0 3 345.7 UTC(NIST) *
Exemple using UDP
$ exec 4<>/dev/udp/172.16.2.200/7 # new file descriptor
$ echo -e "Networking with bash" >&4 && head -1 <&4
Networking with bash
$ exec 4>&- # closing file descriptor '4'
In this example I open a datagram UDP
connection to my home server
172.16.2.200
on the echo service port 7
. The file descriptor is
open in read/write mode.
An almost useful program
This is an example of a small stripped down version of wget
(yes very
stripped down) written in bash.
The line exec 6<>/dev/tcp/$1/80
opens a socket in read write
mode. Since we are using HTTP protocol 1.1 we need to pass the host
name in the header with the line Host: $1
. Also by default HTTP
version 1.1 keeps all the connections alive unless specified
otherwise. The line Connection: close
tells the http server to close
the connection once the response has been sent. I we forget this line
the script will stay connected until the server times out.
#!/bin/bash
#
PATH=${2-/}
exec 6<>/dev/tcp/$1/80
echo -e "GET ${PATH} HTTP/1.1" >&6
echo -e "Host: $1\nConnection: close\n" >&6
echo "Reading: http://${1}${PATH}" >&2
#read and discard the header
while read <&6
do
LINE=${REPLY//$'\r'/}
if [ -z "$LINE" ]; then
break
fi
done
#read the page
while read <&6
do
echo -n $REPLY >&1
done
# close the file descriptor
exec 6<&-
This program takes two arguments, the server name and the path to the file to download.
$ ./wget.sh www.google.com '/search?q=bsd' > ~/result.html
Reading: http://www.google.com/search?q=bsd
$
There is one caveat though. The version of bash you are using needs to
be compiled with the flag --enable-net-redirections
. This code should
work on Mac, *BSD and most of the linux distributions (some Debian by
default use a version of bash without net redirection).