18 October 2010

Network Ports and Processes

Looking at a host, there are times when it may be indeterminable
what process may be holding a particular port open.  Perhaps because
there is no entry for the port in /etc/services, thus netstat, etc,
will not display a recognizable name.  The reason may be that the port
number is not identifiable relative to any process running on the host.
For whatever the reason, it may be necessary to determine the controlling
process holding open a network port.  One effective tool is lsof
(http://people.freebsd.org/~abe/):

        freebsd [0] /usr/local/sbin/lsof -i -nP
        COMMAND    PID  USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
        syslogd    306  root    5u  IPv4 0xc2422654      0t0  UDP *:514
        sshd       415  root    3u  IPv4 0xc24f6000      0t0  TCP *:22 (LISTEN)
        sendmail   421  root    4u  IPv4 0xc24f5de0      0t0  TCP 127.0.0.1:25 (LISTEN)
        mysqld     501 mysql    3u  IPv4 0xc25751bc      0t0  TCP *:3306 (LISTEN)
        snmpd      503  root   13u  IPv4 0xc2575000      0t0  TCP *:199 (LISTEN)
        snmpd      503  root   14u  IPv4 0xc24220b4      0t0  UDP 7.7.6.191:161
        [snip...]

The parameters passed to lsof in the above example break down as follows:

        -i      list all network files
        -n      do not translate IP addrs to hostnames
        -P      do not translate ports to service names

In the above, one can determine that tcp port 199 is opened by snmpd,
pid 503, and is running as root.  Similarly, udp port 514 is opened
by syslogd.  While lsof is a nice tool to have available and will run
on Solaris, FreeBSD, and Linux, its downfall is that lsof typically
needs to be compiled on the host it is to run on and it is not installed
by default.  Though not as full featured as lsof may seem to be, each of
the three OSes mentioned have their own native means of determining this
same information.  Similar to the output of lsof is FreeBSD's sockstat,
which lists open sockets.  The following will allow one to see all open
network sockets, regardless of if they are simply in a listening or
connected state:

        freebsd [0] /usr/bin/sockstat -cl | /usr/bin/egrep -v 'stream|dgram'
        USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
        root     sshd       55112 4  tcp4   7.7.6.191:22          7.7.6.181:42774
        root     sshd       50436 4  tcp4   7.7.6.191:22          7.7.6.181:42772
        root     syslogd    306   5  udp4   *:514                 *:*
        root     snmpd      503   13 tcp4   *:199                 *:*
        root     snmpd      503   14 udp4   7.7.6.191:161         *:*
        mysql    mysqld     501   3  tcp4   *:3306                *:*
        [snip...]

Just as in the lsof example, sockstat on FreeBSD can provide the same
information.  The explanation for the sockstat options are:

        -c      list connected sockets
        -l      list listening sockets

        * the pipe to egrep is simply to strip out UNIX sockets

The next OS, Solaris, provides a slightly more involved means of obtaining
this information through the usage of pfiles.  pfiles is part of the
proc tools supplied with at least Solaris 8 and newer.  Though not as
neatly presented as either sockstat or lsof, the following is an example
of pfiles usage to obtain the information above:

        solaris [0] /usr/bin/pfiles /proc/* | /usr/bin/egrep "^[0-9]|sockname"
        0:      sched
        1:      /etc/init -
        1001:   /usr/local/sbin/snmpd -p /var/run/net-snmpd.pid
                sockname: AF_INET 0.0.0.0  port: 199
                sockname: AF_INET 0.0.0.0  port: 161
        337:    /opt/VRTSob/bin/vxsvc -r /opt/VRTSob/config/Registry -e
                sockname: AF_UNIX /var/vx/isis/vea_portal
                sockname: AF_INET 0.0.0.0  port: 2148
                sockname: AF_INET 0.0.0.0  port: 2148
        695:    /usr/lib/sendmail -bd -q15m
                sockname: AF_INET 0.0.0.0  port: 25
                sockname: AF_INET6 ::  port: 25
                sockname: AF_INET 0.0.0.0  port: 587
        [snip...]

The above pfiles command examines the process data relative to the
contents of /proc.  The subsequent pipe to egrep is to grab only
the data useful towards determining network port / process relation.
The beginning of each entry is the pid in question, followed by the
process and its arguments.  If there is a network port associated with
the process, it is listed on a new line below it, numerically, with the
interface it is listening on, if any.

Finally, Linux can also provide this information, though in a cleaner
manner than Solaris, through the use of netstat.

        linux [0] /bin/netstat -antup
        Active Internet connections (servers and established)
        Proto Recv-Q Send-Q Local Address     Foreign Address   State   PID/Program name
        tcp        0      0 0.0.0.0:32768     0.0.0.0:*         LISTEN  1712/rpc.statd
        tcp        0      0 127.0.0.1:32769   0.0.0.0:*         LISTEN  1831/xinetd
        tcp        0      0 0.0.0.0:199       0.0.0.0:*         LISTEN  2560/snmpd
        tcp        0      0 7.7.6.191:22      0.0.0.0:*         LISTEN  1817/sshd
        tcp        0      0 127.0.0.1:25      0.0.0.0:*         LISTEN  1852/sendmail
        [snip...]

The options to netstat are explained as:

        -a      show all sockets, listening or otherwise
        -n      numeric output, as in don't translate IPs or ports to names
        -t      show tcp sockets
        -u      show udp sockets
        -p      show the pid and name of the program holding open the socket


see also:
    Network Ports and Processes (Windows)