Nginx禁止直接IP访问
系列 - Security Config of Nginx
目录
1 Nginx v1.19.4及后续版本
...
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name <服务器公网IP>;
return 444;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name <服务器公网IP>;
ssl_reject_handshake on;
}
...
值得一提的是, 相比server_name
后接服务器的IP地址, server_name _;
更为常见, 虽然两种写法的作用效果相同, 但是Nginx官方文档中并不提倡使用server_name _;
, 并指出:
原文
There is nothing special about this name, it is just one of a myriad of invalid domain names which never intersect with any real name. Other invalid names like “–” and “!@#” may equally be used.
2 Nginx v1.19.4先前版本
Nginx v1.19.4先前版本不支持ssl_reject_handshake
, 所以只能先指定证书, 再return 444
。
...
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name <服务器公网IP>;
return 444;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name <服务器公网IP>;
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
return 444;
}
...
3 不推荐使用if
当服务器只托管一个网站时, 这可能是最简单的解决方案, 但并不优雅, 因为不方便后续扩展网站。
...
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
if ($host != example.com) {
return 444;
}
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name example.com;
if ($host != example.com) {
return 444;
}
}
...
警告
它将阻止访问其他子域, 比如
www.example.com
, blog.example.com
。如果要支持更多子域, 可以使用正则表达式来执行此操作, 比如这适用于example.com
和www.example.com
:
if ($host !~* ^(www\.)?example.com$) {
return 444;
}
显而易见, 如果有更多的子域, 就与要更复杂的正则表达式来匹配, 这很容易出错, 所以还是ssl_reject_handshake
方案好。