How to Secure Nginx Against Host Header Attacks with Simple Config

This article explains why the HTTP Host header is unsafe, demonstrates how attackers can hijack password‑reset links or launch SSRF by forging it, and provides three practical Nginx configuration methods to strictly validate Host values and block malicious requests.

Xiao Liu Lab
Xiao Liu Lab
Xiao Liu Lab
How to Secure Nginx Against Host Header Attacks with Simple Config
When a web application directly uses the client‑provided Host header to generate redirect links, password‑reset URLs, etc., an attacker can inject malicious content into the Host header, leading to password‑reset hijacking, cache poisoning, SSRF and other security risks. This article shows how to configure Nginx to strictly validate the Host header and effectively defend against such attacks.

⚠️ Brief Overview of the Vulnerability

• The Host header in an HTTP request is controlled by the client and therefore untrusted .

• If backend code directly uses $host or $_SERVER['HTTP_HOST'] to build URLs (e.g., https://$host/reset?token=xxx), an attacker can craft a request with Host: evil.com, causing the generated link to become https://evil.com/reset?token=xxx, which can leak credentials or facilitate phishing.

GET / HTTP/1.1
Host: evil.com

This results in users receiving a link such as https://evil.com/reset?token=xxx, leading to credential leakage or phishing attacks.

✅ Core Fix Idea:

Intercept illegal Host requests at the Nginx layer, allowing only predefined legitimate domains to pass.

✅ Method 1: Use Variable Flag (Recommended, Clear Logic)

server {
  listen 80;
  server_name www.xlsys.cn;

  # Host header protection - Jack.Liu 2020.09.16
  set $flag 0;
  if ($host == "www.xlsys.cn") {
    set $flag 1;
  }
  if ($flag = 0) {
    return 403;
  }

  location / {
    root /www/h5;
    index index.php index.html index.htm;
  }
}

Explanation: Initialize a flag variable. If $host matches an allowed domain, set the flag to 1. Finally check the flag; if it remains 0, return 403 Forbidden. This avoids the pitfalls of nested if statements in Nginx.

✅ Method 2: Support Multiple Valid Hosts (Multi‑domain Scenario)

server {
  listen 80;
  server_name www.xlsys.cn;

  set $flag 0;
  if ($host ~* "^(www\.xlsys\.cn|www\.example\.cn|localhost)$") {
    set $flag 1;
  }
  if ($flag = 0) {
    return 403;
  }

  location / {
    root /www/h5;
    index index.php index.html index.htm;
  }
}

Or using multiple equality checks for better readability:

set $flag 0;
if ($host == "www.xlsys.cn") { set $flag 1; }
if ($host == "www.example.cn") { set $flag 1; }
if ($host == "localhost") { set $flag 1; }
if ($flag = 0) { return 403; }

This method suits environments where a main site, sub‑sites, and local testing domains coexist.

✅ Method 3: Use Regular Expression Matching (Flexible but Requires Caution)

server {
  listen 80;
  server_name www.xlsys.cn;

  # Allow: www.xlsys.cn, IP ranges, localhost
  if ($http_Host !~* "^(www\.xlsys\.cn|134\.175\.[0-9]{1,3}\.52|192\.168\.10\.[0-9]{1,3}|175\.6\.[0-9]{1,3}\.12|127\.0\.0\.1)$") {
    return 403;
  }

  location / {
    root /www/h5;
    index index.php index.html index.htm;
  }
}

⚠️ Notes: Use ~* for case‑insensitive regex; escape dots (.) properly. IP ranges are limited with \d{1,3} and should not be relied upon as a sole security measure. Prefer exact matches over complex regex in production.

🧪 Verify Protection Effectiveness

Normal access (should succeed):

curl -H "Host: www.xlsys.cn" http://your-server-ip/

Forged Host (should return 403):

curl -H "Host: evil.com" http://your-server-ip/
# Returns: 403 Forbidden

📌 Best Practice Recommendations

Never trust the Host header; backend applications should use fixed domain names from configuration files to generate URLs.

Use Nginx as the first line of defense: even if the backend performs checks, Nginx interception reduces invalid requests.

Avoid using default_server to serve sensitive content; configure it to return 444 or 403.

Optionally log illegal requests:

if ($flag = 0) {
  access_log /var/log/nginx/host_attack.log;
  return 403;
}

🌟 Summary

By strictly validating $host in Nginx, you can defend against HTTP Host header attacks with low cost and high efficiency. Method 1 (flag variable) or precise multi‑domain matching is recommended, while complex regex should be avoided due to maintenance risks.

Security starts with a single Host header – harden your web service today!
Nginxhost headerSSRFPassword reset hijack
Xiao Liu Lab
Written by

Xiao Liu Lab

An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.