Using the ss command to examine sockets in Linux

'ss', short for "socket statistics", is the preferred replacement for netstat in CentOS/RHEL 7 and deriviatives.  As part of the iproute2 package, it comes with other IP routing utilities such as 'ip route'.  

ss gathers information directly from kernal space using Netlink, which utilizes the classic sockets API, providing more in-depth information to the user.

To use ss, let's first examine the output of the "man" page.
-h, --help Show summary of options.

-V, --version Output version information.

-n, --numeric Do now try to resolve service names.

-r, --resolve Try to resolve numeric address/ports.

-a, --all Display all sockets.

-l, --listening Display listening sockets.

-o, --options Show timer information.

-e, --extended Show detailed socket information

-m, --memory Show socket memory usage.

-p, --processes Show process using socket.

-i, --info Show internal TCP information.

-s, --summary Print summary statistics. This option does not parse socket lists obtaining summary from various sources. It is useful when amount of sockets is so huge that parsing /proc/net/tcp is painful.

-4, --ipv4 Display only IP version 4 sockets (alias for -f inet).

-6, --ipv6 Display only IP version 6 sockets (alias for -f inet6).

-0, --packet Display PACKET sockets.

-t, --tcp Display only TCP sockets.

-u, --udp Display only UDP sockets.

-d, --dccp Display only DCCP sockets.

-w, --raw Display only RAW sockets.

-x, --unix Display only Unix domain sockets.

-f FAMILY, --family=FAMILY Display sockets of type FAMILY. Currently the following families are supported: unix, inet, inet6, link, netlink.

-A QUERY, --query=QUERY, --socket=QUERY List of socket tables to dump, separated by commas. The following identifiers are understood: all, inet, tcp, udp, raw, unix, packet, netlink, unix_dgram, unix_stream, packet_raw, packet_dgram.

-D FILE, --diag=FILE Do not display anything, just dump raw information about TCP sockets to FILE after applying filters. If FILE is - stdout is used.

-F FILE, --filter=FILE Read filter information from FILE. Each line of FILE is interpreted like single command line option. If FILE is - stdin is used.FILTER := [ state TCP-STATE ] [ EXPRESSION ]Please take a look at the official documentation (Debian package iproute-doc) for details regarding filters.
Displaying the man page allows us to quickly discover what we need.

In our netstat article, we reviewed how to use netstat to determine whether Apache was indeed listening on the correct ports.  For the purpose of this article, we'll follow much of the same outline, tailoring it specifically to CentOS 7 and similar distributions.

Let's first check to make sure that Apache is running, which can be accomplished as below.  

[root@web01][01:10:49 PM][~]$ systemctl status httpd
? httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2017-10-25 07:25:15 CDT; 1 weeks 2 days ago

Once you've determined that Apache is indeed listening, we can proceed with determining whether the appropriate ports are listening.  Most Apache installations, specifically the default installation of Apache 2.4, will include a default configuration that listens on port 80.  The installation of mod_ssl will contain a default listener on 443 as well.

To start, we have to know a few basic things about Apache and web ports in general.  HTTP requests utilize the TCP protocol.  This is a stateful protocol that provides for certain packet delivery.  Unlike UDP, TCP verifies transmission requests each time a packet is sent and received, through a process known as SYN/ACK.

With this knowledge, let's take a look at how we replicate the following netstat command:

[root@web01][01:29:57 PM][~]$ netstat -tlp

This command specifically is looking at TCP Listening Sockets, and listing the PID of the process utilizing the socket.  To get the same output out of ss, we would do the following:

[root@web01][01:29:57 PM][~]$ ss -tlp

You'll notice some distinct similarities here.  The only change is the name of the application we call with our shell.  The output is where things really get different.

