As a web developer, have you ever overlooked the Host header in HTTP requests? This seemingly ordinary field, once exploited by attackers, can lead to serious security issues such as password reset hijacking, cache poisoning, and even Server-Side Request Forgery (SSRF). This article will start from the vulnerability principle and share 3 battle-tested Nginx defense configuration schemes to help you quickly build the first line of defense for your web application.

1. HTTP Host Header Attack (Host Header Injection): Why Is It So Dangerous?
In the HTTP protocol, the Host header is used to specify the target domain name of the request. But many developers don’t know that: the Host header is completely controlled by the client and belongs to untrusted data. The vulnerability caused by failing to verify the legitimacy of the Host header is called HTTP Host Header Injection Vulnerability, which usually has a medium-low risk level but has a wide range of application scenarios and may trigger serious chain reactions. If the back-end application directly uses this field to generate URLs (such as password reset links, page jump addresses), it will create significant security risks.
Take a typical scenario: A website’s password reset function generates a link through the following code:
$resetUrl = "https://" . $_SERVER['HTTP_HOST'] . "/reset?token=" . $token;
Attackers only need to construct the following request:
GET /forgot-password HTTP/1.1
Host: evil.com
User-Agent: Mozilla/5.0...
The reset link received by the user will become https://evil.com/reset?token=xxx. Once the user clicks, the sensitive token will be leaked to the attacker, leading to account theft. This attack method has extremely low cost but can cause fatal consequences. According to the OWASP Security Testing Guide, Host header injection vulnerabilities are often classified into the “Injection Attacks” category and are one of the common configuration vulnerabilities in web applications.
2. Core Defense Idea: Block Illegal Hosts at the Nginx Layer
The key to defending against Host header attacks is not trusting the Host value passed by the client. The best practice is to verify the legitimacy of the Host header in advance at the Nginx (reverse proxy layer) and only allow predefined legitimate domain names to pass. This can not only reduce the pressure on the back-end application but also block attacks from the source.
Core principle: All Host headers entering the system must be in the whitelist; requests not in the whitelist will directly return 403 Forbidden.
3. 3 Practical Nginx Defense Configuration Schemes
Scheme 1: Single Domain Name Exact Match (Recommended, Clearest Logic)
Applicable to scenarios with only one main domain name. It judges whether the Host is legitimate through a flag bit to avoid the if nesting trap of Nginx.
server {
listen 80;
server_name www.xlsys.cn; # Your legitimate domain name
# Host header attack protection configuration
set $host_flag 0; # Initialize flag bit to 0 (illegal)
if ($host == "www.xlsys.cn") { # Match legitimate domain name
set $host_flag 1; # Set flag bit to 1 (legal)
}
if ($host_flag = 0) { # Reject illegal Host directly
return 403;
}
location / {
root /www/h5;
index index.php index.html index.htm;
}
}
The advantage of this scheme is simple logic and easy maintenance, even non-professional operation and maintenance personnel can quickly understand and modify it.
Scheme 2: Multi-Domain Whitelist (Main Site + Subsite/Test Environment)
If your application has multiple legitimate domain names (such as main site www.xlsys.cn, subsite blog.xlsys.cn, local test localhost), you can implement a whitelist using regular expressions or multi-condition judgment.
Method 1: Regular Expression Matching (Concise)
server {
listen 80;
server_name www.xlsys.cn;
set $host_flag 0;
# Regular expression matches multiple legitimate domain names, separated by |
if ($host ~* "^(www\.xlsys\.cn|blog\.xlsys\.cn|localhost)$") {set $host_flag 1;}
if ($host_flag = 0) {return 403;}
location / {
root /www/h5;
index index.php index.html index.htm;
}
}
Method 2: Multi-Condition Judgment (Higher Readability)
set $host_flag 0;
if ($host == "www.xlsys.cn") {set $host_flag 1;}
if ($host == "blog.xlsys.cn") {set $host_flag 1;}
if ($host == "localhost") {set $host_flag 1;}
if ($host_flag = 0) {return 403;}
Scheme 3: Regular Expression Matching IP + Domain Name (Special Scenarios)
If you need to allow access from specific IP segments (such as internal network testing), you can combine IP and domain name for regular expression matching. But note: the more complex the regular expression, the higher the maintenance cost. Exact matching is preferred in the production environment.
server {
listen 80;
server_name www.xlsys.cn;
# Allow domain name + specified IP segment + local loopback address
if ($http_Host !~* "^(www\.xlsys\.cn|192\.168\.10\.\d{1,3}|127\.0\.0\.1)$") {return 403;}
location / {
root /www/h5;
index index.php index.html index.htm;
}
}
Note: The `.` in the regular expression needs to be escaped to `\.`, otherwise it will match any character; the IP segment is only basically restricted with `\d{1,3}`, which cannot completely prevent illegal IPs.
4. How to Verify Whether the Protection Takes Effect?
After the configuration is completed, use the curl command to test two scenarios to ensure the protection takes effect:
- Normal Access (Should Return 200):
curl -I -H "Host: www.xlsys.cn" http://your-server-ip/Returns status code 200 OK, indicating that the legitimate Host passes. - Forged Host (Should Return 403):
curl -I -H "Host: evil.com" http://your-server-ip/Returns 403 Forbidden, indicating that the illegal Host is blocked.
5. 2025 Host Header Defense Best Practices
- Back-End Does Not Depend on Host Header: Even if Nginx does the verification, the back-end should use the fixed domain name in the configuration file when generating URLs, instead of $_SERVER[‘HTTP_HOST’] or $host.
- Default Server Block Rejects Access: Ensure that the default_server block of Nginx does not return any sensitive content. It is recommended to configure it as:
server {listen 80 default_server; return 444;}(444 means closing the connection without response). - Record Illegal Request Logs: Record logs for intercepted illegal requests to facilitate subsequent analysis of attack sources:
if ($host_flag = 0) {access_log /var/log/nginx/host_attack.log;return 403;} - Regularly Audit Configuration: When the domain name is changed or added, update the Host whitelist of Nginx in time to avoid normal requests being blocked.
Summary
HTTP Host header attack (Host Header Injection) is subtle but has extremely low defense cost. Through simple configuration at the Nginx layer, most attack attempts can be effectively blocked. It is recommended to use Scheme 1 (Single Domain Name Flag Bit) or Scheme 2 (Multi-Domain Exact Match) first, which takes into account both security and maintainability. Remember: The core of web security is “not trusting any client input”. Only by starting from the details can a truly solid defense system be built.