Nginx 可以通过 host
头来限制允许访问的域名,而不是仅依赖于 server_name
。为了禁止其他域名(包括 CNAME 解析到该域名的域名),你可以通过检查请求中的 Host
头,确保它匹配特定的域名。
配置步骤:
配置
server_name
: 限制只有指定的域名可以访问。使用
if
语句检查Host
头: 如果Host
头不匹配指定的域名,则返回 404 错误。
以下是具体的配置:
server { listen 80; server_name example.com; # 仅允许这个域名访问 # 检查 Host 头,确保它是正确的域名 if ($host != "example.com") { return 404; # 如果请求的 Host 不是 example.com,返回 404 } location / { # 处理该域名的请求 try_files $uri $uri/ =404; } } server { listen 80 default_server; # 默认的 server block server_name _; # 匹配任何域名 # 如果访问的域名不是 example.com, 返回 404 location / { return 404; } }
解释:
第一个
server
block:server_name example.com;
:仅允许example.com
访问。if ($host != "example.com") { return 404; }
:这行代码检查请求中的Host
头,只有当Host
头为example.com
时,才允许访问,其他域名会返回 404 错误。第二个
server
block:这个
server
block 配置为默认的 server,当请求的域名没有匹配到其他server_name
时,使用这个默认配置。如果请求的域名不匹配
example.com
,就会返回 404 错误。
注意事项:
CNAME: 如果其他域名通过 CNAME 解析到了
example.com
,那么请求中的Host
头依然会是其他域名。因此,通过if ($host != "example.com")
的判断可以防止其他域名访问。检查
Host
头: 这种方法依赖于请求中的Host
头。注意,如果存在 HTTP 请求伪造的情况(例如,通过 HTTP 请求头伪造Host
头),这时该方法可能并不完全安全。为了防止这种情况,可以启用 HTTPS 并结合其他安全措施来加强防护。
配置更新后:
重新加载 Nginx 配置
事实上网站建好,已经有其他的配置了,只要添加以下 if
语句就可以了
# 检查 Host 头,确保它是正确的域名 if ($host != "example.com") { return 404; # 如果请求的 Host 不是 example.com,返回 404 }
拓展
上面的只是匹配单个允许的域名。想要明确地限制仅允许几个指定的域名访问,修改并使用
语句检查多个if
Host
头,或者使用map
指令来优化这种情况
1.使用多个if
条件
# 检查 Host 头,确保它是允许的域名之一 if ($host != "example.com" && $host != "www.example.com" && $host != "example.net" && $host != "www.example.net") { return 404; # 如果 Host 不匹配,返回 404 错误 }
同样的语句,另外的的写法
# 检查 Host 头,确保它是允许的域名之一 if ($host != "example.com") { if ($host != "www.example.com") { return 404; # 如果 Host 不匹配,返回 404 错误 } }
2.使用map
指令(推荐)
# 定义一个 map 来检测允许的域名 map $host $allowed { default 0; example.com 1; www.example.com 1; } server { listen 80; # 只有 $allowed 变量为 1 时才允许访问 if ($allowed = 0) { return 404; # 如果不在允许的域名列表中,返回 404 } location / { try_files $uri $uri/ =404; } } server { listen 80 default_server; location / { return 404; # 默认返回 404 错误 } }
解释:
map
指令:创建了一个名为$allowed
的变量,默认值为 0。如果请求中的Host
匹配example.com
或www.example.com
,则 $allowed 变量的值会变为 1。if ($allowed = 0)
:检查$allowed
变量,如果它的值为 0(即请求的Host
不在允许的域名列表中),就返回404
错误。为什么使用
map
指令更好?性能:
map
是在 Nginx 配置解析阶段就进行处理的,具有更好的性能。可维护性:当你需要检查多个域名时,
map
提供了一种更干净、可扩展的方式,避免了多个if
语句的嵌套。简洁:当域名数量较多时,
map
方式比多个if
语句更简洁且易于管理。
总结
map
指令是再server
外面定义域名有哪些,使用if
语句的时候,不用嵌套加上去了,修改的话,删减增加map
里面的域名就可以了。不过一般同一个网站,也不会用那么多个的域名吧。
3.在 if
语句中使用 !~
你可以在
if
语句中使用
!~
来检查
Host
是否不匹配某个正则表达式。例如,如果你想要检查
Host
是否不为
example.com
或
www.example.com,
你可以这样写:
# 如果 Host 不匹配 example.com 或 www.example.com,返回 404 if ($host !~ ^(example\.com|www\.example\.com)$) { return 404; }
解释:
:表示“不匹配”正则表达式。如果!~
$host
不匹配后面的正则表达式,条件会为真。
:这是一个正则表达式,表示匹配^(example\.com|www\.example\.com)$
example.com
或www.example.com
。^
和$
分别是字符串的开始和结束锚点,确保整个Host
值完全匹配这两个域名之一。| 用于匹配“或者”条件。正则表达式的注意事项:
反斜杠转义:在正则表达式中,点 . 是一个特殊字符,表示任何单个字符。因此,如果你要匹配一个字面上的点 .,你需要使用反斜杠
\
进行转义,例如:example\.com
。!~
的用法:!~
用来检查是否不匹配正则表达式。如果你想要匹配某些特定的域名并拒绝其他所有的请求,使用!~
是非常合适的。