Skip to content
Advertisement

In Python, how do I get user’s remote IP (their last hop) if they’re connected over SSH?

I want to detect if the user is connected over SSH. In a term, the “env” command shows SSH_CONNECTION line. Accessed in Python in one of two ways:

#python:
import os
print os.getenv("SSH_CONNECTION")       #works
print os.environ.get("SSH_CONNECTION")  #works

But, if the user has ran my program using SUDO (as they will need to), env$ dooesn’t show SSH_CONNECTION. So Python can’t see it:

#sudo python:
import os
print os.getenv("SSH_CONNECTION")       #not set
print os.environ.get("SSH_CONNECTION")  #not set

The aim is to achieve the following:

#Detect if user is over remote IP
lRemoteIP=""                                     #Is set if user on SSH
lStr=os.environ.get("SSH_CONNECTION")            #Temp var
if lStr: lRemoteIP=lStr.split()[0].split("=")[1] #Store user's lasthop IP

#Later on in the code, for multiple purposes:
if lRemoteIP: pass #Do stuff (or not) depending on if they're on SSH

How do I retrieve SSH_CONNECTION environment variable under SUDO, when its not present in env$ ?

Or more precisely: how can I detect if the current session is via SSH when sudo?

I’m not a natural at Linuxy-type things, so be gentle with me…

[EDIT:] METHOD 2: Giving up on env$, I’ve tried the following:

pstree -ps $$ | grep "sshd("

If it returns anything then it means that the SSH daemon sits above the session. Ergo, it’s a SSH connection. And the results are showing me the PIDs of the SSH daemons. Results of the pstree cmd:

init(1)---sshd(xxx)---sshd(xxx)---sshd(xxx)---bash(xxx)-+-grep(xxx)

But I’m struggling to get a src IP from the PID. Any ideas on this avenue?

[EDIT] METHOD 3: /run/utmp contains details of SSH logins. In python:

import os
import sys

lStr=open("/var/run/utmp").read().replace('x00','') #Remove all those null values which make things hard to read

#Get the pseudo-session ID (pts) minus the /dev/ that it starts with:
lCurSess=os.ttyname(sys.stdout.fileno()).replace('/dev/','')
#Answer is like pts/10  (pseudo-term session number 10)
#Search lStr for pts/10
lInt=lStr.find(lCurSess.replace('/dev/',''))
#Print /var/utmp starting with where it first mentions current pts:
print lStr[lInt:]

So far, so good. This gives the following results (I’ve changed the IP and username to USERNAME)

pts/10/10USERNAMEx9ex958Ymxb2x05x0 74x14pts/10s/10USERNAME192.168.1.1xbfx958Yxf8xa3rxc0xa88x01

So, when it comes to extracting the IP from the file, there’s some bumf inbetween the occurances of pts/10 and the IP. What’s the best way to parse it, given that (I reckon) the precise distance from the match to the IP will be different under different circumstances?

Advertisement

Answer

GOT IT AT LAST!!!

The “last” command has list of users and their IPs!! So simple.

It has “still logged in” marked against sessions. Filter by these And then filter by current pts ID

To get the IP for the current SSH session in Python, do this:

import os,sys,subprocess
(out, err) = subprocess.Popen(['last | grep "still logged in" | grep "' + os.ttyname(sys.stdout.fileno()).replace('/dev/','') + '"'], stdout=subprocess.PIPE, shell=True).communicate()
RemoteIP=out.split()[2].replace(":0.0","") #Returns "" if not SSH

For readability, across multiple lines:

import os,sys,subprocess
pseudoTermID = os.ttyname(sys.stdout.fileno()).replace('/dev/','')
cmdStr       = 'last | grep "still logged in" | grep "'+pseudoTermID+'"'
sp           = subprocess.Popen([cmdStr], stdout=subprocess.PIPE, shell=True)
(out, err)   = sp.communicate()
RemoteIP     = out.split()[2].replace(":0.0","")   #Returns "" if not SSH
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement