DEV Community

Janak Shrestha
Janak Shrestha

Posted on

Add Response Headers in Apache

We are working on hardening Apache web server on all app servers. As a part of this process we want to add some of the Apache response headers for security purpose. We are testing the settings one by one on all app servers. As per details mentioned below enable these headers for Apache:

  1. Install httpd package on App Server 2 using yum and configure it to run on 3000 port, make sure to start its service.
  2. Create an index.html file under Apache's default document root i.e /var/www/html and add below given content in it. Welcome to the xFusionCorp Industries!
  3. Configure Apache to enable below mentioned headers: X-XSS-Protection header with value 1; mode=block X-Frame-Options header with value SAMEORIGIN X-Content-Type-Options header with value nosniff

Note: You can test using curl on the given app server as LBR URL will not work for this task.


Configuring Apache with Security Headers on a Custom Port

A Deep Dive for System Administrators


Introduction

Web server hardening is a critical part of securing modern infrastructure. One of the most effective ways to harden Apache is by adding HTTP response headers that instruct browsers to enforce security policies. These headers protect against common web vulnerabilities such as cross-site scripting (XSS), clickjacking, and MIME-type sniffing attacks.

This guide walks through a complete implementation on a CentOS Stream 9 server. The task involves installing Apache, running it on a custom port, creating a test page, and enabling three specific security headers. Each step is explained in depth to build a strong understanding of the underlying concepts.


Environment Details

Component Value
Server stapp02
User steve
Password Am3ric@
OS CentOS Stream 9
Apache Version 2.4.62
Custom Port 3000
Document Root /var/www/html

Understanding the Security Headers

Before diving into the configuration, it is essential to understand what each header does and why it matters.

X-XSS-Protection

This header enables the browser's built-in Cross-Site Scripting (XSS) filter. When set to 1; mode=block, the browser detects reflected XSS attacks and blocks the page from rendering rather than attempting to sanitize it. While modern browsers rely more on Content Security Policy, this header still provides protection for older browsers.

X-Frame-Options

This header prevents clickjacking attacks by controlling whether a page can be embedded in a frame or iframe. Setting it to SAMEORIGIN allows only pages from the same origin to embed the content. Attackers cannot trick users into clicking hidden elements on a different site.

X-Content-Type-Options

This header set to nosniff prevents browsers from guessing the MIME type of a file. Without this header, a browser might interpret a text file as JavaScript or HTML, leading to security vulnerabilities. Setting it to nosniff forces the browser to trust the server's declared Content-Type.

Summary Table

Header Value Protection
X-XSS-Protection 1; mode=block Cross-site scripting
X-Frame-Options SAMEORIGIN Clickjacking
X-Content-Type-Options nosniff MIME sniffing

Step 1: Connect to the Server

Access the server using SSH.

ssh steve@stapp02
Password: Am3ric@
Enter fullscreen mode Exit fullscreen mode

Switch to root to perform administrative tasks.

sudo su -
Password: Am3ric@
Enter fullscreen mode Exit fullscreen mode

The sudo command provides elevated privileges required for installing packages and editing system configuration files.


Step 2: Install the httpd Package

Install Apache using the yum package manager.

yum install -y httpd
Enter fullscreen mode Exit fullscreen mode

The installation pulls in several dependencies.

Package Purpose
httpd Main Apache server
httpd-core Core server binary
httpd-tools Utilities like apachectl
apr Apache Portable Runtime
apr-util Utility library for APR
mod_http2 HTTP/2 protocol support
mod_lua Lua scripting support
mailcap MIME type handling

After installation, the httpd.service is registered with systemd.


Step 3: Configure Apache to Listen on Port 3000

By default, Apache listens on port 80. The task requires port 3000. The Listen directive in the main configuration file controls this.

Edit the file at /etc/httpd/conf/httpd.conf.

sed -i 's/^Listen 80/Listen 3000/' /etc/httpd/conf/httpd.conf
Enter fullscreen mode Exit fullscreen mode

Verify the change.

grep "^Listen" /etc/httpd/conf/httpd.conf
Enter fullscreen mode Exit fullscreen mode

Expected output.

Listen 3000
Enter fullscreen mode Exit fullscreen mode

Why Use sed

The sed command performs a search and replace in place. The ^ anchors the match to the start of the line, ensuring only the Listen directive is changed and not other occurrences of 80.


Step 4: Create the Index Page

Create a simple index.html file in the document root.

echo "Welcome to the xFusionCorp Industries!" > /var/www/html/index.html
Enter fullscreen mode Exit fullscreen mode

Verify the content.

cat /var/www/html/index.html
Enter fullscreen mode Exit fullscreen mode

The document root /var/www/html is the default location from which Apache serves files. The DirectoryIndex directive in the configuration tells Apache to look for index.html when a directory is requested.


Step 5: Configure Security Headers

Apache uses the mod_headers module to manipulate HTTP headers. This module is enabled by default on CentOS Stream 9.

Create a dedicated configuration file in the conf.d directory.

cat > /etc/httpd/conf.d/security-headers.conf << 'EOF'
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
EOF
Enter fullscreen mode Exit fullscreen mode

Why Use a Separate Configuration File

Keeping custom configurations in /etc/httpd/conf.d/ is a best practice. Files in this directory are automatically included by the main configuration. This approach avoids modifying the main file and makes it easier to manage changes.

Understanding the Directives

Directive Meaning
Header always set Adds the header to all responses
X-XSS-Protection Header name
"1; mode=block" Header value (quoted)

The always keyword ensures the header is added even to error responses and redirects.


Step 6: Start and Enable the Apache Service

Start the service and configure it to start on boot.

