Manage SELinux Security in RHEL

Red Hat Enterprise LinuxBeginner
Practice Now

Introduction

In this lab, you will gain hands-on experience managing SELinux security in RHEL. You will learn to change SELinux enforcement modes, both temporarily and persistently, and configure Apache with custom SELinux file contexts. The lab also covers adjusting SELinux policy for user home directories using booleans and provides practical steps for troubleshooting and resolving SELinux denials for Apache web servers and custom web content.

Change SELinux Enforcement Mode

In this step, you will learn how to manage SELinux modes, both temporarily and persistently. SELinux (Security-Enhanced Linux) is a security mechanism that provides mandatory access control (MAC) for the Linux kernel. It defines the access rights for processes, files, and other system resources.

SELinux operates in three primary modes:

  • Enforcing: SELinux policy is enforced. Accesses denied by the policy are blocked and logged. This is the default and most secure mode.
  • Permissive: SELinux policy is not enforced. Accesses denied by the policy are logged but not blocked. This mode is useful for troubleshooting and testing new policies.
  • Disabled: SELinux is turned off. No policy is loaded or enforced. This mode is generally not recommended for production systems.

You will practice changing the SELinux mode using command-line tools and by modifying configuration files.

First, let's check the current SELinux enforcement mode.

  1. Check the current SELinux enforcement mode.

    You can use the getenforce command to quickly see the current SELinux mode.

    getenforce

    You should see Enforcing as the output, indicating that SELinux is currently enforcing its policies.

    Enforcing
  2. Change the SELinux mode to permissive temporarily.

    The setenforce command allows you to change the SELinux mode at runtime. A value of 0 sets the mode to permissive, and 1 sets it to enforcing. This change is temporary and will not persist across reboots.

    sudo setenforce 0

    Now, verify the change using getenforce again.

    getenforce

    The output should now be Permissive.

    Permissive
  3. Change the SELinux mode back to enforcing temporarily.

    To revert the temporary change, use setenforce 1.

    sudo setenforce 1

    Verify the mode once more.

    getenforce

    The output should be Enforcing again.

    Enforcing
  4. Change the default SELinux mode to permissive persistently.

    To make SELinux mode changes persistent across reboots, you need to modify the /etc/selinux/config file. This file defines the default SELinux mode for the system.

    Open the configuration file using nano.

    sudo nano /etc/selinux/config

    Inside the nano editor, find the line that starts with SELINUX= and change its value from enforcing to permissive.

    ## This file controls the state of SELinux on the system.
    ## SELINUX= can take one of these three values:
    ##     enforcing - SELinux security policy is enforced.
    ##     permissive - SELinux prints warnings instead of enforcing.
    ##     disabled - No SELinux policy is loaded.
    SELINUX=permissive
    ## SELINUXTYPE= can take one of these three values:
    ##     targeted - Targeted processes are protected,
    ##                for the majority of users.
    ##     minimum - Modification of targeted policy
    ##               uses current settings and adds to it.
    ##     mls - Multi Level Security protection.
    SELINUXTYPE=targeted

    Press Ctrl+X to exit, then Y to confirm saving, and Enter to write to the same file.

    After saving the file, you can confirm the change in the configuration file using grep.

    grep '^SELINUX' /etc/selinux/config

    The output should show SELINUX=permissive.

    SELINUX=permissive
    SELINUXTYPE=targeted

    Important Note: Changing /etc/selinux/config does not immediately change the active SELinux mode. It only sets the mode that will be applied after the next system reboot. To see the current active mode, you still need to use getenforce.

    getenforce

    It should still show Enforcing because the system has not been rebooted yet.

    Enforcing
  5. Change the default SELinux mode back to enforcing in the configuration file.

    Now, let's change the persistent mode back to enforcing. This is the recommended and most secure setting for SELinux.

    Open the configuration file again.

    sudo nano /etc/selinux/config

    Change the SELINUX= parameter back to enforcing.

    ## This file controls the state of SELinux on the system.
    ## SELINUX= can take one of these three values:
    ##     enforcing - SELinux security policy is enforced.
    ##     permissive - SELinux prints warnings instead of enforcing.
    ##     disabled - No SELinux policy is loaded.
    SELINUX=enforcing
    ## SELINUXTYPE= can take one of these three values:
    ##     targeted - Targeted processes are protected,
    ##                for the majority of users.
    ##     minimum - Modification of targeted policy
    ##               uses current settings and adds to it.
    ##     mls - Multi Level Security protection.
    SELINUXTYPE=targeted

    Save and exit the file (Ctrl+X, Y, Enter).

    Confirm the change in the configuration file.

    grep '^SELINUX' /etc/selinux/config

    The output should now show SELINUX=enforcing.

    SELINUX=enforcing
    SELINUXTYPE=targeted

    At this point, the system's active SELinux mode is still Enforcing (if you didn't reboot after step 4), and the persistent setting is also Enforcing.

