These days, security is a hot topic, especially for servers. The Red Hat server distribution provides many security features by default to help keep your server safe, but depending on your environment, you may need to still do some tweaking. This chapter explores three areas where you should consider making changes to the security of your server.
As discussed in Chapter 17, “Exploring Ubuntu Security,” Linux systems utilize three types of user accounts:
Because of its power, the root
user account can be somewhat dangerous to have active on your Linux server. As discussed in Chapter 17, the Ubuntu server distribution blocks the ability to log in or change to the root
user account to help manage the security environment. However, that's not the case in the Red Hat server distribution.
If you check in a Red Hat environment, the root
user account exists:
$ getent passwd root
root:x:0:0:root:/root:/bin/bash
$
This account should have been assigned a password at the time of installation:
$ sudo getent shadow root
[sudo] password for sysadmin:
root:$6$P92P.wjWGerpM8Zz4PqYcSfIn6UqS1hLY.K7aNEdpEssjK8ES6C1::0:99999:7:::
$
Because the root
user account is active in the Red Hat server, there are a few things that you should be careful about when using a Red Hat server. This section walks through a few security practices related to the root
user account you should consider when working on a Red Hat server.
If the root
user account is active on your Linux server, it's always a good idea to monitor the times it's used on your server. You can do that using the aulast
command. The aulast
command displays a list of users who have logged into the system as found in the system audit logs. Listing 18.1 shows a sample output.
The second column in the aulast
output shows the terminal the root user account logged in from. If the terminal was a remote terminal (such as an SSH connection), the third column shows the IP address of the remote device. It's a good idea to monitor this on a regular basis to watch for unknown login activity.
The OpenSSH software package includes an SSH server that allows connections from remote clients using the secure SSH protocol. The /etc/ssh/sshd_config
file controls the behavior of the SSH server. By default, the configuration used in Red Hat servers allows the root
user account to log in from a remote device. To prevent the root
user account from logging in from a remote device using the SSH protocol, you'll need to modify the configuration file.
The line in the configuration file that allows this feature is as follows:
PermitRootLogin yes
To block access for the root
user account, edit the line to the following:
PermitRootLogin no
Then restart the OpenSSH service for the change to take effect:
$ sudo systemctl restart sshd
After restarting OpenSSH, you should now be denied access as the root
user account in a remote SSH connection:
login as: root
root@192.168.1.81's password:
Access denied
root@192.168.1.81's password:
Now the root
user account can log in only from a console device on the server.
If you allow administrators on the Linux server to log in using the root
user account, it's a good idea to set a timeout for the Bash shell. An unattended Bash shell prompt with the root
login is a huge security risk for your Linux server environment.
The timeout feature in the Bash shell is controlled by the TMOUT
environment variable. To implement a shell timeout, you just need to set the TMOUT
environment variable to the number of seconds you want an idle session to terminate.
For the setting to apply to all logins, you should enable it in the /etc/profile
script, which the Bash shell runs at each login. However, to make adding login scripts easier, Red Hat systems also look for scripts in the /etc/profile.d
directory. You can create a file in the /etc/profile.d
directory that sets the TMOUT
environment variable, and it will run each time a user account logs into the system and opens a Bash shell. It's also a good idea to make the TMOUT
environment variable read-only so users can't override that feature. You do that with the readonly
command.
So to implement this feature, all you need to do is create the file /etc/profile.d/timeout.sh
and include these two lines:
TMOUT=300
readonly TMOUT
In this example, we set the timeout to 300 seconds (5 minutes). Now if any user account session on the server sits idle for 5 minutes (300 seconds), the server will terminate the session.
If you prefer for your Red Hat server to block all access to the root
user account similar to what Ubuntu does, you can do that as well. There are a couple of ways to do that:
root
user account.root
user account the special nologin
shell.While Ubuntu's method of using the asterisk as a password is perfectly valid, it's not typically the preferred way of blocking access from a user account. The /sbin/nologin
file is a special program that displays a message to the user and then exits. To activate it, just set it as the default shell for the root
user account in the /etc/passwd
file:
root:x:0:0:root:/root:/sbin/nologin
Then when you try to log in using the root
user account, you'll see the default warning message and be disconnected:
$ ssh root@localhost
root@localhost's password:
Last login: Sat Mar 13 10:34:55 2021 from ::1
This account is currently not available.
Connection to localhost closed.
$
You can customize the message that appears by creating the /etc/nologin.txt
file and entering the following text message:
# echo &c.dblgr;The root account not available. Please use sudo to gain root
Privileges.˝ > /etc/nologin.txt
Now when you attempt to log in using the root
user account, you'll see the custom message:
$ ssh root@localhost
root@localhost's password:
Last login: Sat Mar 13 10:36:21 2021 from ::1
The root account is not available. Please use sudo to gain root privileges.
Connection to localhost closed.
$
In Chapter 13, “Managing Users and Groups,” we introduced the concept of file and directory permissions. By default, Linux uses two layers of file and directory protection:
As discussed in Chapter 17, in Linux you can take file and directory security even further by implementing Mandatory Access Control (MAC) security. MAC security allows you to set policy rules for controlling access between various types of objects on the Linux system, including users, files, directories, memory, network ports, and processes. Each time a user or process attempts to access any object on the Linux system, the MAC security software intercepts the attempt and evaluates it against any defined policy rules.
The Red Hat Linux distribution uses the Security-Enhanced Linux (SELinux) application to provide MAC security. SELinux is a project of the United States National Security Agency (NSA) and has been integrated into the Linux kernel since version 2.6.x. It is now a standard part of Red Hat-based Linux distributions, including Fedora and CentOS, and an optional install for Debian-based distributions.
SELinux implements MAC security by allowing you to set policy rules for controlling access between various types of objects on the Linux system, including users, files, directories, memory, network ports, and processes. Each time a user or process attempts to access an object on the Linux system, SELinux intercepts the attempt and evaluates it against the defined policy rules.
The /etc/selinux/config
file controls the basic operation of SELinux. There are two primary settings that you need to set:
enforcing
to enable the policy rules on the system and block any unauthorized access. By setting this to permissive
, SELinux monitors policy rules and logs any policy violations, but doesn't enforce them. The disabled
setting value completely disables SELinux from monitoring actions on the system.targeted
setting is the default and only enforces network daemon policy rules. The mls
setting uses multilayer security, providing advanced policies following the Bell-LaPadula model of security control. The strict
setting enforces policy rules for all daemons but is not recommended for use anymore.To change the state of SELinux, you can also use the setenforce
utility from the command line. However, you can only use the utility to change SELinux between enforcing and permissive modes. To disable SELinux, you must make the change in the SELinux configuration file manually. To see the current mode of SELinux, use the getenforce
utility:
$ sudo getenforce
Enforcing
$
For a more detailed listing of the SELinux status, use the sestatus
utility:
$ sudo sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Memory protection checking: actual (secure)
Max kernel policy version: 32
$
Once you've enabled SELinux, it starts enforcing access rules on the objects defined in a set of policies. The next sections explain how SELinux policies work.
SELinux labels each object on the system with a security context. The security context defines what policies SELinux applies to the object. The security context format is as follows:
user:role:type:level
The user
and role
attributes are only used in the multilayer security mode and can get quite complex. Systems running in the default targeted
security mode only use the type
attribute to set the object security type, and control access based on that. The level
attribute sets the security sensitivity level and clearance level. It is optional under the targeted security mode and is mostly used in high-secure environments.
To view the security context assigned to objects, add the -Z
option to common Linux commands such as id
, ls
, ps
, and netstat
. For example, to view your user security context, use the following:
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$
The unconfined_u
user security context means the user account is not assigned to a specific security policy. Likewise, the unconfined_r
for the role and the unconfined_t
for the type also mean no security policy is assigned. The level security context of s0-s0:c0.c10123
means the security and clearance levels for the object are also not set.
To view the security context for a file, use the following:
$ ls -Z test1.txt
unconfined_u:object_r:user_home_t:s0 test1.txt
$
Again, the user and role attributes are unconfined, but now the type attribute is set to user_home_t
. You can use this attribute in a security policy to set the access for files in each user account's $HOME
directory.
To examine the security context assigned to a process, use this:
$ ps -axZ | grep firewalld
system_u:system_r:firewalld_t:s0 899 ? Ssl 0:00
/usr/libexec/platform-python -s /usr/sbin/firewalld --nofork --nopid
$
The process required for the firewalld
firewall application is set to the system_u
user security context and the system_r
role security context. These indicate the process is system-related. Notice that the type security context contains the program name; each program has its own security context. This means you can control each program running on the system with separate policies. SELinux assigns policies to each object on the system when SELinux is first enabled, which can be a long process, so be prepared if you're first enabling SELinux on your system.
The semanage
utility allows you to view and set the security context for user accounts on the system. For files and directories, the Linux system sets their security context when they are created, based on the security context of the parent directory. You can change the default security context assigned to a file by using the chcon
or restorecon
utilities.
The chcon
format is as follows:
chcon -u newuser -r newrole -t newtype filename
The newuser
, newrole
, and newtype
values define the new user, role, and type security contexts you want assigned to the specified file.
The restorecon
utility restores the security context of a file or directory back to the default settings as defined in the policies. You can use the -R
option to recursively restore the security context on all files under a specified directory.
The runcon
utility allows you to start an application with a specified security context, but be careful. If an application starts without having access to any required configuration or logging files, strange things can, and usually will, happen.
SELinux controls access to system objects based on policies. In the targeted security mode, each policy defines what objects within a specific type security context can access objects within another type security context. This is called type enforcement.
For example, an application labeled with the type security context firewalld_t
is only allowed to access files labeled with the type security context firewalld_t
. This restricts access from the application to only certain files on the system.
SELinux maintains policies as text files within the /etc/selinux
directory structure. For example, all policies for the targeted security mode are under the /etc/selinux/targeted
directory.
Creating your own policies can be somewhat complicated. Fortunately, SELinux includes policy groups, called modules, that you can install as standard rpm packages. Use the semodule
utility to list, install, and remove policy modules in your system.
To make things even easier for us, SELinux uses a method of enabling and disabling individual policies without having to modify a policy file. A Boolean is a switch that allows you to enable or disable a policy rule from the command line based on its policy name. To view the current setting of a policy, use the getsebool
command:
$ getsebool antivirus_can_scan_system
antivirus_can_scan_system --> off
$
To view all of the policies for the system, include the -a
option, as shown in Listing 18.2.
Listing 18.2 just shows a partial output from the getsebool
command; there are lots of different policies installed by default in most Red Hat Linux environments.
To change the Boolean setting, use the setsebool
command:
$ sudo setsebool antivirus_can_scan_system on
$ getsebool antivirus_can_scan_system
antivirus_can_scan_system --> on
$
This setting applies only to your current session. To make the change permanent, you must add the -P
option to the command. This gives you full control over the policy settings defined for SELinux.
Firewall software helps protect your Linux server from unwanted network access. It uses ACLs to define what network connections can be allowed and which ones should be blocked.
The Red Hat Linux distribution uses the firewalld
software package to provide firewall services. This section describes the firewalld
program and shows how you can use it to help protect your Red Hat server on different types of networks.
The firewalld
software uses the concept of zones to define protection for the network interfaces on your Red Hat server. A zone defines the type of network the interface is connected to and what type of network traffic should be allowed or blocked. Different types of network connections require different levels of protection. For example, consider the network shown in Figure 18.1.
In Figure 18.1, the Linux server has two network interfaces. Network card A is connected to a home network, which includes other network devices that need to connect to the Linux server. Network card B in the server is connected to the Internet. You most likely will want to define different ACL rules for each network interface. Network card A should allow the local clients to connect to server resources, such as shared files, printers, and possibly even establish SSH connections to login.
However, network card B needs extra security protections so that unknown attackers lurking on the Internet can't gain access to your server. With a myriad of different network applications and protocols, you can see how it would quickly become difficult to keep things straight on the system.
The solution is to implement zone-based ACL rules. The firewalld
program allows you to define multiple zones and assign each zone a different set of rules to control network access. Typically, each network interface on the server is assigned to a specific zone, based on the network requirements. The firewalld
program applies the zone rules to the network interface.
By default, the Red Hat server defines 10 zones. You can list the currently defined zones using the firewall-cmd
command:
$ firewall-cmd --get-zones
block dmz drop external home internal nm-shared public trusted work
$
Table 18.1 provides a basic description of what each of these default zones is used for.
TABLE 18.1 The Default firewalld
Zones
ZONE | DESCRIPTION |
---|---|
block |
Rejects all incoming network connections and sends an ICMP prohibited message. Only outgoing network connections are allowed. |
dmz |
Only selected incoming connections are accepted. |
drop |
Rejects all incoming network connections with no reply message. Only outgoing network connections are allowed. |
external |
Enables masquerading feature to hide the server's true IP address. Only specified incoming connections are accepted. |
home |
Allows only specified incoming connections, but all outgoing connections are allowed. |
internal |
Only specified incoming connections are accepted. |
nm-shared |
Special zone defined for sharing on the network. |
public |
For use on untrusted networks; only select incoming connections are accepted. |
trusted |
All network connections are accepted. |
work |
For use on mostly trusted networks; only select incoming connections are accepted. |
Each zone has a different set of rules assigned to it, controlling what network traffic can come in or go out from network interfaces assigned to that zone. To manage the access on a network interface, you just assign it to a specific zone.
Besides zones, firewalld
uses ACL rules. The ACL rules define what network connections should be allowed or blocked. With firewalld
, you can define the rules using two different methods:
By using service names, you can allow or block connections by application, such as FTP, SSH, or HTTP. By using ports, you can allow or block connections based on TCP or UDP port numbers.
The following sections show you how to use firewalld
in your Red Hat server environment.
While the firewalld
program uses standard text configuration files, you can use the firewall-cmd
command-line command for most of the things you need to do. To check if firewalld
is running, just use the following command:
$ sudo firewall-cmd --state
running
$
You can check what zone a specific interface is currently in by using the --get-zone-of-interface
option:
$ sudo firewall-cmd --get-zone-of-interface=enp0s8
public
$
Or, if you have multiple network interface cards, you can use the --get-active-zones
option to list all zones that are currently active on network interfaces:
$ sudo firewall-cmd --get-active-zones
public
interfaces: enp0s3, enp0s8
$
You can see the current configuration for a zone by using the --list-all
option and specifying the zone name using the --zone
option:
$ sudo firewall-cmd --zone=public --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s8
sources:
services: cockpit dhcpv6-client ssh
ports: 631/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
$
The output shows the features and what items are allowed through the firewall for that zone. The target
feature defines the action for the zone:
The sources
, services
, ports
, and protocols
features define the rule items that are either allowed or blocked, based on the target setting. In this example, the Red Hat web cockpit service, the DHCPv6 client service, and the OpenSSH service are all allowed. Likewise, traffic on TCP port 631 (the CUPS application, described in Chapter 16, “Managing Printers”) is allowed.
Besides the default zones, you can create your own zones to help customize your server's network environment. The --new-zone
option of the firewall-cmd
command defines the zone name:
$ sudo firewall-cmd --permanent --new-zone=mytest
Success
$
The --permanent
option is required to make the change permanent in the configuration files. Before you can use the zone, you must tell firewalld
to reload the configuration file so it knows about the new zone:
$ sudo firewall-cmd --reload
Success
$
Then you can list the zones to see if the new zone exists:
$ sudo firewall-cmd --get-zones
block dmz drop external home internal mytest nm-shared public trusted work
$
Once you've created the zone, you can move a network interface to the zone using the --add-interface
option:
$ sudo firewall-cmd –zone=mytest --add-interface=enp0s8
Success
$
Be careful, though, as the new zone doesn't have any ACL rules applied to it:
$ sudo firewall-cmd --zone=mytest --list-all
mytest
target: default
icmp-block-inversion: no
interfaces:
sources:
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
$
If you add the network interface that you're currently connected to the server, this will cause your connection to drop and possibly be a problem! The next section shows how you can add rules to the zones.
ACL rules are the core of the firewall. They define what type of network traffic is allowed or blocked by the network interface. Mistakes when adding or removing rules can be costly, especially if you're remotely connected to the server!
The firewalld
program is robust in how it allows you to define rules. You can define rules to allow or block access based on a well-known application service name by using the --add-service
option:
$ sudo firewall-cmd --zone=mytest --add-service=https --permanent
success
$ sudo firewall-cmd --reload
success
$ sudo firewall-cmd --zone=mytest --list-all
mytest
target: default
icmp-block-inversion: no
interfaces:
sources:
services: https
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
$
Notice again that you should add the --permanent
option to ensure the new rule applies when the system reloads.
You can also specify rules as TCP or UDP port values:
$ sudo firewall-cmd --zone=mytest --add-port=631/tcp --permanent
success
$ sudo firewall-cmd --reload
success
$ sudo firewall-cmd --zone=mytest --list-all
mytest
target: default
icmp-block-inversion: no
interfaces:
sources:
services: https
ports: 631/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
$
The
program also uses what it calls rich rules, which allow you to customize a rule to specify a specific object, such as a single IP address and a port or service:
$ sudo firewall-cmd --zone=mytest --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.70 port port=22 protocol=tcp reject'
success
$ sudo firewall-cmd --reload
success
$
This rich rule example rejects SSH packets (port 22) coming from a specific source address, 192.168.1.70. The command applies this rich rule to the mytest
zone. You can then check if the rule was applied:
$ sudo firewall-cmd --zone=mytest --list-all
mytest
target: default
icmp-block-inversion: no
interfaces:
sources:
services:
ports: 631/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule family="ipv4" source address="192.168.1.70" port port="22"
protocol="tcp" reject
$
With the firewalld
program, you can lock down your Red Hat server as tight as you need, only opening it up to specific network clients.
root
user account by default, which could cause security issues if not managed correctly. You should always check for uses of the root
user account by using the aulast
command to view the logins on the server. Depending on your environment, you may also want to restrict the root
user account from accessing the server from a remote device. You can do that using the /etc/ssh/sshd_config
configuration file in OpenSSH. Finally, if you do allow root
user access on your system, it's a good idea to restrict the idle time at the command prompt. You do that using the TMOUT
environment variable.
firewalld
. In today's world, managing access to the Linux server is a must, especially if your Linux server has some type of connection to the Internet. Red Hat servers utilize the firewalld
program to block unwanted network connections and allow approved connections on the network. The firewalld
program defines connections as rules and applies those rules to specific zones. You can then assign network interfaces to the zone that supports the network connections needed.