218

I have a script that is to be run by a person that logs in to the server with SSH.

Is there a way to find out automatically what IP address the user is connecting from?

Of course, I could ask the user (it is a tool for programmers, so no problem with that), but it would be cooler if I just found out.

dfeuer
  • 48,079
  • 5
  • 63
  • 167
flybywire
  • 261,858
  • 191
  • 397
  • 503

19 Answers19

344

Check if there is an environment variable called:

$SSH_CLIENT 

OR

$SSH_CONNECTION

(or any other environment variables) which gets set when the user logs in. Then process it using the user login script.

Extract the IP:

$ echo $SSH_CLIENT | awk '{ print $1}'
1.2.3.4
$ echo $SSH_CONNECTION | awk '{print $1}'
1.2.3.4
cweiske
  • 30,033
  • 14
  • 133
  • 194
nolim1t
  • 4,051
  • 1
  • 17
  • 7
  • @cwd i want to replace the ip in this command "iptables -A INPUT -s 93.203.118.251 -p tcp --destination-port 443 -j DROP" is that possible? – wutzebaer Aug 05 '15 at 13:00
  • 2
    This was REMOTEHOST for me. – dramzy Jul 07 '16 at 19:57
  • 5
    only works with non-sudoed users. e.g. if you have an ssh user and then escalate to root, a new shell is created and these variables are lost, unless you can trace back through the tree to find the original ssh pid and get the variables from /proc/$PID/environ – Andrej Jun 01 '17 at 15:24
  • 10
    thanks to https://stackoverflow.com/questions/428109/extract-substring-in-bash this answer can be improved to simply `${SSH_CLIENT%% *}` – Jeff Apr 19 '18 at 16:32
  • 2
    @Andrej look into `sudo -E` – Jeff Apr 19 '18 at 16:37
  • Had to use echo $SSH_CONNECTION | awk '{print $3}' – Alok Prasad Aug 12 '20 at 16:19
  • This is my go to for finding all env vars with a certain substring `env | grep SSH | sort` – Everett Toews Dec 06 '20 at 22:55
  • Sometimes, it won't work if there was a network reconnection and IP address changed, but an actual SSH session stayed alive, for example. It may return a previous(old) IP address. Consider trying using `who` instead. – Artfaith Apr 07 '21 at 21:10
128

You could use the command:

server:~# pinky

that will give to you somehting like this:

Login      Name                 TTY    Idle   When                 Where 

root       root                 pts/0         2009-06-15 13:41     192.168.1.133
Vinicius
  • 1,835
  • 2
  • 13
  • 15
41

Try the following to get just the IP address:

who am i|awk '{ print $5}'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
AlexP
  • 419
  • 4
  • 2
  • pretty sure if you write whoami and you will get the name of the logged in user. there's no fifth thing or ip to print sorry. but whoami is a useful command – gerard Nov 04 '13 at 16:06
  • 19
    `who am i` != `whoami` on my Linux at least. There is a fifth thing, and it is the host name of the client. – kbulgrien Jan 27 '14 at 15:48
  • 8
    For anyone else wondering about `who am i`: The manpage for `who` says: `If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.`. So really anything with two words works, also things like `who likes icecream`. – jmiserez Oct 30 '15 at 14:15
  • 4
    Building on this answer, I reduced it to `who -m --ips|awk '{print $5}'` so that I had only IP and no reverse-dns answer. Thanks for the help on `who am i`! – Yvan Aug 14 '17 at 20:23
  • Some output may look like `admin pts/0 Sep 30 13:20 1.1.1.1`, so this better be date-format-independent – ᴍᴇʜᴏᴠ Sep 30 '19 at 13:39
  • 2
    Fails with tmux: `who am i|awk '{ print $5}'` `(tmux(2445).%3)` – Alexx Roche Oct 25 '19 at 12:29
22

Just type the following command on your Linux machine:

who
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bangar
  • 221
  • 2
  • 2
13
 who | cut -d"(" -f2 |cut -d")" -f1
danilo
  • 139
  • 1
  • 5
6

Improving on a prior answer. Gives ip address instead of hostname. --ips not available on OS X.

who am i --ips|awk '{print $5}' #ubuntu 14

more universal, change $5 to $6 for OS X 10.11:

WORKSTATION=`who -m|awk '{print $5}'|sed 's/[()]//g'`
WORKSTATION_IP=`dig +short $WORKSTATION`
if [[ -z "$WORKSTATION_IP" ]]; then WORKSTATION_IP="$WORKSTATION"; fi
echo $WORKSTATION_IP
SeeBenClick
  • 111
  • 1
  • 6
5
who am i | awk '{print $5}' | sed 's/[()]//g' | cut -f1 -d "." | sed 's/-/./g'


export DISPLAY=`who am i | awk '{print $5}' | sed 's/[()]//g' | cut -f1 -d "." | sed 's/-/./g'`:0.0

I use this to determine my DISPLAY variable for the session when logging in via ssh and need to display remote X.

Spindrift
  • 59
  • 1
  • 4
  • Useful one liner to add my IP to .htaccess files. Thank you. I've made a modification for FreeBSD: `who am i | awk '{print $6}' | sed 's/[()]//g' | sed 's/\./\\./g'` The last part escapes the dots. – Olivier - interfaSys Aug 12 '14 at 20:59
4
netstat -tapen | grep ssh | awk '{ print $4}'
4

