A firewall is a protective layer that is configured between a private and a public network to segregate traffic. There are several types of firewalls one of which performs data packet filtering. A data packet is formed as a result of a process called encapsulation whereby the header information is attached to a message during the formation of a packet. The header includes information such as source and destination IP addresses, port, and type of data. Based on pre-defined rules, a firewall intercepts each inbound and outbound data packet, inspects its header information, and decides whether to allow the packet to pass through. A port is defined in the /etc/services file for each network service available on the system, and are typically standardized across all network operating systems including RHEL. Some common services and the ports they listen on are: ftp on port 21, ssh on 22, telnet on 23, postfix on 25, http on 80, and ntp on port 123.
RHEL comes standard with a host-based packet-filtering firewall software called iptables that can be used to control the flow of data packets. Another major use of iptables in RHEL is to provide support for Network Address Translation (NAT), which is explained in detail in Chapter 14 “Advanced Firewall, TCP Wrappers, Usage Reporting & Remote Logging”.
The configuration file for the iptables firewall is the iptables file located in the /etc/sysconfig directory and the /etc/rc.d/init.d/iptables is the startup script, which reads the configuration file and loads the rules defined in it. The configuration file may be customized using a text editor, the iptables command, the lokkit command, or the Firewall Configuration tool (system-config-firewall or system-config-firewall-tui).
Understanding the iptables Configuration File
As mentioned, the /etc/sysconfig/iptables file is the configuration file for the iptables firewall. This file contains all necessary rules needed to control the inbound and outbound traffic on the system. An excerpt from this file is shown below:
Iptables allows you to define tables containing groups of rules called chains with each table related to a different type of packet processing. In the output above, one default table called filter is defined, which includes three pre-defined chains (INPUT, FORWARD, and OUTPUT) with the INPUT chain containing several rules. Each inbound and outbound packet goes through at least one of the configured chains. Packets destined for the local system use the INPUT chain, packets originated from the local system use the OUTPUT chain, and packets that need to be routed to a different network use the FORWARD chain. Chains have a policy called target, which can have a value such as ACCEPT, REJECT, DROP, and LOG. The ACCEPT policy allows a packet to pass through, the REJECT policy throws a packet away and sends a notification back, the DROP policy simply throws a packet away without sending a notification, and the LOG policy sends packet information to the rsyslogd daemon for logging.
Also notice the string “state” in the file contents above. Some of the common states are NEW, ESTABLISHED, RELATED, and INVALID. The NEW state identifies packets that are not part of an existing communication, the ESTABLISHED state indicates that the packets are part of an existing communication, the RELATED state signifies packets generated in relation with some other existing communication, and the INVALID state identifies packets that do not match other states.
The first rule in the configuration file above will continue to accept all inbound connection requests, the second rule will accept incoming ICMP requests, the third rule will accept all inbound connection requests on the loopback interface, the fourth rule will accept all new matching TCP requests received on port 22, and the last two rules will reject any network packets from any source with the icmp-host-prohibited rejection reason sent back to the source system.
It is imperative that you modify the default iptables rules to match the requirements of packet filtering associated with application accessibility.
The iptables Command
The iptables command is used to modify the firewall rules on the system. This command supports several options, some of which are listed and described in Table 12-1.
Run the iptables command with the –L option to list the rules currently in place on the system:
# iptables –L
The above output indicates that the INPUT, FORWARD, and OUTPUT chains are set to ACCEPT all traffic as explained in the previous sub-section.
Managing iptables Service Start and Stop
The iptables service can be started, restarted, and stopped manually. It can also be configured to start automatically at specific run levels.
To start the iptables service:
# service iptables start
iptables: Applying firewall rules: [ OK ]
To restart the iptables service:
# service iptables restart
iptables: Flushing firewall rules: [ OK ]
To stop the iptables service:
# service iptables stop
iptables: Flushing firewall rules: [ OK ]
To enable the iptables service to autostart at each system reboot:
# chkconfig iptables on
To check the status of the iptables service:
# service iptables status
Exercise 12-1: Add and Manage iptables Rules
In this exercise, you will first delete all existing rules and then append rules to the filter table to allow inbound HTTP traffic on port 80, reject outbound ICMP traffic without sending a notification back, and forward all inbound traffic to 192.168.2.0/24 network. You will insert a rule to allow the first and subsequent incoming FTP connection requests on port 21 and append a rule to disallow all outgoing connection requests on port 25. You will save all these rules in the /etc/sysconfig/iptables file and make necessary settings so that these rules are loaded each time you reboot the system in multiuser mode. You will restart the iptables service and run the command to ensure that the new rules have taken place.
1. Run the iptables command with the –F option to remove all existing rules:
2. Append a rule to the filter table to allow inbound HTTP traffic on port 80:
3. Append a rule to reject outbound ICMP traffic without sending a notification back:
4. Append a rule to forward all inbound traffic to 192.168.2.0/24 network:
5. Insert a rule to allow the first and subsequent incoming FTP connection requests on port 21:
6. Append a rule to disallow all existing and new outgoing connection requests on port 25:
7. Save the rules in the /etc/sysconfig/iptables file and restart the firewall to activate the new rule:
8. Set the iptables firewall service to autostart at each system reboot, and validate:
9. Issue the iptables command and check whether the new rules have taken effect:
Security Enhanced Linux
Security Enhanced Linux (SELinux) is an implementation of the Mandatory Access Control (MAC) architecture developed by the National Security Agency (NSA), with the assistance of other organizations and Linux community, for enhanced, granular security controls in Linux. MAC provides an added layer of protection on top of the standard Linux Discretionary Access Control (DAC) security architecture which includes file and directory permissions, ACLs, and so on. With DAC in use, world-readable user home directories with potentially sensitive data could become the target of unauthorized access. SELinux limits this access by adding appropriate controls on the home directories so that they can only be accessed by authorized processes and users. The added security controls are stored in contexts (or labels) and are applied on files, processes, and users.
SELinux controls are fine-grained meaning that if one service on the system is compromised, other services will remain intact.
SELinux Contexts for Files, Processes, and Users
SELinux contexts define security attributes set on individual files, processes, and users. There are generally four types of attributes associated with the contexts and are referred to as subject, object, action, and level. The subject attribute represents a process or a user, the object attribute identifies a role, the action attribute determines a type, and the level determines the SELinux security level in the form of sensitivity:category. RHEL 6 supports multiple sensitivity levels starting from s0 with 1024 different categories within each sensitivity level.
SELinux allows you to set security policies using type enforcement and role-based access control (RBAC). The type enforcement element identifies the domains for processes and the types for files. The RBAC, or simply a role, element controls which domains and types can be accessed. Each subject has an associated domain and each object within the domain has an associated type. Likewise, each subject has an associated role to ensure that the system and user processes are separated. By default, any process or service that is not explicitly permitted is denied.
Use the –Z option with the ll, ps, and id commands to view the current security contexts on files, processes, and users respectively. The following shows the four attributes currently set on the install.log file and the Desktop directory in the /root directory:
The subject (user) field in the output provides an SELinux user name (system_u, unconfined_u, root, user_u, etc.) that is mapped to a Linux user (root in this case); the object (role) field defines an SELinux role (object_r, system_r, etc.); the action (type) field determines an SELinux type (admin_home_t, user_home_t, etc.); and the level (level) field determines the level of sensitivity & category used as defined in the /etc/selinux/targeted/setrans.conf file. Contexts for all files in the system are stored in the /etc/selinux/targeted/contexts/files/file_contexts file. Notice the dot next to the public execute permission in the first column of the output of the ll command. This dot tells you that the SELinux context is set on this file or directory.
By default, files created in a directory inherit the security contexts set on the directory. If a file is moved to another directory, it takes its security contexts with it, which may differ from the destination directory’s contexts.
In the same manner, you can use the –Z option with the ps command to view the SELinux contexts for running processes:
The subject (user) field in the output provides an SELinux user name (system_u, unconfined_u, root, user_u, etc.) that is mapped to a Linux user; the object (role) field defines an SELinux role (object_r, system_r, etc.) associated with the system process such as daemons; the action (type) field determines what sort of protection is applied to the process (init_t, httpd_t, public_content_t, sshd_exec_t, kernel_t, etc.); and the level (level) field determines the level of sensitivity & category used. Any process that is unprotected will have the action set to unconfined_t.
Likewise, you can use the –Z option with the id command to view the security contexts associated with your Linux user account:
If you run the above command as a normal user, you will get the same output. In RHEL, all Linux users, including root, run unconfined by default, which entails that they have full access to the system and are only restricted by the DAC restrictions. The above output indicates that the root user is mapped to the SELinux unconfined_u user (subject), running as unconfined_r role (role) in the unconfinred_t domain (type) with sensitivity level 0 (level).
SELinux user mappings with Linux users may be viewed using the semanage command. But before you are able to do that, ensure that packages policycoreutils and policycoreutils-python are installed on the system. These packages include several SELinux management commands such as restorecon, chcon, secon, setfiles, semodule, and semanage. You may also want to install the policycoreutils-gui package so that you can manage SELinux graphically using the SELinux Configuration tool system-config-selinux.
If any of these packages are missing on the system, use one of the package management commands explained in Chapter 06 “Package Management” to install it.
Execute the semanage command with the login –l arguments to view the default user mappings:
The above output shows Linux users in the first column mapped to SELinux users in the second column, and the associated sensitivity & category level in the third column.
As stated above, all users including the root user run unconfined by default. If you want to switch a user such as user1 into the staff_u role, run the semanage command. The following example first runs the id command with the –Z option to confirm that user1 is running unconfined and then it switches the role:
Now log off and log back in as user1 and run the id command with the –Z option again to confirm the change:
SELinux Configuration File
The key configuration file for SELinux is /etc/selinux/config and the default contents of it are displayed below:
The SELINUX directive in the file defines the activation mode for SELinux. Enforcing activates SELinux and allows or denies actions based on configured settings. Permissive activates SELinux, but permits all actions. It records all security violations; however, it does not hinder actions being taken. This mode is useful from a troubleshooting perspective, and developing or tuning SELinux security policy. The third option is to completely disable it. When activated in the enforcing mode, the SELINUXTYPE directive dictates the type of policy to be enforced. SELinux supports two policies: targeted and mls (multi-level security). With the targeted policy in place, you can modify SELinux restrictions set on files, processes, and users. The mls policy, on the other hand, allows you to tighten security at more granular levels. The default policy in RHEL6 is the targeted policy.