In most environments, you would only expect to find tcp, udp, raw and packet sockets. Happily, ss
knows about all of these.
Assuming ss
knows all the protocols you need it to, I might use the following command. This will exclude the "unix" sockets. It also excludes "netlink" sockets, which are only used to communicate with the local kernel.
sudo ss -l -p | grep -vE '^(u_|nl )'
Often you do not have a lot of listening sockets. So you can look through them all, and manually ignore any that listen on loopback IP addresses. Alternatively, you can ask ss
to do all the filtering:
sudo ss -l -p -A 'all,!unix,!netlink' 'not src 127.0.0.1 not src [::1]'
In both cases, the output can also include "client" udp sockets. So it might also show DNS clients, HTTP/3 clients, ...
If you do not need to see information about the program which opened each socket, then you can remove the -p
option, and you do not need to run ss
(or netstat
) with root privileges (sudo
).
How comprehensive is the above command?
Despite being advertised as a replacement for netstat, ss
lacks the support for showing "udplite" sockets.
Also, the answer depends on your version of ss
(and I guess the kernel as well). When this answer was originally written, before 2017, ss
did not support "sctp". netstat
supported it since February 2014). sctp is expected specifically inside phone companies. Outside of phone companies, VOIP typically uses udp.
Unfortunately if you look for a comprehensive list in man netstat
, it gets quite confusing. Options for sctp and udplite are shown in the first line, along with tcp, udp and raw. Further down there's what looks like a comprehensive list of protocol families: [-4|--inet] [-6|--inet6] [--unix|-x] [--inet|--ip|--tcpip] [--ax25] [--x25] [--rose] [--ash] [--bluetooth] [--ipx] [--netrom] [--ddp|--appletalk] [--econet|--ec]
.
Although netstat
supports udplite and sctp, it does not support "dccp". Also netstat doesn't support packet sockets (like raw sockets but including link-level headers), as selected by ss -l -0
. In conclusion, I hate everything, and I could probably stand to be less pedantic.
Also ss
does not support bluetooth sockets. Bluetooth sockets are not a traditional concern. This could be relevant if you were doing a full audit. Bluetooth security is quite a specific question though; I am not answering it here.
Omitting localhost in netstat
?
netstat
does not have a specific way to omit sockets bound to localhost. You could use | grep -v
on the end. Take care if you use the -p
option to netstat / ss. You might accidentally exclude some of your processes, if there is a match in the process name. I would include the colon in your pattern, like grep -v localhost:
. Except the default in ss
is to show numeric addresses, so in that case you would use | grep -vE (127.0.0.1|\[::1\]):
. I suppose you could try to check for processes which would be accidentally excluded, e.g. ps ax | grep -E (127.0.0.1|\[::1\]):
.
Is there a simpler command?
It's unfortunate about the packet sockets. Otherwise, I might suggest a plain netstat -l
command. netstat
helpfully anticipates your request and splits the output into "Internet connections", "UNIX domain sockets", and "Bluetooth connections". You would just look at the first section. There is no section for netlink sockets.
Suppose you're only concerned with tcp, udp, raw, and packet sockets. For the first three types of socket you could use netstat -l -46
.
Packet sockets are in common use. So you would also need to train yourself to run ss -l -0
(or ss -l --packet
).
Unfortunately this leaves you with a big pitfall. The problem is it is now tempting to try and combine the two commands...
Traps to avoid with ss
ss -l -046
looks appealing as a single-command answer. However this is not true. ss -46
only shows IPv6 sockets. ss -64
only shows IPv4 sockets.
I suggest always sanity-checking your results. Learn what to expect; go through each protocol and see if there's anything missing that should be there. If you have no IPv4 addresses, or no IPv6 addresses, that's very suspicious. You can expect most servers to have an SSH service listening on both. Most non-servers should also show packet or raw sockets, due to using DHCP.
If you don't want to interpret the output of two different commands, one alternative might be to replace the netstat
command with ss -l -A inet
. This is slightly unfortunate because when you run netstat, the exact same options would exclude ipv6 sockets.
So for a single command, you could use ss -l -A inet,packet ...
.
IMO you might as well use ss -l | grep ...
as I suggested in the first section. It is easy to remember this command, and it avoids any and all confusing behaviour in the selection options of ss
.
Although if you write scripts that use this output to automate something, then you should probably prefer to filter on a positive list of socket types instead. Otherwise the script could break when ss
starts supporting a new type of local-only socket.
Did I mention that ss -a -A raw -f link
shows a combination of sockets from ss -a -A raw
and ss -a -f link
? Whereas ss -a -A inet -f inet6
shows less sockets than ss -a -A inet
? I think -f inet6
and -f inet
are special cases, which are not documented properly.
(-0
, -4
and -6
are aliases for -f link
, -f inet
, and -f inet6
).
Did I mention that ss -A packet
will show headings, but will never show any sockets? strace
shows that it literally does not read anything. It seems to be because it treats packet sockets as always being "listening". ss
does not bother to provide a warning about this. And this is different from raw sockets, which ss
treats as being simultaneously "listening" and "non-listening".
(man 7 raw
says that if a raw socket is not bound to a specific protocol which are not bound to a specific IP protocol, then it is transmit-only. I have not checked if these are treated as listening sockets only)