Configure Apache with Custom SELinux File Contexts

In this step, you will learn how to configure Apache to serve web content from a non-standard directory and manage its SELinux file contexts. By default, SELinux policies restrict Apache (httpd) to serving files only from specific directories, primarily /var/www/html. If you place web content in a different location, SELinux will prevent Apache from accessing it, even if file system permissions are correct. This is where SELinux file contexts come into play.

An SELinux file context is a label applied to a file or directory that defines its security attributes. For Apache to serve content from a custom location, that location and its contents must have the correct SELinux context, typically httpd_sys_content_t. You will use semanage fcontext to define a persistent rule and restorecon to apply it.

First, you need to install the Apache HTTP server.

  1. Install the Apache HTTP server.

    Use the dnf package manager to install the httpd package.

    sudo dnf install -y httpd

    You should see output indicating the successful installation of the httpd package and its dependencies.

  2. Create a custom directory for web content and an index.html file.

    You will create a new directory named /custom and place a simple index.html file inside it. This will be your non-standard web document root.

    sudo mkdir /custom
    echo 'This is custom web content.' | sudo tee /custom/index.html

    Verify the content of the index.html file.

    cat /custom/index.html
    This is custom web content.
  3. Configure Apache to use the new document root.

    Apache's main configuration file is /etc/httpd/conf/httpd.conf. You need to edit this file to point Apache to your new /custom directory instead of the default /var/www/html.

    Open the configuration file using nano.

    sudo nano /etc/httpd/conf/httpd.conf

    Inside the editor, find the lines DocumentRoot "/var/www/html" and <Directory "/var/www/html">. Change both occurrences of /var/www/html to /custom.

    The relevant sections should look like this after modification:

    #
    ## DocumentRoot: The directory out of which you will serve your
    ## documents. By default, all requests are taken from this directory, but
    ## symbolic links and aliases may be used to point to other locations.
    #
    DocumentRoot "/custom"
    
    #
    ## Relax access to content within /var/www.
    #
    <Directory "/custom">
        AllowOverride None
        ## Allow open access:
        Require all granted
    </Directory>

    Save and exit the file (Ctrl+X, Y, Enter).

  4. Start and enable the Apache web service.

    After modifying the configuration, you need to start the httpd service. Since you are in a container environment, systemctl is not available. You will start httpd directly.

    sudo /usr/sbin/httpd -DFOREGROUND &

    The & symbol runs the command in the background, allowing you to continue using the terminal. You should see output similar to this, indicating Apache is starting.

    [1] 5094
    AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::216:3eff:fe00:63b%eth0. Set the 'ServerName' directive globally to suppress this message

    Note: The warning message about the server's fully qualified domain name is normal in this lab environment and can be safely ignored.

    To verify that Apache is running, you can check for the httpd process.

    ps aux | grep httpd

    You should see several httpd processes running.

    root        ... /usr/sbin/httpd -DFOREGROUND
    apache      ... /usr/sbin/httpd -DFOREGROUND
    ...output omitted...
  5. Attempt to access the web page.

    Now, try to access your web page using curl. Since you are on the same machine, you can use localhost.

    curl http://localhost/index.html

    Note: In this particular environment, you may find that the web page is accessible even with the root_t context. This demonstrates that while SELinux is enforcing, the root_t context may have broader permissions than expected. However, for security best practices and proper SELinux configuration, web content should still use the appropriate httpd_sys_content_t context.

    This is custom web content.
  6. Check the current SELinux context of the custom directory.

    Use the ls -Z command to view the SELinux context of your /custom directory and the index.html file.

    ls -Zd /custom /custom/index.html

    You will notice that they have the root_t context, which is not the recommended context for Apache web content.

    system_u:object_r:root_t:s0 /custom
    system_u:object_r:root_t:s0 /custom/index.html

    Compare this to the default Apache document root:

    ls -Zd /var/www/html

    You will see that /var/www/html has the httpd_sys_content_t context. This is the context you need to apply to your custom directory.

    system_u:object_r:httpd_sys_content_t:s0 /var/www/html
  7. Define a persistent SELinux file context rule for /custom.

    The semanage fcontext command is used to manage SELinux file context mapping rules. The -a option adds a new rule, -t specifies the target type, and the regular expression '/custom(/.*)?' matches the /custom directory itself and all files and subdirectories within it.

    sudo semanage fcontext -a -t httpd_sys_content_t '/custom(/.*)?'

    This command adds the rule to the SELinux policy, but it does not immediately change the contexts of existing files.

  8. Apply the new SELinux contexts to the files.

    The restorecon command is used to restore the SELinux contexts of files and directories to their default values as defined by the policy. The -R option applies the change recursively, and -v provides verbose output.

    sudo restorecon -Rv /custom

    You should see output indicating that the contexts of /custom and /custom/index.html have been relabeled.

    Relabeled /custom from system_u:object_r:root_t:s0 to system_u:object_r:httpd_sys_content_t:s0
    Relabeled /custom/index.html from system_u:object_r:root_t:s0 to system_u:object_r:httpd_sys_content_t:s0

    Verify the contexts again using ls -Z.

    ls -Zd /custom /custom/index.html

    They should now have the httpd_sys_content_t context.

    system_u:object_r:httpd_sys_content_t:s0 /custom
    system_u:object_r:httpd_sys_content_t:s0 /custom/index.html
  9. Access the web page again.

    Now that the SELinux contexts are correct, try accessing the web page with curl again.

    curl http://localhost/index.html

    You should now see the content of your index.html file.

    This is custom web content.

    Finally, stop the Apache HTTP server process.

    sudo pkill httpd

    Verify that no httpd processes are running.

    ps aux | grep httpd

    You should only see the grep process itself.

    labex     ... grep httpd

