bash network interface

Summary

Bash provides a built-in network interface through special pseudo-files like /dev/tcp/host/port and /dev/udp/host/port, enabling direct TCP and UDP connections without external utilities such as wget or nc. This functionality is implemented within bash itself, not as a kernel-level filesystem, and allows developers to establish connections using standard redirection syntax. For instance, one can cat from /dev/tcp/time.nist.gov/13 to retrieve time data or use exec with a file descriptor to send and receive HTTP requests. The bash source code reveals that its redirection mechanism intercepts these specific patterns, parsing the host and port to initiate network communication rather than opening a physical file. This powerful feature is documented in the bash manual, highlighting its utility for scripting network interactions directly from the shell.

Some of us may have seen /dev/tcp/<host>/<port> before, is this a special file system implemented in some BSD kernel? Because there is no /dev/tcp in Linux. Actually, this one is implemented in bash. We no need to rely on wget,nc to do network connection.

It's very easy to use this interface:

bash-4.2$ cat </dev/tcp/time.nist.gov/13

56188 12-09-18 15:34:26 50 0 0 733.5 UTC(NIST) * 

bash-4.2$ exec 3<>/dev/tcp/www.w3.org/80
bash-4.2$ echo -e "GET / HTTP/1.0\n\n" >&3
bash-4.2$ cat <&3
HTTP/1.1 200 OK
Date: Tue, 18 Sep 2012 15:41:08 GMT
Server: Apache/2
Content-Location: Home.html
Vary: negotiate,accept
TCN: choice
Last-Modified: Tue, 18 Sep 2012 14:06:27 GMT
ETag: "8f75-4c9fa65657ec0;89-3f26bd17a2f00"
Accept-Ranges: bytes
Content-Length: 36725
Cache-Control: max-age=600
Expires: Tue, 18 Sep 2012 15:51:08 GMT
P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml"
Connection: close
Content-Type: text/html; charset=utf-8
...

In bash source code, we can find below codes in redir.c.

    /* A list of pattern/value pairs for filenames that the redirection
       code handles specially. */
    static STRING_INT_ALIST _redir_special_filenames[] = {
    #if !defined (HAVE_DEV_FD)
      { "/dev/fd/[0-9]*", RF_DEVFD },
    #endif
    #if !defined (HAVE_DEV_STDIN)
      { "/dev/stderr", RF_DEVSTDERR },
      { "/dev/stdin", RF_DEVSTDIN },
      { "/dev/stdout", RF_DEVSTDOUT },
    #endif
    #if defined (NETWORK_REDIRECTIONS)
      { "/dev/tcp/*/*", RF_DEVTCP },
      { "/dev/udp/*/*", RF_DEVUDP },
    #endif
      { (char *)NULL, -1 }
    };
     
    ...
    static int
    redir_open (filename, flags, mode, ri)
         char *filename;
         int flags, mode;
         enum r_instruction ri;
    {
      int fd, r;
     
      r = find_string_in_alist (filename, _redir_special_filenames, 1);
      if (r>= 0)
        return (redir_special_open (r, filename, flags, mode, ri));
     
      /* If we are in noclobber mode, you are not allowed to overwrite
         existing files.  Check before opening. */
      if (noclobber && CLOBBERING_REDIRECT (ri))
        {
          fd = noclobber_open (filename, flags, mode, ri);
          if (fd == NOCLOBBER_REDIRECT)
            return (NOCLOBBER_REDIRECT);
        }
      else
        {
          fd = open (filename, flags, mode);
    #if defined (AFS)
          if ((fd <0) && (errno == EACCES))
            {
              fd = open (filename, flags & ~O_CREAT, mode);
              errno = EACCES;       /* restore errno */
            }
    #endif /* AFS */
        }
     
      return fd;
    }

When bash finds redirection, it will first check whether the file to be redirected is a special file or not. If yes, then bash will intercept it and parse it, otherwise it will open the file. The detailed definition is in of /dev/tcp/HOST/PORT is in lib/sh/netopen.c

In bash manual, we can find these special interfaces as well:

/dev/fd/fd
If fd is a valid integer, file descriptor fd is duplicated.
/dev/stdin
File descriptor 0 is duplicated.
/dev/stdout
File descriptor 1 is duplicated.
/dev/stderr
File descriptor 2 is duplicated.
/dev/tcp/host/port
If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts
to open a TCP connection to the corresponding socket.
/dev/udp/host/port
If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts
to open a UDP connection to the corresponding socket.

Reference : http://wangcong.org/blog/archives/2099

BASH NETWORK INTERFACE /DEV/TCP

  RELATED

  COMMENTS

0

No comment for this article.