Admin-Ahead Community

Linux => General Linux => Topic started by: akhilt on April 12, 2018, 12:31:10 am

Title: How to open a TCP/UDP socket in a bash shell
Post by: akhilt on April 12, 2018, 12:31:10 am
How to open a TCP/UDP socket in a bash shell

Open or Close a TCP/UDP Socket in Bash Shell

In a nutshell, you can open a TCP/UDP socket using the following syntax in the bash shell.

Code: [Select]
$ exec {file-descriptor}<>/dev/{protocol}/{host}/{port}
The "file descriptor" is a unique non-negative integer associated with each socket. File descriptors 0, 1 and 2 are reserved for stdin, stdout and stderr, respectively. Thus you must specify 3 or higher (whichever is unused) as a file descriptor.

"<>" implies that the socket is open for both reading and writing. Depending on your need, you can open a socket for read-only (<) or write-onlyTCP).

The "protocol" field can be either TCP or UDP. The "host" and "port" fields are self-explanatory.

For example, to open a bi-directional TCP socket for a domain with HTTP port and file descriptor 3:

Code: [Select]
$ exec 3<>/dev/tcp/domainname/80
Once opened, a read/write socket can be closed using the following syntax. The first command close an input connection, while the latter closes an output connection.

Code: [Select]
$ exec {file-descriptor}<&-
$ exec {file-descriptor}>&-

Read from or Write to a TCP/UDP Socket in Bash Shell

Once a socket is opened, you can write a message to or read a message from the socket.

To write a message stored in $MESSSAGE to a socket:

Code: [Select]
$ echo -ne $MESSAGE >&3
$ printf $MESSAGE >&3

To read a message from a socket and store it in $MESSAGE:

Code: [Select]
$ read -r -u -n $MESSAGE <&3
$ MESSAGE=$(dd bs=$NUM_BYTES count=$COUNT <&3 2> /dev/null)

TCP/UDP Socket Examples in Bash Shell

Here I present several shell script examples that open and use a TCP socket.

1. Fetch a remote web page and print its content
Code: [Select]
#!/bin/bash
exec 3<>/dev/tcp/domainname/80
echo -e "GET / HTTP/1.1\r\nhost: domainname\r\nConnection: close\r\n\r\n" >&3
cat <&3

2. Display a remote SSH server version
Code: [Select]
#!/bin/bash
exec 3</dev/tcp/192.168.0.10/22
timeout 1 cat <&3

In fact, the above script can be shortened to the following one-liner:

Code: [Select]
#!/bin/bash
timeout 1 cat </dev/tcp/192.168.0.10/22

3. Display the current time from nist.gov
Code: [Select]
#!/bin/bash
cat </dev/tcp/time.nist.gov/13

4. Check the Internet connectivity
Code: [Select]
#!/bin/bash
 
HOST=hostname
PORT=80
 
(echo >/dev/tcp/${HOST}/${PORT}) &>/dev/null
if [ $? -eq 0 ]; then
    echo "Connection successful"
else
    echo "Connection unsuccessful"
fi

5. Perform TCP port scanning against a remote host
Code: [Select]
#!/bin/bash
host=$1
port_first=1
port_last=65535
for ((port=$port_first; port<=$port_last; port++))
do
  (echo >/dev/tcp/$host/$port) >/dev/null 2>&1 && echo "$port open"
done

Final Notes

Opening a socket in bash requires that the bash shell have net-redirections enabled (i.e., compiled with "--enable-net-redirections"). Old distributions may have this feature disabled for bash, in which case you will encounter the following error:
Code: [Select]
/dev/tcp/domainname/80: No such file or directoryBesides bash, socket support is known to be available in other shells such as ksh or zsh.