[root@web01][01:29:57 PM][~]$ ss -tlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:memcache *:* users:(("memcached",pid=61424,fd=46))
LISTEN 0 128 *:ssh *:* users:(("sshd",pid=1672,fd=3))
LISTEN 0 100 *:* users:(("master",pid=2337,fd=13))
LISTEN 0 128 *:* users:(("snmpd",pid=12442,fd=9))
LISTEN 0 128 *:* users:(("php-fpm",pid=60154,fd=0),("php-fpm",pid=60153,fd=0),("php-fpm",pid=60152,fd=0),("php-fpm",pid=60095,fd=0),("php-fpm",pid=59224,fd=0),("php-fpm",pid=59223,fd=0),("php-fpm",pid=59222,fd=0),("php-fpm",pid=59221,fd=0),("php-fpm",pid=59220,fd=0),("php-fpm",pid=59219,fd=0),("php-fpm",pid=59218,fd=0),("php-fpm",pid=56507,fd=0),("php-fpm",pid=45797,fd=0),("php-fpm",pid=42745,fd=6),("php-fpm",pid=35753,fd=0),("php-fpm",pid=35752,fd=0),("php-fpm",pid=35751,fd=0),("php-fpm",pid=35694,fd=0),("php-fpm",pid=35693,fd=0),("php-fpm",pid=35692,fd=0),("php-fpm",pid=35691,fd=0),("php-fpm",pid=35690,fd=0),("php-fpm",pid=35661,fd=0),("php-fpm",pid=35660,fd=0),("php-fpm",pid=35659,fd=0),("php-fpm",pid=35658,fd=0),("php-fpm",pid=35657,fd=0),("php-fpm",pid=35656,fd=0),("php-fpm",pid=35655,fd=0),("php-fpm",pid=31426,fd=0),("php-fpm",pid=22224,fd=0),("php-fpm",pid=17704,fd=0),("php-fpm",pid=8536,fd=0),("php-fpm",pid=8535,fd=0),("php-fpm",pid=8533,fd=0),("php-fpm",pid=4017,fd=0))
LISTEN 0 128 :::http :::* users:(("httpd",pid=60105,fd=4),("httpd",pid=60096,fd=4),("httpd",pid=47756,fd=4),("httpd",pid=45510,fd=4),("httpd",pid=44321,fd=4),("httpd",pid=35662,fd=4),("httpd",pid=31465,fd=4),("httpd",pid=24482,fd=4),("httpd",pid=19878,fd=4),("httpd",pid=7387,fd=4),("httpd",pid=7353,fd=4))
LISTEN 0 128 :::ssh :::* users:(("sshd",pid=1672,fd=4))
LISTEN 0 100 ::1:smtp :::* users:(("master",pid=2337,fd=14))
LISTEN 0 128 :::https :::* users:(("httpd",pid=60105,fd=6),("httpd",pid=60096,fd=6),("httpd",pid=47756,fd=6),("httpd",pid=45510,fd=6),("httpd",pid=44321,fd=6),("httpd",pid=35662,fd=6),("httpd",pid=31465,fd=6),("httpd",pid=24482,fd=6),("httpd",pid=19878,fd=6),("httpd",pid=7387,fd=6),("httpd",pid=7353,fd=6))

As you can see, this specific server is listening on both port 80 (http above) and port 443 (https above).  The huge difference comes with the fact that we are able to gather additional information regarding FD (file descriptors), individual PID's for each Apache process, and a local send/receive-Q status.  These may assist further in diagnostic work you may undertake.

So as to provide additional examples;

If you would like to view ALL listening sockets, you would type:
[root@web01][01:30:00 PM][~]$ ss -s
To display ALL open network ports, you would type:

[root@web01][01:40:36 PM][~]$ ss -l

To filter by connection state, for example if you wanted to see all connected HTTP sockets, you would type:

[root@web01][01:52:14 PM][~]$ ss -o state established '( dport = :http )'

Where :http in the example above is the name of the process for which you want to see established process statistics, and dport stands for destination port.  You can choose to change 'dport' in the above example to 'sport', if you're looking for outbound http connections.

As discussed, ss is a versatile, fully featured replacement for netstat.  It's introduction should bring delight, not fear, to a sysadmin!  The pleathora of data it provides is unmatched by current offerings, and it's a more than capable utility.

If you have any specific questions regarding utilizing ss or any other linux utilities, or just need assistance managing your server, please don't hesitate to contact us!
  • centos 7, linux, ss, ports, services, ubuntu

Was this answer helpful?

 Print this Article

Related Articles

Using Netstat to check which ports are listening in Linux

Netstat is a command line utility for Linux that prints network connections, routing tables,...