I have a number of servers, including a few on the home office network, that accept SSH connections. Even though they are serving on different (non-standard) SSH ports, there are regular attempts made to break it via brute-force – I can see how some random IP addresses start trying to log in using different standard user names. It's therefore never too late to use additional software for protecting SSH service, something like fail2ban.
[Read more…] about How To: Use fail2ban to Protect SSHConfirm Actively Listening TCP Ports with lsof
I was researching SSH daemon configuration on my macOS Catalina system and realised that lsof is still the best tool for meaningfully confirming network ports that are LISTENed to.
What does it mean for port to LISTEN?
All the network services in Linux (and Windows, actually) operating systems start with the same basic pattern: some process is managing incoming network connections.
Nowadays most of network services are directly managing their own network connections – meaning service like SSH daemon or Apache web server are made available via main process (sshd or httpd in my examples) constantly running and waiting for incoming network connections on specific port. For SSH server, default port is 22. For web servers, default ports are 80 and 443.
When we say a port is LISTENing, it means there's a process running on your system that's monitoring this specific port. SSH is therefore listening on/for port 22, Apache (httpd) is listening for port 80 and possibly 443.
Meaningful TCP ports reporting vs Default
You may remember that netstat command shows network ports as well, but its implementations are sometimes limited to just confirming that a certain port is listened to, without helping us understand what process is doing that port listening:
greys@mcfly:~ $ netstat -na |grep LISTEN | grep 22
tcp46 0 0 *.22000 *.* LISTEN
tcp4 0 0 *.22 *.* LISTEN
tcp6 0 0 *.22 *.* LISTEN
That's why I prefer the lsof tool – it's reporting processes information, which means any output you get is bound to contain processes numbers (PIDs) and most likely process names (binary names like sshd or httpd).
Use lsof to show listening TCP ports
lsof command has specific options for reporting processes with network activity: -iTCP will report TCP specific information, and -sTCP:LISTEN qualifier will filter just the processes that are listening for incoming connections on TCP ports (rather than client processes that only initiate outgoing network connections).
Don't Forget to run lsof with sudo!
Normally lsof is super useful even with standard user privileges, but since I'm investigating a system service (SSH server), I have to run lsof as root. Otherwise lsof will report a list of network services, but hide the ones running above your standard user privilege level.
On modern Linux servers, lsof without sudo won't show me anything:
greys@s2:~ $ lsof -iTCP -sTCP:LISTEN
greys@s2:~ $
My complete command to list all the services listening for incoming TCP connections in will therefore look like this (this is the macOS example):
greys@mcfly:~ $ sudo lsof -iTCP -sTCP:LISTEN COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME launchd 1 root 8u IPv6 0xc37c60e6e93432f1 0t0 TCP *:ssh (LISTEN) launchd 1 root 9u IPv4 0xc37c60e6e934d8f1 0t0 TCP *:ssh (LISTEN) launchd 1 root 10u IPv6 0xc37c60e6e9343911 0t0 TCP *:rfb (LISTEN) launchd 1 root 11u IPv4 0xc37c60e6e934e2b9 0t0 TCP *:rfb (LISTEN) launchd 1 root 21u IPv6 0xc37c60e6e93432f1 0t0 TCP *:ssh (LISTEN) launchd 1 root 24u IPv4 0xc37c60e6e934d8f1 0t0 TCP *:ssh (LISTEN) launchd 1 root 29u IPv6 0xc37c60e6e9343911 0t0 TCP *:rfb (LISTEN) launchd 1 root 32u IPv4 0xc37c60e6e934e2b9 0t0 TCP *:rfb (LISTEN) launchd 1 root 40u IPv6 0xc37c60e6e9342cd1 0t0 TCP localhost:intu-ec-client (LISTEN) launchd 1 root 46u IPv6 0xc37c60e6e9342cd1 0t0 TCP localhost:intu-ec-client (LISTEN) launchd 1 root 47u IPv4 0xc37c60e6e934cf29 0t0 TCP localhost:intu-ec-client (LISTEN) launchd 1 root 48u IPv4 0xc37c60e6e934cf29 0t0 TCP localhost:intu-ec-client (LISTEN) kdc 120 root 5u IPv6 0xc37c60e6e93426b1 0t0 TCP *:kerberos (LISTEN) kdc 120 root 7u IPv4 0xc37c60e6e934f649 0t0 TCP *:kerberos (LISTEN) rapportd 625 greys 4u IPv4 0xc37c60e6ef7969d9 0t0 TCP *:49263 (LISTEN) rapportd 625 greys 5u IPv6 0xc37c60e6e9342091 0t0 TCP *:49263 (LISTEN) ARDAgent 697 greys 9u IPv6 0xc37c60e6e9341a71 0t0 TCP *:net-assistant (LISTEN) Dropbox 1148 greys 128u IPv4 0xc37c60e6eefd8561 0t0 TCP *:17500 (LISTEN) Dropbox 1148 greys 129u IPv6 0xc37c60e703f137b1 0t0 TCP *:17500 (LISTEN) Dropbox 1148 greys 154u IPv4 0xc37c60e6f88c09d9 0t0 TCP localhost:17603 (LISTEN) Dropbox 1148 greys 168u IPv4 0xc37c60e6f8940011 0t0 TCP localhost:17600 (LISTEN) dynamicli 1204 greys 7u IPv4 0xc37c60e6f908f9d9 0t0 TCP localhost:51456 (LISTEN) dynamicli 1205 greys 7u IPv4 0xc37c60e6f9a453a1 0t0 TCP localhost:51549 (LISTEN) dynamicli 1205 greys 16u IPv4 0xc37c60e6f9b0a8f1 0t0 TCP localhost:51551 (LISTEN) com.docke 1341 greys 7u IPv4 0xc37c60e6fa8222b9 0t0 TCP localhost:51725 (LISTEN) com.docke 1345 greys 15u IPv4 0xc37c60e6eefd7b99 0t0 TCP localhost:sun-sr-https (LISTEN)
Confirming what process is listening on a specific port
While we're at it, here's how the previous command can be modified to confirm a specific service listening on SSH port 22:
greys@mcfly:~ $ sudo lsof -iTCP -sTCP:LISTEN | grep ssh
Password:
launchd 1 root 8u IPv6 0xc37c60e6e93432f1 0t0 TCP *:ssh (LISTEN)
launchd 1 root 9u IPv4 0xc37c60e6e934d8f1 0t0 TCP *:ssh (LISTEN)
launchd 1 root 21u IPv6 0xc37c60e6e93432f1 0t0 TCP *:ssh (LISTEN)
launchd 1 root 24u IPv4 0xc37c60e6e934d8f1 0t0 TCP *:ssh (LISTEN)
IMPORTANT: Note that because SSH is a standard service, lsof reports its name (ssh) rather than port number (22) in the last column of output. TCP *:ssh means process is listening for TCP port for SSH service.
I was expecting sshd, actually. But turns out remote access via SSH is managed by launchd process in recent macOS versions. Once someone logs in though, you'll see sshd process spun up to manage the connection.
That's it for today, hope you learned something new!
See Also
Unix Tutorial Digest – January 4th, 2020
It's time for another Unix Tutorial digest – this issue covers notable events and releases in December 2019.
I also plan to start annual digests, will try and publish the Unix Tutorial Annual Digest 2019 tomorrow.
Please get in touch to arrange a technical consultation with me or suggest a useful link for the next digest here at Unix Tutorial.
Unix Tutorial News
Unix Tutorial website now has a chat feature! This means you can ping me and ask a quick question or discuss a project. My online (live chat) time is quite limited but please take a moment to leave me note and your email so that I can get back to you.
Unix and Linux News
I have started a new category on Unix Tutorial – called New Releases, that's where OS upgrades and Linux kernel releases will be announced going forward (they're still blog posts).
- Kali Linux 2019.4
- Linux Mint 19.3 was released – must try it soon
Software News
- VirtualBox 6.1 released – this is the must-have software on Linux and Windows platforms, such a great and stable desktop virtualization product
- tmux 3.0a is here – I already upgraded tmux to 3.0a on my macOS systems to this version
- Ruby got upgraded to 2.7.0
- QEMU 4.2 is here
Interesting and Useful
- Basics: setting static IP address in Ubuntu
- Show lines around matched pattern with grep
- Confirm Symlink Destination
Unix Tutorial articles
Full list of posts published on Unix Tutorial in December 2019, 18 posts in total:
- Check Python Version
- Merry Christmas!
- Show Next Few Lines with grep
- Install Jekyll 4 in macOS
- How To Change Mac Hostname with scutil
- Protecting Directories with Sticky Bit
- neofetch in Debian Linux
- VirtualBox 6.1 Released
- Ubuntu – Static IP
- How To Confirm Symlink Destination
- Get Last Field with awk
- Live Chat on Unix Tutorial
- Kali Linux 2019.4
- List Kernel Extensions with kextfind
- How To: List Kernel Modules in macOS
- more or less
- Sort Files by Size with ls
- Unix Tutorial Digest – December 1st, 2019
That's it for the month of December 2019!
See Also
Welcome to 2020!
Hey everyone, just wanted to wish you all a Happy New Year and to welcome you into 2020!
Unix Tutorial: 2019 in Numbers
2019 has been the greatest year in all of the UnixTutorial.org history: 970K views – that's just one typical week shy of a whole 1 million post and page views!
I'm super thankful to everyone who stopped by and plan to make 2020 an even bigger success – for you and for me.
I made 258 posts last year, so it will be really great to do 300 or more in 2020.
Need Any Help?
Please get in touch or ask a question in chat widget, I would love to help you solve quick and not so quick Unix challenges.
I'm also looking for opportunities in training – so if you have a team of technical professionals looking for guidance with Unix/Linux administration – please get in touch to arrange a custom training program or just have me create or review a manual or technical guide.
See You Around
2020 will be an awesome year – THANK YOU and hope you see you on Unix Tutorial pages and my Facebook group.
Merry Christmas!
Greetings from Germany!
We're spending Christmas break away from Ireland this year, so most of the week has been pre-scheduled posts as I'm offline until we come back.
Want to take a moment and wish you a very happy Christmas! Great time to spend time with family and maybe catch up on RSS and ebook reading on some of the quiet wintery mornings.
Will be back soon, hope you're all having a great time!
Show Next Few Lines with grep
Now and then I have to find some information in text files – logs, config files, etc. with a unique enough approach: I have a hostname or parameter name to search by, but the actual information I'm interested in is not found in the same line. Simple grep will just not do – so I'm using one of the really useful command line options for the grep command.
Default grep Behaviour
By default, grep shows you just the lines of text files that match the parameter you specify.
I'm looking for the IP address of the home office server called "server" in .ssh/config file.
Here's what default grep shows me:
greys@maverick:~ $ grep server .ssh/config Host server
So it's useful in a sense that this confirms that I indeed have a server profile defined in my .ssh/config file, but it doesn't show any more lines of the config so I can't really see the IP address of my "server".
Show Next Few Lines with grep
This is where the -A option (A – After) for grep becomes really useful: specify number of lines to show in addition to the line that matches search pattern and enjoy the result!
I'm asking grep to show me 2 more lines after the "server" line:
greys@maverick:~ $ grep -A2 server .ssh/config Host server HostName 192.168.1.55 ForwardAgent yes
Super simple but very powerful way of using grep. I hope you like it!
See Also
Install Jekyll 4 in macOS
This is a fairly straightforward procedure, I just want to capture it here for my own future use.
Install Ruby Version 2.4.0 or Better
Your macOS comes with Ruby pre-installed, but unfortunately it's not recent enough to support Jekyll 4.
In macOS Mojave I have the following ruby version:
greys@mcfly:~ $ ruby -v ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]
Now that Jekyll 4 is the default, you simply install jekyll gem and it will get you the latest version of the 4.x branch.
But Jekyll gem install would fail with one of the dependencies like this:
greys@mcfly:~/proj/gleb.reys.net $ sudo gem install jekyll Password: Fetching: public_suffix-4.0.1.gem (100%) Successfully installed public_suffix-4.0.1 Fetching: addressable-2.7.0.gem (100%) Successfully installed addressable-2.7.0 Fetching: colorator-1.1.0.gem (100%) Successfully installed colorator-1.1.0 Fetching: http_parser.rb-0.6.0.gem (100%) Building native extensions. This could take a while… Successfully installed http_parser.rb-0.6.0 Fetching: eventmachine-1.2.7.gem (100%) Building native extensions. This could take a while… Successfully installed eventmachine-1.2.7 Fetching: em-websocket-0.5.1.gem (100%) Successfully installed em-websocket-0.5.1 Fetching: concurrent-ruby-1.1.5.gem (100%) Successfully installed concurrent-ruby-1.1.5 Fetching: i18n-1.7.0.gem (100%) HEADS UP! i18n 1.1 changed fallbacks to exclude default locale. But that may break your application. Please check your Rails app for 'config.i18n.fallbacks = true'. If you're using I18n (>= 1.1.0) and Rails (< 5.2.2), this should be 'config.i18n.fallbacks = [I18n.default_locale]'. If not, fallbacks will be broken in your app by I18n 1.1.x. For more info see: https://github.com/svenfuchs/i18n/releases/tag/v1.1.0 Successfully installed i18n-1.7.0 Fetching: ffi-1.11.1.gem (100%) Building native extensions. This could take a while… Successfully installed ffi-1.11.1 Fetching: sassc-2.2.1.gem (100%) Building native extensions. This could take a while… Successfully installed sassc-2.2.1 Fetching: jekyll-sass-converter-2.0.1.gem (100%) ERROR: Error installing jekyll: jekyll-sass-converter requires Ruby version >= 2.4.0.
Which means that we need to upgrade Ruby, easily done with brew.
Simply install latest Ruby with Homebrew:
greys@mcfly:~/proj/gleb.reys.net $ brew install ruby
...
greys@mcfly:~/proj/gleb.reys.net $ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18]
Install Jekyll 4 gem
Now let's try installing Jekyll 4 again:
greys@mcfly:~/proj/gleb.reys.net $ sudo gem install jekyll Password: Jekyll 4.0 comes with some major changes, notably: Ourlink
tag now comes with therelative_url
filter incorporated into it. You should no longer prepend{{ site.baseurl }}
to{% link foo.md %}
For further details: https://github.com/jekyll/jekyll/pull/6727 Ourpost_url
tag now comes with therelative_url
filter incorporated into it. You shouldn't prepend{{ site.baseurl }}
to{% post_url 2019-03-27-hello %}
For further details: https://github.com/jekyll/jekyll/pull/7589 Support for deprecated configuration options has been removed. We will no longer output a warning and gracefully assign their values to the newer counterparts internally. Successfully installed jekyll-4.0.0 Parsing documentation for jekyll-4.0.0 Done installing documentation for jekyll after 0 seconds 1 gem installed
That's it – Jekyll is ready for developing static websites!
See Also
How To Change Mac Hostname with scutil
Standard command like hostname will still work in macOS, but perhaps it's best to use the native way of updating system information on your Mac? scutil command is here to help.
Change Hostname with scutil
Simply run this command in your Terminal window:
greys@macbook:/ $ sudo scutil --set HostName "maverick"
if you now start new Terminal window or even just start new shell, you should see the new hostname:
greys@macbook:/ $ sudo scutil –set HostName "maverick"
greys@macbook:/ $ bash
greys@maverick:/ $ hostname
maverick
That's it for today!
See Also
Protecting Directories with Sticky Bit
One of the least used and usually forgotten features in Linux/Unix filesystems, sticky bit is a great way to manage regular user access to a shared directory.
[Read more…] about Protecting Directories with Sticky Bitneofetch in Debian Linux
When it comes to reporting basic OS information in one terminal screen for easy screenshot, I've been using screenFetch most of the time. Turns out, it's not the only software of this kind – and neofetch is a great alternative.
neofetch or screenFetch?
Notice how I didn't say netofetch VS screenFetch!
Because mostly the choice between neofetch and screenFetch is a personal preference: both tools are quite capable and available on majority of popular operating systems.
Reasons to use neofetch
Compared to screenFetch, neofetch has a few really cool features:
- Server hardware model reported
- On desktop systems, the following is reported
- Windows manager and sometimes even desktop theme
- Screen resolution
- Better reporting of IP addresses
- Lots of configuration options