10

If I use a client to create a reverse tunnel with SSH using -R I will get this output on the server if I run netstat:

default@debian:~$ sudo netstat -pln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      801/sshd
tcp        0      0 127.0.0.1:39963         0.0.0.0:*               LISTEN      1074/sshd: anonymou
tcp6       0      0 :::22                   :::*                    LISTEN      801/sshd
udp        0      0 0.0.0.0:68              0.0.0.0:*                           451/dhclient

I would like to know what is the IP of the client that created the listening socket on port 39963.

What command can I run so I not only get the bound IP:PORT but the IP of the client that created the tunnel?

  • We can only see LISTEN-ing sockets on that output. Including that port you are interested on, which is not a connection (yet), it’s just the sshd server itself that has set up the port forwarding you requested with the -R option. To really see the ESTABLISHED connections, take the l (el) away from the netstat command. I suppose you might instead want to use the t option to see only TCP sockets, and also the a option to see both ESTABLISHED connections and LISTEN-ing sockets. That is: netstat -ptan – LL3 Apr 22 '19 at 23:20
  • Hi, Unfortunately that does not give you the source IP for the binded port (127.0.0.1:39963) – user1618465 Apr 22 '19 at 23:53
  • There is no source IP because your server is just waiting for new connections. 127.0.0.1 is the localhost, your server in that case. It is waiting for connections to that port, and only the server machine itself can connect to its own 127.0.0.1. For example, try telnet localhost 39963 from the server: the ssh on your client machine will connect to whatever other host:port you indicated on your ssh -R command. Then you’ll see an ESTABLISHED connection on your server. Only, it won't be interesting because it'll be 127.0.0.1. The real remote IP will be seen from your client – LL3 Apr 23 '19 at 00:22
  • @LL3 I think the OP is looking for the IP of the SSH client connected to the server. In particular he is looking for the SSH client responsible for opening a remote listening socket on the server. There will be a source IP, the challenge is finding it. – Philip Couling Apr 23 '19 at 11:33
  • Related (and NOT a duplicate) is https://unix.stackexchange.com/questions/127940/determine-dynamically-allocated-port-for-openssh-remoteforward – mr.spuratic Apr 23 '19 at 12:20
  • @PhilipCouling Perhaps you’re right. Certainly that would make more sense of this question.. let’s see what OP has to say. If that’s the case, the client ssh connection that triggered the creation of the listening socket will very likely be under file-descriptor 3 of the process owning that socket, so a simple lsof -anp <pid-of-the-listening-socket> -d 3 suffices (lsof -anp 1074 -d 3 in OP’s case). Or if it's not file-descriptor 3 will anyway be the one which carries a TCP connection tuple in state ESTABLISHED and referring to IP addresses != 127.0.0.1 from a lsof -np 1074 – LL3 Apr 23 '19 at 22:47

5 Answers5

8

I can't give you a single command but there are a few commands which will let you find the client. The problem is with the way OpenSSH creates processes. The process which owns the listening socket 39963 is the child of the process which owns the SSH connection. So they will have different PIDs. In your example you need to find the parent process for 1074. The following works for OpenSSH server on Ubuntu. I can't guarantee every distribution will behave the same way.

Start by finding the PID for the client connection. Use grep to filter the output of netstat.

$ sudo netstat -ptln | grep 39963
tcp        0      0 127.0.0.1:39963         0.0.0.0:*               LISTEN      21921/sshd: philip@
tcp6       0      0 ::1:39963               :::*                    LISTEN      21921/sshd: philip@

The listening process here is 21921. You need it's parent:

$ ps -ef | grep 21921
philip   21921 21919  0 11:01 ?        00:00:00 sshd: philip@pts/1
philip   21924 21921  0 11:01 pts/1    00:00:00 -bash
philip   22844 20309  0 11:15 pts/0    00:00:00 grep --color=auto 21921

# Or try this:

$ ps -ef | awk '$2 == 21921 { print $3 }'
21919

The parent of 21921 here is 21919. Now we look back to netstat to find the client:

$ sudo netstat -ptn | grep 21919
tcp        0      0 192.168.1.36:22          192.168.1.10:54425   ESTABLISHED 21919/sshd: philip

This shows the remote ip is 192.168.1.10

  • 1
    To get the parent process of $child, consider ps -p "$child" -oppid= – Jeff Schaller Apr 23 '19 at 14:23
  • I put together an script based on your line of though to automatically detect the port. It's an answer here. Any thoughs on it will be appreciated – DGoiko Dec 23 '20 at 21:25
2

The SSH client and server exchange messages to set up forwardings, but the kernel network table cares/knows only about its local IP stack, so it sees only sshd.

But, OpenSSH also shares some details in the environment (which too is passed via a message exchange).

 sshcpid=$(pgrep -P 1074)               # fetch child PID
 xargs -0 -L1 -a /proc/$sshcpid/environ # show environment strings

The variables SSH_CLIENT and SSH_CONNECTION should both contain what you need.

Here, xargs is a handy way to process the NUL delimited strings in environ.

This assumes:

  • linux, for a /proc with environ
  • OpenSSH with a process chain like:

    daemon sshd → forked connection sshd → privsep sshd → user shell

e.g. (from pstree -lp):

 init(1)-+
         .
         |-sshd(1015) +-sshd(1072)---sshd(1074)---bash(1075)

The privsep sshd process is the one you see in netstat, the environment you read is from its immediate descendent, the shell (bash in this example).

mr.spuratic
  • 9,901
1

The lsof command in Linux displays in its output information about files that are opened by processes

Taking the process id of ssh from the netstat,

lsof -p $pid -a -d 3

will show IP of other end of the connection. As ssh can be hopped, this might not be the final location.

$pid is process id of your ssh service

if you don't have lsof you can install it with apt-get install lsof

  • I know what PIDs are. My point is the example in question shows there are at least two sshd processes, two PIDs that match your description. Which one to use then? and why? In other words: your answer should explicitly state this must be the PID of sshd that listens on the port being forwarded (39963), not of some other (any) sshd. So 1074 in the OP's example. – Kamil Maciorowski Apr 23 '19 at 07:41