Adjust SELinux Policy for User Home Directories with Booleans

In this step, you will learn how to adjust SELinux policy using Booleans to allow Apache to serve web content from users' home directories. By default, SELinux prevents services like Apache from accessing files in user home directories for security reasons. However, there are specific scenarios, such as personal web pages, where this functionality is desired.

SELinux Booleans are true/false settings that allow administrators to modify the behavior of the SELinux policy without writing complex custom policies. They provide a flexible way to enable or disable certain security features. For example, there's a Boolean specifically for allowing Apache to access user home directories.

  1. Enable Apache's user directory feature.

    Apache has a module called mod_userdir that allows users to publish web content from a public_html directory within their home directory (e.g., ~/public_html). This feature is typically configured in /etc/httpd/conf.d/userdir.conf. By default, this feature is often disabled.

    Open the configuration file using nano.

    sudo nano /etc/httpd/conf.d/userdir.conf

    Inside the editor, you will find lines related to UserDir. You need to comment out the line that disables UserDir and uncomment the line that enables it for public_html.

    Change:

    UserDir disabled
    #UserDir public_html

    To:

    #UserDir disabled
    UserDir public_html

    Save and exit the file (Ctrl+X, Y, Enter).

  2. Create a public_html directory and an index.html file in your home directory.

    You will create the public_html directory and an index.html file inside it. This is where your personal web content will reside.

    mkdir ~/public_html
    echo 'This is labex user content.' > ~/public_html/index.html

    Verify the content of the index.html file.

    cat ~/public_html/index.html
    This is labex user content.

    Informational: When you created the ~/public_html directory, it was automatically configured with user_home_t and ~/ (your home directory) with home_dir_t SELinux contexts. The Apache web server process (httpd_t) cannot read files labeled user_home_t or home_dir_t by default due to SELinux policy.

  3. Start the Apache web service.

    Start the httpd service. Remember, systemctl is not available in this container environment, so you will start httpd directly.

    sudo /usr/sbin/httpd -DFOREGROUND &

    You may see a warning message about the server's fully qualified domain name, which can be safely ignored in this lab environment.

    Verify that Apache is running.

    ps aux | grep httpd
    root        ... /usr/sbin/httpd -DFOREGROUND
    apache      ... /usr/sbin/httpd -DFOREGROUND
    ...output omitted...
  4. Attempt to access the user's web page and observe the SELinux denial.

    Now, try to access your personal web page using curl. The URL for user directories typically follows the format http://localhost/~username/.

    curl http://localhost/~labex/index.html

    You will likely receive a "Forbidden" error, indicating that Apache is still unable to access the content due to SELinux.

    <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
    <html><head>
    <title>403 Forbidden</title>
    </head><body>
    <h1>Forbidden</h1>
    <p>You don't have permission to access /~labex/index.html
    on this server.<br />
    </p>
    </body></html>
  5. Check SELinux Booleans related to home directories for httpd.

    The getsebool command allows you to view the current state of SELinux Booleans. You can filter the output using grep to find Booleans related to httpd and home directories.

    sudo getsebool -a | grep httpd | grep home

    You should see httpd_enable_homedirs --> off, indicating that this Boolean is currently disabled.

    httpd_enable_homedirs --> off
  6. Enable the httpd_enable_homedirs Boolean persistently.

    The setsebool command is used to change the state of SELinux Booleans. The -P option makes the change persistent across reboots.

    sudo setsebool -P httpd_enable_homedirs on

    Verify that the Boolean is now on.

    sudo getsebool -a | grep httpd | grep home
    httpd_enable_homedirs --> on
  7. Set the correct file permissions for the home directory.

    Even with the SELinux boolean enabled, Apache needs proper file system permissions to access your home directory and the public_html directory. By default, user home directories are not accessible to the Apache user.

    chmod 711 ~
    chmod 755 ~/public_html
    chmod 644 ~/public_html/index.html
  8. Access the web page again.

    Now that both the httpd_enable_homedirs Boolean is enabled and the file permissions are correct, try accessing your personal web page with curl again.

    curl http://localhost/~labex/index.html

    You should now see the content of your index.html file.

    This is labex user content.

    Troubleshooting: If you still encounter access issues even after enabling the boolean and setting file permissions, this demonstrates the multi-layered nature of Linux security. In some environments, additional factors such as:

    • Apache configuration directives in /etc/httpd/conf.d/userdir.conf
    • SELinux file contexts on the home directory structure
    • Additional Apache modules or security settings

    may need to be addressed. The key learning point is understanding how SELinux booleans work in conjunction with traditional file permissions and application-specific configurations.

  9. Stop the Apache HTTP server process.

    Finally, stop the Apache HTTP server process.

    sudo pkill httpd

    Verify that no httpd processes are running.

    ps aux | grep httpd
    labex     ... grep httpd

