A vanilla ss -l lists (on my current machine) lots of open sockets, with various Netid types and many of which are only listening on localhost.

How do I get a list of all and only those sockets through which a remote machine can conceivably exchange data with the machine?

  • This would include TCP, UDP, any other transport-layer protocols, RAW sockets, and any others I may not be aware of. (Is ss complete in this sense?)

  • I believe this would exclude UNIX sockets (they're over the local filesystem only, right? or of UNIX sockets can act remotely, they should be included).

  • Localhost-restricted listeners can be ignored but I don't know if there are any caveats in terms of how localhost can be represented/mapped.

The essential criteria is "any socket I can be remotely hacked through, if the listening process allowed it".

(I recall ss commands from a few years ago showed a lot fewer results than what I get now. This makes me wonder if some distributions configure ss to hide stuff by default. I'm looking for a ss or similar utility command which is as portable as possible, insofar as it won't hide anything just because it was run in a different environment. Also, from a security-theoretic point of view, we can assume for the threat model that the machine is fully under our control and is running ordinary, non-malicious software.)

So how do I list all and only the relevant sockets?


In most environments you would only expect to see tcp, udp, raw and packet sockets. ss knows about all of these.

If ss knows all the protocols you need it to, you could use the following command. It will exclude the UNIX sockets, and the same goes for netlink sockets, which are only used to communicate with the local kernel.

ss -l | grep -vE '^(u_|nl )

Remember that if you want information on the listing programs (-p), you will need to run ss (or netstat) with root privileges (sudo).

Omitting localhost

Sorry, but there isn't a specific way to omit sockets bound to localhost. 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 (|::):. I guess you could also check for processes which would be accidentally excluded, e.g. ps ax | grep (|::):.

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 this context, 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.

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...

A dire warning

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 option would exclude ipv6 sockets.

A single command that seems to work is ss -l -A inet,packet.

However, you might as well use ss -l | grep... as I suggested in the first section. It is easier to remember this command, because it avoids all the all the horribly 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)

  • Remember: "Netstat? Tuna, please!" The output of netstat -tunapl gives you an easyly readable output with the information you're looking for. – Jan Sep 10 '16 at 20:08
  • No. Poster explicitly asked for raw sockets. And any other... the netstat manpage is annoyingly cagey when it comes to the complete list of protocols, but I think it's saying: [-4|--inet] [-6|--inet6] [--unix|-x] [--inet|--ip|--tcpip] [--ax25] [--x25] [--rose] [--ash] [--bluetooth] [--ipx] [--netrom] [--ddp|--appletalk] [--econet|--ec] – sourcejedi Sep 10 '16 at 20:16
  • Doh, forgot raw sockets. IIRC netstat -w lists them. – Jan Sep 10 '16 at 20:29
  • @Jan In netstat -tunapl, which of -a and -l overrides the other? – Tim Mar 22 at 23:33
  • @Tim the one that comes later. Good question :-). I think it is there to make the phrase easy to remember (if Tuna is in your vocabulary :-). – sourcejedi Mar 22 at 23:36

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.