Linux systems are complicated things. Out of the box, every distribution includes a number of services meant to help you get things up and running. Some distributions enable fewer services by default, and some enable more. The difference is in convenience. Some distributions try to get you up and running quickly, so they have a large set of default services enabled to make it easier for you to get set up, logged in, and configured. Others take the opposite approach and install almost nothing by default.
This article is the start of a short series, where we’ll talk a bit about hardening, a bit about segmentation, and finally how to scan our networks to see if we got it right. So hang on and let me show you through a few layers of defense.
Install less software
When I install a new system, I try to install as little as possible. I start with the base package set and really install nothing else. It’s simple to add services after installation, so why complicate the process? Besides, if you’re doing this a lot, you’ll probably want to install from a Kickstart (or template) system. So, you’d want that set up as simply and generically as possible.
For this article, I installed a base Red Hat Enterprise Linux (RHEL) 7.6 system to do some real testing. I did the bare minimum during installation, selecting the base
package set and setting up my passwords, usernames, and network. I also enabled the Network Time Protocol (NTP).
Identify open ports
After the installation, we can see the list of open ports. Ports are how services running on your server allow other systems to connect to them. A web server, for example, will bind ports 80 and 443 to the web server’s service. In this article, we’ll identify what services have open ports in your base installation, and then look at how to list services and disable the ones we don’t want.
On a Red Hat Enterprise Linux 7.6 system, we use the ss
command to see this information. On systems that still ship with netstat
, you’ll use the netstat
command.
Running ss
on our test system shows a few open ports:
[root@rhel76test ~]# ss -tulnp --no-header | awk '{print($1, $5, $7)}'
udp *:68 users:(("dhclient",pid=3316,fd=6))
udp 127.0.0.1:323 users:(("chronyd",pid=2974,fd=1))
udp ::1:323 users:(("chronyd",pid=2974,fd=2))
tcp *:22 users:(("sshd",pid=3523,fd=3))
tcp 127.0.0.1:25 users:(("master",pid=3771,fd=13))
tcp :::22 users:(("sshd",pid=3523,fd=4))
tcp ::1:25 users:(("master",pid=3771,fd=14))
It looks like RHEL 7.6 base isn’t bad. Notice in the second column, some of the open ports show an IP and then a port, and others have a *
and then a port. The entries that look like 127.0.0.1:25
mean they’re just listening on localhost. This result means that they’re not remotely accessible. The services that look like *:22
mean they’re listening on any interface. Likewise, for the IPv6 addresses, we’ve got ::1:323
, and :::22
. The ::1
entries are localhost, the :::
’s are wide open.
What all this means is that this system has only two IPv4 ports, and one IPv6 port, open to the world. The dhclient
service is probably a good example of something we could disable (which would close its port), but only if your server isn't using DHCP to get its IP address. In the case of my test server, it is.
Disable services
Listing services and stopping/disabling them is relatively easy on Red Hat Enterprise Linux 7. We’ll use systemd
to list all of the active units, and then tell it to stop and disable the ones we don’t want running.
To list all running services, you can use systemctl list-units --type=service --state=running
. On my test system, the result shows a very modest 19 services, and most of them look like they’re necessary. We’ll pick one to demonstrate with, though:
[root@rhel76test ~]# systemctl list-units --type=service --state=running
UNIT LOAD ACTIVE SUB DESCRIPTION
auditd.service loaded active running Security Auditing Service
chronyd.service loaded active running NTP client/server
crond.service loaded active running Command Scheduler
dbus.service loaded active running D-Bus System Message Bus
firewalld.service loaded active running firewalld - dynamic firewall daemon
getty@tty1.service loaded active running Getty on tty1
lvm2-lvmetad.service loaded active running LVM2 metadata daemon
NetworkManager.service loaded active running Network Manager
polkit.service loaded active running Authorization Manager
postfix.service loaded active running Postfix Mail Transport Agent
qemu-guest-agent.service loaded active running QEMU Guest Agent
rhnsd.service loaded active running LSB: Starts the Spacewalk Daemon
rhsmcertd.service loaded active running Enable periodic update of entitlement certificates.
rsyslog.service loaded active running System Logging Service
sshd.service loaded active running OpenSSH server daemon
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running Login Service
systemd-udevd.service loaded active running udev Kernel Device Manager
tuned.service loaded active running Dynamic System Tuning Daemon
Let’s say we didn’t want Postfix loaded at boot. We’d simply use systemctl stop postfix
, and then systemctl disable postfix
, like so:
[root@rhel76test ~]# systemctl stop postfix
[root@rhel76test ~]# systemctl disable postfix
Removed symlink /etc/systemd/system/multi-user.target.wants/postfix.service.
[root@rhel76test ~]# systemctl list-units --type=service --state=running | grep postfix
Now, you probably don’t want to disable Postfix, but you get the point.
Wrapping up
So, there you have it. I learned something today: Out of the box, Red Hat Enterprise Linux 7.6 is pretty neat and tidy. I hope you learned how to look for and disable services to lower your attack surface.
Tune in for the next installment of this series, where I’ll talk about network segmentation and firewalling
Thanks for reading!
About the author
Nate is a Technical Account Manager with Red Hat and an experienced sysadmin with 20 years in the industry. He first encountered Linux (Red Hat 5.0) as a teenager, after deciding that software licensing was too expensive for a kid with no income, in the late 90’s. Since then he’s run everything from BBS’s (remember those?) to derby hat’s containing raspberry pi’s, to Linux systems in his basement, or in enterprise-class data-centers.
He runs his own blog at undrground.org, hosts the Iron Sysadmin Podcast, and when he’s not at a command line, he’s probably in the garage tinkering on his Jeep, or out on the trails.
More like this
Browse by channel
Automation
The latest on IT automation for tech, teams, and environments
Artificial intelligence
Updates on the platforms that free customers to run AI workloads anywhere
Open hybrid cloud
Explore how we build a more flexible future with hybrid cloud
Security
The latest on how we reduce risks across environments and technologies
Edge computing
Updates on the platforms that simplify operations at the edge
Infrastructure
The latest on the world’s leading enterprise Linux platform
Applications
Inside our solutions to the toughest application challenges
Original shows
Entertaining stories from the makers and leaders in enterprise tech
Products
- Red Hat Enterprise Linux
- Red Hat OpenShift
- Red Hat Ansible Automation Platform
- Cloud services
- See all products
Tools
- Training and certification
- My account
- Customer support
- Developer resources
- Find a partner
- Red Hat Ecosystem Catalog
- Red Hat value calculator
- Documentation
Try, buy, & sell
Communicate
About Red Hat
We’re the world’s leading provider of enterprise open source solutions—including Linux, cloud, container, and Kubernetes. We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.
Select a language
Red Hat legal and privacy links
- About Red Hat
- Jobs
- Events
- Locations
- Contact Red Hat
- Red Hat Blog
- Diversity, equity, and inclusion
- Cool Stuff Store
- Red Hat Summit