Troubleshoot SELinux Denials for Apache Web Server

In this step, you will learn how to identify and troubleshoot SELinux security denials, specifically focusing on issues that might prevent the Apache web server from functioning correctly. When SELinux blocks an operation, it logs an "Access Vector Cache" (AVC) denial message. These messages are crucial for understanding why an operation failed and how to resolve it.

You will use tools like auditd (the Linux Auditing System daemon) and sealert to analyze these denial messages. auditd collects system calls and events, including SELinux denials, and stores them in /var/log/audit/audit.log. The sealert tool, part of the setroubleshoot-server package, can parse these logs and provide human-readable explanations and suggested solutions for SELinux denials.

First, you need to ensure auditd and setroubleshoot-server are installed.

  1. Install auditd and setroubleshoot-server.

    sudo dnf install -y audit setroubleshoot-server

    You should see output indicating the successful installation of these packages.

  2. Start the Apache web server and create a problematic file.

    To simulate an SELinux denial, you will create a file with an incorrect SELinux context and try to serve it with Apache.

    First, ensure Apache is running.

    sudo /usr/sbin/httpd -DFOREGROUND &

    Now, create a new directory and an index.html file within it. This time, you will intentionally set an incorrect SELinux context for this file to trigger a denial.

    sudo mkdir /testweb
    echo 'This is a test page.' | sudo tee /testweb/index.html

    By default, /testweb/index.html will likely have the root_t context. Let's confirm.

    ls -Z /testweb/index.html
    system_u:object_r:root_t:s0 /testweb/index.html

    Now, let's configure Apache to serve from /testweb. Open /etc/httpd/conf/httpd.conf.

    sudo nano /etc/httpd/conf/httpd.conf

    Change DocumentRoot and the <Directory> directive to /testweb.

    DocumentRoot "/testweb"
    
    <Directory "/testweb">
        AllowOverride None
        Require all granted
    </Directory>

    Save and exit (Ctrl+X, Y, Enter).

    Restart Apache to apply the configuration changes. Since you are in a container, you need to kill the old process and start a new one.

    sudo pkill httpd
    sudo /usr/sbin/httpd -DFOREGROUND &
  3. Attempt to access the web page.

    Try to access the web page using curl.

    curl http://localhost/index.html

    Important Note: In this environment, you may find that the web page is accessible even with the root_t context, similar to what we observed in Step 2. This demonstrates that while SELinux is enforcing, the root_t context has broader permissions than more restrictive contexts.

    This is a test page.

    However, for the purpose of learning SELinux troubleshooting techniques, we will proceed as if there were a denial. In more restrictive SELinux environments or with different policy configurations, accessing files with inappropriate contexts would indeed generate denials.

  4. Learn about investigating SELinux denials using ausearch.

    The ausearch command is used to query the audit logs. You can search for SELinux AVC denials (-m AVC) that occurred today (-ts today).

    sudo ausearch -m AVC -ts today

    Note: Since the web page was accessible in our environment, you may not see any recent AVC denials related to this specific test. However, this command would normally output detailed audit log entries if there were denials. In a typical denial scenario, you would look for entries related to httpd and /testweb/index.html.

    A typical AVC denial entry would look like this:

    ----
    time->...
    type=AVC msg=audit(...): avc:  denied  { getattr } for  pid=... comm="httpd" path="/testweb/index.html" dev="overlay" ino=... scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:root_t:s0 tclass=file permissive=0
    ...output omitted...

    The key parts in an AVC denial would be:

    • denied { getattr }: The operation that was denied (getting attributes of the file).
    • comm="httpd": The process that was denied (Apache HTTP server).
    • path="/testweb/index.html": The file that was accessed.
    • scontext=system_u:system_r:httpd_t:s0: The SELinux context of the source (Apache).
    • tcontext=system_u:object_r:root_t:s0: The SELinux context of the target (your index.html file).
    • tclass=file: The type of target (a file).

    This output clearly shows that httpd_t (Apache) was denied getattr access to a file with default_t context.

  5. Learn about using sealert for SELinux analysis.

    sealert can parse the audit logs and provide more user-friendly information. You can either run sealert -a to analyze all recent denials or use sealert -l <UUID> if you have a specific UUID from a setroubleshoot message in /var/log/messages.

    sudo sealert -a /var/log/audit/audit.log

    Note: Since we haven't encountered actual denials in this environment, running sealert may not show results related to our /testweb example. However, in a scenario where SELinux denials occur, sealert would analyze the audit log and present a summary.

    A typical sealert output for an httpd context issue would look like this:

    SELinux is preventing /usr/sbin/httpd from getattr access on the file /testweb/index.html.
    
    ***** Plugin catchall_labels (83.8 confidence) suggests *******************
    If you want to allow httpd to have getattr access on the index.html file
    Then you need to change the label on /testweb/index.html
    Do ## semanage fcontext -a -t FILE_TYPE '/testweb/index.html'
    where FILE_TYPE is one of the following:
    httpd_sys_content_t, httpd_sys_script_exec_t, httpd_unconfined_script_exec_t, ...
    
    ***** Plugin httpd_can_network_connect (93.8 confidence) suggests *********
    If you want to allow httpd to connect to the network (for example, to a database)
    Then you must set the httpd_can_network_connect boolean to on.
    Do ## setsebool -P httpd_can_network_connect on
    ...output omitted...

    The sealert output would be very helpful in real denial scenarios. It would explicitly state the problem and suggest solutions, such as changing the label with semanage fcontext -a -t FILE_TYPE '/testweb/index.html' and listing httpd_sys_content_t as a suitable FILE_TYPE.

    Finally, stop the Apache HTTP server process.

    sudo pkill httpd

    Verify that no httpd processes are running.

    ps aux | grep httpd
    labex     ... grep httpd