systemctl start httpd
systemctl enable httpd
systemctl status httpd
Enter fullscreen mode Exit fullscreen mode

The status output confirms the service is running and listening on port 3000.

● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
     Active: active (running)
   Main PID: 29475 (httpd)
     Status: "Started, listening on: port 3000"
Enter fullscreen mode Exit fullscreen mode

Understanding systemctl

Command Purpose
systemctl start Starts the service immediately
systemctl enable Configures the service to start on boot
systemctl status Shows the current state

Step 7: Verify Firewall Status

Check if firewalld is active.

systemctl status firewalld
Enter fullscreen mode Exit fullscreen mode

In this environment, firewalld was not installed. If it were active, port 3000 would need to be allowed.

firewall-cmd --zone=public --add-port=3000/tcp --permanent
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Step 8: Verify the Headers

Test the configuration using curl.

curl -I http://localhost:3000/
Enter fullscreen mode Exit fullscreen mode

The output shows the HTTP response headers.

HTTP/1.1 200 OK
Date: Thu, 24 Sep 2026 12:01:11 GMT
Server: Apache/2.4.62 (CentOS Stream)
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Last-Modified: Thu, 24 Sep 2026 11:59:33 GMT
ETag: "27-65c39553de0df"
Accept-Ranges: bytes
Content-Length: 39
Content-Type: text/html; charset=UTF-8
Enter fullscreen mode Exit fullscreen mode

All three headers are present with the correct values.

Filter the output for specific headers.

curl -I http://localhost:3000/ | grep -E "X-XSS|X-Frame|X-Content"
Enter fullscreen mode Exit fullscreen mode

Expected output.

X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Enter fullscreen mode Exit fullscreen mode

Complete Workflow Summary

# 1. Connect to the server
ssh steve@stapp02
sudo su -

# 2. Install httpd
yum install -y httpd

# 3. Configure port 3000
sed -i 's/^Listen 80/Listen 3000/' /etc/httpd/conf/httpd.conf
grep "^Listen" /etc/httpd/conf/httpd.conf

# 4. Create index.html
echo "Welcome to the xFusionCorp Industries!" > /var/www/html/index.html

# 5. Configure security headers
cat > /etc/httpd/conf.d/security-headers.conf << 'EOF'
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
EOF

# 6. Start and enable Apache
systemctl start httpd
systemctl enable httpd
systemctl status httpd

# 7. Configure firewall (if applicable)
systemctl status firewalld
# If active:
# firewall-cmd --zone=public --add-port=3000/tcp --permanent
# firewall-cmd --reload

# 8. Verify
curl -I http://localhost:3000/
curl -I http://localhost:3000/ | grep -E "X-XSS|X-Frame|X-Content"
Enter fullscreen mode Exit fullscreen mode

Verification Checklist

Check Command Expected
Apache installed `rpm -qa \ grep httpd`
Listening on 3000 `ss -tlnp \ grep :3000`
Index page cat /var/www/html/index.html Welcome message
Headers file cat /etc/httpd/conf.d/security-headers.conf Three headers
Service running systemctl is-active httpd active
Service enabled systemctl is-enabled httpd enabled
Headers present curl -I http://localhost:3000/ All three headers

Troubleshooting

Apache Fails to Start

Check the configuration syntax.

httpd -t
Enter fullscreen mode Exit fullscreen mode

Check the error log.

tail -20 /var/log/httpd/error_log
journalctl -u httpd -n 50
Enter fullscreen mode Exit fullscreen mode

Headers Not Appearing

Verify that mod_headers is enabled.

httpd -M | grep headers
Enter fullscreen mode Exit fullscreen mode

If not enabled, uncomment the LoadModule line in /etc/httpd/conf.modules.d/00-base.conf.

Port Already in Use

Check what is listening on port 3000.

ss -tlnp | grep :3000
Enter fullscreen mode Exit fullscreen mode

Stop the conflicting service or choose a different port.

Firewall Blocking Access

Check firewalld status and allow the port if needed.

systemctl status firewalld
firewall-cmd --zone=public --add-port=3000/tcp --permanent
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

SELinux Blocking Port

If SELinux is enforcing, Apache may not be able to bind to port 3000.

semanage port -a -t http_port_t -p tcp 3000
Enter fullscreen mode Exit fullscreen mode

Best Practices

  1. Use a separate configuration file in /etc/httpd/conf.d/ for custom headers.
  2. Always test configuration with httpd -t before restarting.
  3. Use Header always set to ensure headers appear on all responses.
  4. Document the purpose of each header for future reference.
  5. Check both the service status and the actual HTTP response after changes.
  6. Consider Content Security Policy (CSP) for modern XSS protection.
  7. Regularly review and update security headers as standards evolve.

Conclusion

This guide demonstrated the complete process of installing Apache, configuring it to run on a custom port, creating a test page, and enabling three important security headers. Each step was explained with the underlying concepts to build a deep understanding.

The key takeaways are that HTTP response headers provide browser-enforced security controls, Apache configuration is modular and can be extended via files in /etc/httpd/conf.d/, and verification with tools like curl confirms that the configuration is working as intended.

By applying these headers, the web server gains protection against cross-site scripting, clickjacking, and MIME-type sniffing attacks, contributing to a more secure application environment.


Quick Reference

Task Command
Install httpd yum install -y httpd
Change port sed -i 's/^Listen 80/Listen 3000/' /etc/httpd/conf/httpd.conf
Create index echo "Welcome..." > /var/www/html/index.html
Add headers Create /etc/httpd/conf.d/security-headers.conf
Start service systemctl start httpd
Enable service systemctl enable httpd
Test headers curl -I http://localhost:3000/
Check syntax httpd -t

Top comments (0)