A simple command to get a list of recent users logged in to the machine is last. This is ordered most recent first, so last | head -n 1 will show the last login. This may not be the currently logged in user though.

Sample output:

root     pts/0        192.168.243.99   Mon Jun  7 15:07   still logged in   
admin    pts/0        192.168.243.17   Mon Jun  7 15:06 - 15:07  (00:00)    
root     pts/0        192.168.243.99   Mon Jun  7 15:02 - 15:06  (00:03)    
root     pts/0        192.168.243.99   Mon Jun  7 15:01 - 15:02  (00:00)    
root     pts/0        192.168.243.99   Mon Jun  7 13:45 - 14:12  (00:27)    
root     pts/0        192.168.243.99   Mon May 31 11:20 - 12:35  (01:15)    
...
miken32
  • 42,008
  • 16
  • 111
  • 154
Nikhil Katre
  • 2,114
  • 23
  • 22
2

You can get it in a programmatic way via an SSH library (https://code.google.com/p/sshxcute)

public static String getIpAddress() throws TaskExecFailException{
    ConnBean cb = new ConnBean(host, username, password);
    SSHExec ssh = SSHExec.getInstance(cb);
    ssh.connect();
    CustomTask sampleTask = new ExecCommand("echo \"${SSH_CLIENT%% *}\"");
    String Result = ssh.exec(sampleTask).sysout;
    ssh.disconnect();   
    return Result;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
vineetv2821993
  • 927
  • 12
  • 25
2

an older thread with a lot of answers, but none are quite what i was looking for, so i'm contributing mine:

sshpid=$$
sshloop=0
while [ "$sshloop" = "0" ]; do
        if [ "$(strings /proc/${sshpid}/environ | grep ^SSH_CLIENT)" ];
then
                read sshClientIP sshClientSport sshClientDport <<< $(strings /proc/${sshpid}/environ | grep ^SSH_CLIENT | cut -d= -f2)
                sshloop=1
        else
                sshpid=$(cat /proc/${sshpid}/status | grep PPid | awk '{print $2}')
                [ "$sshpid" = "0" ] && sshClientIP="localhost" && sshloop=1
        fi
done

this method is compatible with direct ssh, sudoed users, and screen sessions. it will trail up through the process tree until it finds a pid with the SSH_CLIENT variable, then record its IP as $sshClientIP. if it gets too far up the tree, it will record the IP as 'localhost' and leave the loop.

Andrej
  • 180
  • 1
  • 2
  • 10
2

I'm getting the following output from who -m --ips on Debian 10:

root pts/0 Dec 4 06:45 123.123.123.123

Looks like a new column was added, so {print $5} or "take 5th column" attempts don't work anymore.

Try this:

who -m --ips | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}'

Source:

ᴍᴇʜᴏᴠ
  • 4,804
  • 4
  • 44
  • 57
1
netstat -tapen | grep ssh | awk '{ print $10}'

Output:

two # in my experiment

netstat -tapen | grep ssh | awk '{ print $4}' 

gives the IP address.

Output:

127.0.0.1:22 # in my experiment

But the results are mixed with other users and stuff. It needs more work.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gerard
  • 179
  • 5
  • my netstat only gives a truncated address for IPv6 and "127.0.0.1:22" is the server rather than the client, (which was specified in the question.) – Alexx Roche Oct 25 '19 at 12:39
0

Assuming he opens an interactive session (that is, allocates a pseudo terminal) and you have access to stdin, you can call an ioctl on that device to get the device number (/dev/pts/4711) and try to find that one in /var/run/utmp (where there will also be the username and the IP address the connection originated from).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mihi
  • 6,507
  • 1
  • 38
  • 48
-1

Linux: who am i | awk '{print $5}' | sed 's/[()]//g'

AIX: who am i | awk '{print $6}' | sed 's/[()]//g'

pfrandsen
  • 47
  • 3
-1

Search for SSH connections for "myusername" account;

Take first result string;

Take 5th column;

Split by ":" and return 1st part (port number don't needed, we want just IP):

netstat -tapen | grep "sshd: myusername" | head -n1 | awk '{split($5, a, ":"); print a[1]}'


Another way:

who am i | awk '{l = length($5) - 2; print substr($5, 2, l)}'

Nex
  • 361
  • 3
  • 10
  • `sudo ss -tapen | grep "sshd: $(whoami)"|head -n1|awk '{split($5, a, ":"); print a[1]}'` says my ssh client is from `2a02` and your "Another way:" says `tmux(2445).%3` – Alexx Roche Oct 25 '19 at 12:45
-1

One thumb up for @Nikhil Katre's answer :

Simplest command to get the last 10 users logged in to the machine is last|head.

To get all the users simply use last command

The one using who or pinky did what is basically asked. But But But they don't give historical sessions info.

Which might also be interesting if you want to know someone who has just logged in and logged out already when you start this checking.

if it is a multiuser system. I recommand add the user account you are looking for:

last | grep $USER | head

EDIT:

In my case, both $SSH_CLIENT and $SSH_CONNECTION do not exist.

Community
  • 1
  • 1
Kangqiao Zhao
  • 111
  • 1
  • 8
-1

netstat will work (at the top something like this) tcp 0 0 10.x.xx.xx:ssh someipaddress.or.domainame:9379 ESTABLISHED

aric
  • 17
  • 1
-1

Usually there is a log entry in /var/log/messages (or similar, depending on your OS) which you could grep with the username.

Daniel Schneller
  • 13,728
  • 5
  • 43
  • 72