Resolve SELinux Issues for Custom Web Content

In this final step, you will apply the knowledge gained from the previous troubleshooting exercise to resolve the SELinux denial that prevented Apache from serving content from the /testweb directory. You will use semanage fcontext to define the correct SELinux context for your custom web content and restorecon to apply it.

This process reinforces the understanding of how SELinux contexts work and how to correctly configure them for services like Apache.

  1. Ensure Apache is running and the configuration is in place.

    First, ensure that Apache is configured to serve from /testweb and is running. If you stopped Apache in the previous step, start it again.

    sudo /usr/sbin/httpd -DFOREGROUND &

    Verify that the DocumentRoot in /etc/httpd/conf/httpd.conf is set to /testweb. If not, modify it as done in the previous step.

    grep "DocumentRoot" /etc/httpd/conf/httpd.conf
    DocumentRoot "/testweb"

    Also, confirm that /testweb/index.html exists and has the root_t context.

    ls -Z /testweb/index.html
    system_u:object_r:root_t:s0 /testweb/index.html
  2. Access the web page to confirm current behavior.

    Let's verify that the web page is currently accessible with the root_t context.

    curl http://localhost/index.html

    As we've seen before, the page is accessible even with the root_t context.

    This is a test page.

    While this works, we will proceed to demonstrate the proper SELinux configuration for web content.

  3. Define the correct SELinux file context for /testweb.

    The correct SELinux context for web content served by Apache is httpd_sys_content_t. You need to add a persistent rule using semanage fcontext.

    sudo semanage fcontext -a -t httpd_sys_content_t '/testweb(/.*)?'

    This command tells SELinux that any files or directories within /testweb (including /testweb itself) should be labeled with httpd_sys_content_t.

  4. Apply the new SELinux contexts to the files.

    After defining the rule, you must apply it to the existing files using restorecon.

    sudo restorecon -Rv /testweb

    You should see output indicating that the contexts have been relabeled.

    Relabeled /testweb from system_u:object_r:root_t:s0 to system_u:object_r:httpd_sys_content_t:s0
    Relabeled /testweb/index.html from system_u:object_r:root_t:s0 to system_u:object_r:httpd_sys_content_t:s0

    Verify the contexts again using ls -Z.

    ls -Z /testweb/index.html
    system_u:object_r:httpd_sys_content_t:s0 /testweb/index.html
  5. Access the web page again to confirm proper configuration.

    Now that the SELinux contexts are correctly applied according to best practices, try accessing the web page with curl one more time.

    curl http://localhost/index.html

    The content should still be accessible, and now it's properly configured with the recommended SELinux context.

    This is a test page.

    This demonstrates that while the root_t context may work in this environment, using the proper httpd_sys_content_t context follows SELinux best practices and ensures compatibility across different security configurations.

    Finally, stop the Apache HTTP server process.

    sudo pkill httpd

    Verify that no httpd processes are running.

    ps aux | grep httpd
    labex     ... grep httpd

Summary

In this lab, you learned to manage SELinux security in RHEL. You began by understanding and practicing how to change SELinux enforcement modes, both temporarily using setenforce and persistently by modifying /etc/selinux/config. This included verifying the current mode with getenforce and understanding the implications of Enforcing, Permissive, and Disabled modes.

Furthermore, you gained practical experience in configuring Apache with custom SELinux file contexts using semanage fcontext and restorecon to ensure proper web server operation. You also learned to adjust SELinux policy for user home directories by enabling specific SELinux booleans with setsebool. Finally, the lab covered essential troubleshooting techniques for SELinux denials, specifically for the Apache web server, by analyzing audit logs with ausearch and audit2allow to identify and resolve access issues for custom web content.