1、需求
网关:172.16.0.48 反向代理到 nginx:172.16.0.32 nginx 只允许来源是网关 172.16.0.48 访问,拒绝所有其它 ip。
关键点:经过代理转发,nginx 拿到的源 ip,默认不是真实客户端,而是网关 172.16.0.48,直接用 allow/deny 就可以实现。 注意区分两种场景:①四层转发(tcp 代理);②七层 http 代理。
2、处理方案
方案一:nginx ngx_http_access_module(七层 http,最常用)
场景:网关是 http 反向代理,把 http 请求转发给 172.16.0.32 的 nginx。编辑 nginx server/location 块:
server {
listen 80;
server_name _;
# 只放行网关,其余全部拒绝
allow 172.16.0.48;
deny all;
location / {
root html;
index index.html;
}
}⚠️重要前提:网关是直接 http 代理访问 nginx,没有做 x‑forwarded‑for 篡改访问控制;此时 nginx 看到的 remote_addr 就是172.16.0.48。 不要拿 $http_x_forwarded_for 做访问控制!这个 header 客户端可以伪造,不安全。
验证配置 & 重载
nginx -t nginx -s reload
多 ip 白名单配置
原理:allow 可以写多条,从上到下匹配,最后 deny all; 拒绝其余所有 ip。 依然记住:allow/deny 匹配的是 $remote_addr(tcp 真实连接源 ip),不要用 x‑forwarded‑for 做权限校验。
直接写多条 allow(写在 server /location 块内)
server {
listen 80;
server_name _;
# 白名单ip列表
allow 172.16.0.48;
allow 172.16.0.49;
allow 172.16.0.50;
# 也支持网段
allow 192.168.1.0/24;
deny all; # 不在上面白名单全部拒绝403
location / {
root html;
index index.html;
}
}方案二:防火墙层面(系统 iptables/firewalld,网络层,更彻底)
直接在 nginx 服务器172.16.0.32操作系统防火墙限制,不管 nginx 配置,网络层面只允许172.16.0.48访问 80/443,其它 ip 全部 drop。
# 删除80、443公开放行 firewall-cmd --permanent --remove-service=http firewall-cmd --permanent --remove-service=https # 仅允许网关访问80、443 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.16.0.48/32" port protocol="tcp" port="80" accept' firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.16.0.48/32" port protocol="tcp" port="443" accept' firewall-cmd --reload
- 优点:就算 nginx 配置被篡改,外部 ip 依然无法访问服务;
- 缺点:操作系统层面,需要服务器权限。
方案三:nginx stream 模块(网关是四层 tcp 代理,stream 块)
如果网关是四层 tcp 转发,nginx 用stream处理 tcp 流量,ngx_stream_access_module做 ip 限制:
stream {
server {
listen 80;
allow 172.16.0.48;
deny all;
proxy_pass backend;
}
}3、坑点提醒
- ❌ 错误:拿
$http_x_forwarded_for做 allow 判断。x‑forwarded‑for是 http 头,外网用户可以随便伪造,不能用来做访问控制;$remote_addr才是 tcp 真实连接来源 ip。 - 如果网关做的是 snat,nginx 看到源永远网关 ip,
allow 172.16.0.48;deny all直接生效。 - 如果网络中间还有其他设备(负载均衡、交换机)做源 nat,那 remote_addr 就不是网关,访问控制会失效,需要排查网络链路。
调试如何看 nginx 拿到的真实 tcp 源 ip
在 nginx 日志格式加上$remote_addr,看日志确认连接来源 ip:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;执行 tail -f /var/log/nginx/access.log,确认请求过来时remote_addr是172.16.0.48。
到此这篇关于nginx白名单的几种方法实现的文章就介绍到这了,更多相关nginx白名单内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论