3

given a process Id (that use sockets), I would like to get the IP on socket endpoints.

e.g When new SSH session is created, the sshd demon fork process per session. I want to get the IP endpoints of that session.

I find this logic to work:
1. List all TCP sockets, "cat /proc/net/tcp"
2. List all file descriptor for input process and grep "socket": "ls -la /proc/PID/fd | grep socket"
3. Merge the results

Output #1:

root@L137B-DV3:/home/ilan# cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
...
  18: 519A0A0A:E0D1 3C890A0A:C006 01 00000000:00000000 00:00000000 00000000     0        0 10494 1 ffff88003c44f640 20 4 30 10 -1
  19: 519A0A0A:9930 3C890A0A:C004 01 00000000:00000000 00:00000000 00000000     0        0 10496 1 ffff88003c44ee80 20 4 32 10 -1
  20: 519A0A0A:01BD 59890A0A:C1FA 01 00000000:00000000 02:0004F47D 00000000     0        0 76451 2 ffff88003b39d740 21 4 30 10 -1

Output #2

root@L137B-DV3:/home/ilan# ls -la /proc/4038/fd/ | grep socket
lrwx------ 1 root root 64 Jun  4 13:40 30 -> socket:[6347]
lrwx------ 1 root root 64 Jun  4 13:40 32 -> socket:[76483]
lrwx------ 1 root root 64 Jun  4 13:40 35 -> socket:[6357]
lrwx------ 1 root root 64 Jun  4 13:40 36 -> socket:[76451]
lrwx------ 1 root root 64 Jun  4 13:40 6 -> socket:[76453]

We see inode 76451 is the merge result, socket ip address is localhost: 519A0A0A and remote: 59890A0A.

My questions are:
1. Is it possible to "cat /proc/net/tcp" a specific process ? I tried cat /proc/PID/net/tcp - it return the same results as cat /proc/net/tcp.
2. Is there more efficient way to retrieve IP ?

2 Answers 2

5

You can list open file for a PID with lsof:

lsof -p <PID>

But you may prefer to use command name filtering on ssh processes:

# filters on both ssh and sshd command (client/server)
lsof -i -na -c /sshd?/ -sTCP:ESTABLISHED

And combine both of course:

lsof -p <PID> -i -na -sTCP:ESTABLISHED
3
  • what is "-na" combined together ? AND expression ?
    – ilansch
    Commented Jun 4, 2018 at 14:55
  • a is for ANDing indeed and n is to prevent conversion of network numbers to host names as you requested IP.
    – kaliko
    Commented Jun 4, 2018 at 15:09
  • And the cost is only single lsof execution, thats not so cheap, but at least not 2 different executions like my solution
    – ilansch
    Commented Jun 4, 2018 at 16:07
1

Get a list of local IP addresses and ports listening via TCP/UDP:

netstat -planu | awk '/^udp / {print $4}'

Get the same info via the /proc filesystem:

for h in $(awk 'NR>1{print $2}' /proc/net/tcp); do
printf "%s:%d\n" $(printf "%d." $(echo ${h%:*}|sed 's/../0x& /g'|tr ' ' '\n'|tac)|sed 's/\.$/\n/') 0x${h#*:}; done

Followed by

ip_addr=$(echo 0F01A8C0 | sed -e 's/\(..\)\(..\)\(..\)\(..\)/echo $((0x\4)).$(echo $((0x\3))).$(echo $((0x\2))).$(echo $((0x\1)))/e')

Then in awk

 awk 'NR>1{split($2, addr, ":"); for(i=0;i<4;i++){
printf("%d.",strtonum("0x" substr(addr[1],2*i+1,2)))}; print ":" strtonum("0x" addr[2]);}' /proc/net/udp

Just need to reverse the dotted decimals.

echo 0F01A8C0 | awk '{str = sprintf("0x%s", $0); ip = strtonum(str); \
printf ("%d.%d.%d.%d\t",rshift(and(ip,0x000000ff),00),
                        rshift(and(ip,0x0000ff00),08),
                        rshift(and(ip,0x00ff0000),16),
                        rshift(and(ip,0xff000000),24))}'

Final:

 awk 'NR>1 {
    split($2, a, ":");
   patsplit(a[1],h,/.{2}/);
   for(i=4;i>0;i--){
     h[i]=strtonum("0x" h[i]);
   };
   printf("%d.%d.%d.%d:%d\n",h[4],h[3],h[2],h[1],strtonum("0x" a[2]));
 }' /proc/net/udp

Source: https://wiki.christophchamp.com/index.php?title=Unix_sockets

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .