Does this site look plain?

This site uses advanced css techniques

We've periodically had the need to find a current user's remote IP address when logged into a UNIX/Linux system, and have been surprised that this is not nearly so easy as it looks on some platforms. Though the information is typically stored in the /etc/utmpx file (maintained by the login or init processes), it's not always exposed to the user in an obvious way.

Table of Contents
  1. Download & Build
  2. Locating the remote host
  3. The Secure Shell Shortcut
  4. Command-Line Options

The need for this varies, but the one that prompted this program was a desire to set a proper default printer for a very large (hundreds of users) UNIX installation with users all over the country. They all logged in via telnet to use a line-of-business application, and by finding the remote hostname or IP, we could make some pretty good guesses about which printers should the various routine business documented produced (invoices, pick tickets, etc.).

So we wrote one.

Giving a tip of the hat to the whoami program, we've called this whoamip, and it reports the hostname or IP of the remotely-connected session if this is available.

$ whoamip
linux.unixwiz.net

This is done on a best-effort basis and is not strictly deterministic, but for the most common cases (for instance, examining the remote hostname or IP out of /etc/profile), it's tolerably reliable.

Download and Build

This tool is published in the form of portable C source code, and it can be compiled on any Linux/UNIX platform that provides a development environment.

Download the code from here:

$ cc whoamip.c -o whoamip
$ sudo cp whoamip /usr/local/bin/

Now we'll find whoamip in the usual place: /usr/local/bin/.

This is a UNIX/Linux application only: It cannot run on Windows. Not ever.

It also doesn't build on BSD because it doesn't support utmpx in the same way (it seems to have the hostname, but no library functions for accessing the data files). We may look into this someday.

Locating the remote host

Finding the IP address of a user with a shell session is more difficult than it seems: though a program with a direct network connection can call the getpeername() system call to obtain the IP address directly via the file descriptor (which is a socket handle).

But a shell session doesn't have a direct network connection. Instead, it goes through a pseudo-tty to make the user's shell "look" like a real serial terminal session (with full stty support) rather than a naked pipe, but this insulates us from the real network socket and makes it unavailable to us.

It's likely possible to somehow dig into the kernel and track this down (perhaps via looking at the network connections of the shell's parent process), but this is highly unportable and probably a lot of work.

Fortunately, we're left with an indirect method: the init and login programs cooperate to maintain this information in the utmpx file. This is the database that the who command uses to identify the currently logged-on users, and on many platforms this session information includes the remote host.

The information in the utmpx.ut_host field is stored as a string, and this is either an IP address or a hostname depending on what the init program chooses. This program has no control over the format of this string and must live with whatever it gives us.

We suspect that the format is governed by the state of local inverse DNS resolution, but that's outside the scope of this tool.

The Secure Shell Shortcut

Though users of telnet sessions have to go through all the above procedures to locate the remote host, users of secure shell sessions have a shortcut which this program takes advantage of.

The SSH daemon sets several environment variables, and one of them includes the remote host's IP address directly: this is SSH_CLIENT.

$ echo $SSH_CLIENT
172.27.217.9 1324 22

This includes the IP address and remote TCP port, plus the local TCP port, but we only care about the first token in this string.

If it's present we return it directly, and short-circuit the utmpx process.

Command-Line Options

whoamip has very little need for command line parameters, so we support only a few:

-V
Report the program's version information onto the standard error stream, then exit with success status.
-S
Disable any attempt to use the $SSH_CLIENT environment variable, and use the ordinary utmpx process.

We'll note that in the process of discovering the current session's tty name requires a file descriptor, and this tool uses the standard input for this. If the standard input is not attached to the user's pseudo-tty, it will not be able to find the associated utmpx record, and therefor won't find the remote host.


First published: 2006/07/31 (Blogged)