Nginx安全加固教程:从默认配置到可验证的防护清单
Nginx安全加固的核心思路不是堆一堆复杂模块,而是先把默认配置里对外暴露的信息和宽松权限收紧,再逐项验证。
本文适合已经装好Nginx、能登录服务器终端的用户,默认系统为常见Linux发行版,配置文件路径为/etc/nginx/nginx.conf,站点配置在/etc/nginx/conf.d/或/etc/nginx/sites-enabled/。
所有改动前先备份,出错能回滚。
改配置前先做两件事
第一,确认当前Nginx版本和配置文件位置,避免路径猜错。
nginx -v
nginx -t
ls /etc/nginx/
第二,备份整个配置目录。
不要只复制单个文件,站点配置可能是分散的。
cp -a /etc/nginx /etc/nginx.bak.$(date +%F)
如果用的是宝塔面板,
也可以在面板的“网站—配置文件”里操作,
但建议先通过面板的“文件”功能把/www/server/nginx/conf/nginx.conf复制一份到同目录,
改名加日期后缀。
隐藏版本号并收紧响应头
默认Nginx会在响应头和错误页暴露版本号,攻击者可以据此查找对应版本的已知问题。
在http块内加入或修改:
server_tokens off;
只隐藏版本号不够,错误页仍可能暴露系统信息。
如果业务不需要自定义错误页,保持默认即可;
如果已经自定义,检查错误页里是否写了服务器路径或框架版本。
改完执行:
nginx -t && nginx -s reload
验证方式:
curl -I http://你的域名
看返回头里的Server字段,应该只剩nginx,不再带具体版本号。
限制危险请求方法和默认站点
很多站点只用到GET、POST、HEAD,却允许PUT、DELETE、TRACE等方法。
可以在站点server块中加入:
if ($request_method !~ ^(GET|POST|HEAD)$) {
return 405;
}
同时删除或禁用默认站点,防止别人用IP直接访问到默认页。
检查/etc/nginx/conf.d/下是否有default.conf或example.conf,没有业务用途就移走:
mkdir -p /etc/nginx/disabled
mv /etc/nginx/conf.d/default.conf /etc/nginx/disabled/
注意:如果你只有一个站点且配置文件就叫default.conf,不要直接删,先确认它是不是正在用的站点配置。
防目录穿越和限制连接频率
防目录穿越主要靠规范root和alias路径,避免把用户输入直接拼进路径。
检查站点配置中是否有类似alias /var/www/$uri的写法,这种拼接方式风险较高。
限制连接频率可以用limit_req_zone和limit_conn_zone。
在http块定义:
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
在需要保护的location中引用:
location /login {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 10;
proxy_pass http://127.0.0.1:8080;
}
rate=10r/s表示每个IP每秒10个请求,burst=20允许短时突发。
数值要根据业务调整,设太小会误伤正常用户。
日志审计与文件权限
加固后要能查到异常请求。
确认http块中有访问日志和错误日志配置:
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
日志目录权限建议只允许root和Nginx运行用户读取。
查看Nginx运行用户:
ps aux | grep nginx
常见为www-data或nginx。
不要为了让日志“方便看”而把权限设成777,这会带来新的风险。
避坑与回滚
以下情况容易导致加固后站点打不开:
- 在
http块外写了limit_req_zone,Nginx启动时报unknown directive。 - 限制请求方法时把业务需要的接口方法也拦了,例如某些API用PUT。先确认业务再改。
- 移除默认站点后,用IP访问返回404或连接被拒,这是预期结果,不是故障。
- 改完没执行
nginx -t就直接reload,配置错误会导致旧进程继续跑或重载失败。
回滚方法:用备份目录覆盖回去,再测试并重载。
cp -a /etc/nginx.bak.日期/. /etc/nginx/
nginx -t && nginx -s reload
验证加固是否生效
用几条命令做基础检查:
nginx -t
curl -I http://你的域名
curl -X PUT http://你的域名 -I
预期结果:nginx -t显示syntax is ok和test is successful;
响应头Server不含版本号;
PUT请求返回405或403。
如果返回内容与预期不符,先看error_log最近几行:
tail -n 50 /var/log/nginx/error.log
需要提醒的是,Nginx安全加固只是Web安全的一部分,它不能替代系统补丁、应用层鉴权和HTTPS。
如果你的站点已经启用HTTPS,还应检查证书配置和TLS版本,这部分可以结合服务器证书管理一起做。
常见疑问
隐藏版本号能完全防止被扫描吗?
不能。
它只是减少信息暴露,扫描器仍可通过行为特征识别Nginx。
限速设多少合适?
没有统一值。
先按业务峰值观察一周访问日志,再设置略高于正常峰值的阈值,从宽到严调整。
改完配置需要重启服务器吗?
通常不需要,nginx -s reload即可平滑重载。
只有在改动了系统级参数或Nginx编译模块时才考虑重启服务。