Search code examples
linuxsshnetstatfuser

How can I figure out which process is opening the certain tcp port?


I usually use fuser command to check pid opening the certain tcp port like the following

fuser 22/tcp //To get pid opening the 22 tcp port

I've got a reference board which running a embedded linux. It have been already opening 22 tcp port for ssh connection. But fuser doesn't display output anything about 22 port. So I tried another ssh daemon to open 322 port then tried to check pid using fuser, it worked fine.

root@imx6qsabreauto:~# netstat -nlt | grep 22
tcp        0      0 0.0.0.0:4224            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:322             0.0.0.0:*               LISTEN
tcp        0      0 :::322                  :::*                    LISTEN
tcp        0      0 :::22                   :::*                    LISTEN

root@imx6qsabreauto:~# fuser 322/tcp
351

root@imx6qsabreauto:~# ps -ef | grep 351
root       351     1  0 01:46 ?        00:00:00 /usr/sbin/dropbear -r /etc/dropbear/dropbear_rsa_host_key -p 322 -B

root       379   315  0 02:11 ttymxc3  00:00:00 grep 351


root@imx6qsabreauto:~# fuser 22/tcp
==> This output nothing !!

How can I figure out which process is opening tcp 22 port. (In the board, lsof command is not available and.. netstat doesn't have -p option.)


Solution

  • I you have /proc mounted and bash and readlink both installed, You can write a small bash script that parses /proc/net/tcp, and scan /proc/*/fd/ to find the corresponding socket.

    I'm not so familiar with embedded linux, but if you cannot find readlink, it may be included in busybox.

    /proc/net/tcp is something like

    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
    0: 00000000:4E7A 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 13128 1 ffff8800cf960740 99 0 0 10 0
    

    The local_address is hex string of HOST:PORT, so the script searches for :0016 when you want to search tcp 22 port.

    Once it founds the row which contains :0016 in local_address, the inode is the corresponding socket number.

    Then it searchs for /proc/*/fd/* which has the socket number using readlink command.

    #!/bin/bash
    PORT="$1"
    HEX_PORT=$(printf %04X $PORT)
    INODE=""
    if ! [ "$PORT" ];then
      echo "usage $0 [PORT]"
      exit
    fi
    while read num host_port _ _ _ _ _ _ _ inode _; do
      if [[ $host_port =~ :"$HEX_PORT"$ ]];then
        INODE=$inode
      fi
    done < /proc/net/tcp
    if ! [ "$INODE" ];then
      echo "no process using $PORT"
      exit
    fi
    for fn in /proc/[1-9]*/fd/*; do
      if [ "$(readlink $fn)" = "socket:[$INODE]" ];then
        tmp=${fn%/fd*}
        echo ${tmp#/proc/}
      fi
    done