I recently read instructions that surprised me. Paraphrased:
You can send messages over UDP:
echo -n "message" | nc -4u -w0 localhost 1738
Or if you use bash, you might prefer this instead:
bash -c 'echo -n "message" > /dev/udp/localhost/1738'
/dev/udp
?
That doesn’t look bash-specific.
How did I miss that that was available as a device on Unix?
Wait a second…
$ echo -n message > /dev/udp/localhost/1738
zsh: no such file or directory: /dev/udp/localhost/1738
No, this is truly a bash feature, not a generic shell one. In fact, UDP in particular seems to be completely unique to bash — zsh has a module that provides TCP networking, but no similar module for UDP networking.
It seems almost perverse.
There is no /dev/udp
directory (or device) at all in the filesystem,
bash just intercepts any attempt to redirect to it and does networking stuff transparently.
Although maybe it’s not perverse and redirection is just weirder than I thought it was.
From the previously linked bash manual:
Bash handles several filenames specially when they are used in redirections, as described in the following table. If the operating system on which Bash is running provides these special files, bash will use them; otherwise it will emulate them internally with the behavior described below.
The table lists more than just networking:
aside from /dev/udp/HOST/PORT
and /dev/tcp/HOST/PORT
, it includes
/dev/fd/FD
, /dev/stdin
, /dev/stdout
, and /dev/stderr
.
This lead me to realize that these too are not POSIX!
The string /dev/fd
doesn’t exist
at all in the
online POSIX documentation,
and the others are specifically
called out
as extensions:
The system may provide non-standard extensions. These are features not required by POSIX.1-2017 and may include, but are not limited to: … Additional character special files with special properties (for example, /dev/stdin, /dev/stdout, and /dev/stderr)
At least on my macOS desktop,
the /dev/std*
and /dev/fd/*
devices to actually exist,
so bash wouldn’t do anything special for redirection to those paths.
But even the ancient bash from 2007 (!) that ships with macOS will happily talk to the special networking “device” paths.
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin24)
Copyright (C) 2007 Free Software Foundation, Inc.
$ /bin/bash -c 'echo -n message > /dev/udp/localhost/1738'
$ echo $?
0
Prescriptions
Being a POSIX sh purist, I can’t endorse this for lay shell scripting, but it seems really interesting as a tool for fixing very broken systems, bootstrapping very barebones systems, and penetration testing.