Monday 15 June 2009

Part 2: Monitoring SSH status in Mac OS X Terminal

<< Part 1: Monitoring AFP Status in Mac OS X Terminal

At the end of the last post, I gave the following solution to see whether AFP is enabled via Terminal:

netstat -naf inet6 | grep [*][.]548[\ ].*LIST

If the above command returns nil (or blank) then AFP is disabled. If it returns a line similar to the below, then AFP is enabled:

tcp6 0 0 *.548 *.* LISTEN

As always, there are a multitude of different ways to return similar information e.g. If we replace the -f inet6 option of netstat (which looks for address families using inet6) with the -p option (-p stands for protocol), we can then ask netstat to list all TCP services e.g. the following does pretty much the same thing as above:

netstat -nap TCP | grep [*][.]548[\ ].*LIST

however, returns all TCP services on port 548 i.e. tcp4 and tcp6 entries in return:

tcp4 0 0 *.548 *.* LISTEN
tcp6 0 0 *.548 *.* LISTEN

I'm going to use the -p option to delve once again into netstat, to view whether SSH (Remote Login) is enabled in the terminal or not. However, this time, instead of building something up from the basic building blocks, lets take a look at the final terminal command and break it down:

netstat -nap TCP | cut -c 22-40 | grep -w [*][.]22[\ ]

If you've read the previous post you should be able to see where I'm heading.

First of all, we're using netstat to return a list of current network connections and statistics using the options (-a) all (-n) network addresses which use the TCP (-p) protocol. That's pretty straight forward.

We're then piping ( | ) the output through cut which allows us to only select a portion of each line using the -c option to specify the character positions we want returned.

Why are we doing this? Well, we are only interested in ports running on our local machine, not on other servers. If we're not careful, netstat will return a result for this command based on a SSH service running on a foreign server rather than our own.

e.g. Here's a sample output from netstat based on a connection to google along with the standard netstat column headings:

Proto Recv-Q Send-Q Local Address Foreign Address
tcp4 0 0 192.168.0.5.54400 209.85.227.191.80

The example above is only a http (port 80) connection, however if I was connected via SSH, the foreign address in this case would be: 209.85.227.192.22 (port 22 being the standard SSH port). If I issued the command without cut i.e.

netstat -nap TCP | grep -w [*][.]22[\ ]

I could return a result based on the foreign address connection instead of the local address.

So in order to remove from the nestat output any reference to ports being used in the foreign address column we are using cut -c 22-40. What we're essentially saying is, give me the result from netstat but only the characters 22-40 of each line. e.g. If I issued this command:

netstat -nap TCP | cut -c 22-40

I just get a result of:

Local Address
192.168.0.5.54400

Instead of:

Proto Recv-Q Send-Q Local Address Foreign Address
tcp4 0 0 192.168.0.5.54400 209.85.227.191.80

Ok, that now leaves us with the final grep command:
grep -w [*][.]22[\ ]

This time we're using the -w option which forces grep to return only the lines that contain an exact match. What we're looking for in the netstat output is a local address listening port of *.22 i.e. port 22 of localhost. We need to enclose * and . in [ square braces ] to force grep to include them as part of the pattern as they otherwise have a special meaning for pattern matching in regular expressions.

Usually, or rather, by default, SSH runs over port 22. For security reasons and other, SSH is often run on a custom port, so you'll need to substitute 22 for your unique port number if you've changed the default setting in e.g. /etc/services depending on your set up.

Finally, we want to force an exact pattern match of *.22 not *.223 or *.2202 etc... so we need to add a forced blank space at the end of the pattern using an escape character followed by a space and both surrounded by square brackets [\ ]

Put that all together:

netstat -nap TCP | cut -c 22-40 | grep -w [*][.]22[\ ]

and hey presto:

*.22
*.22

If you get a result similar to the above, Remote Login (SSH) is enabled in System Prefs. If you get nothing, it's disabled.

(PS This is probably, not fool proof. E.g. if you're running SSH over port 443 and you've also got a https server running, you're going to run into problems monitoring which service is enabled. However, I imagine you're going to come across problems anyhow trying to run two different services over the same port before you're even faced with this problem? Comments please!)

Coming soon... monitoring to see if you have active connections

No comments:

Post a Comment