0

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

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
  • what is "-na" combined together ? AND expression ? – ilansch Jun 4 '18 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 Jun 4 '18 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 Jun 4 '18 at 16:07
0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.