48人参与 • 2026-09-09 • Linux
线上 nginx 配置 ip 白名单,使用allow + deny all做访问控制,仅允许内网 ip196.16.0.2访问服务。
allow 196.16.0.2; deny all;
同一台 windows 浏览器发起两类请求:
get /:请求正常返回 304,页面成功加载;nginx 访问日志客户端 ip 记录为196.16.0.2。get /test/get:直接返回 403 拒绝访问;nginx 日志客户端 ip 记录为公网 ip1.80.211.195。现象:同一个浏览器,页面请求放行,接口请求被拦截,nginx 日志记录两个完全不同的客户端 ip,业务人员第一反应怀疑浏览器或者 nginx 缓存异常。
196.16.0.2 - - [07/aug/2026:15:01:25 +0800] "get / http/1.1" 304 0 "-" "mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/147.0.0.0 safari/537.36" 1.80.211.195 - - [07/aug/2026:15:01:26 +0800] "get /test/get http/1.1" 403 555 "http://196.16.0.37/" "mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/147.0.0.0 safari/537.36"
referer 字段http://196.16.0.37/,说明前端页面部署在196.16.0.37这台 nginx 服务器。
allow、deny属于 nginx 的access访问控制模块,读取的是 tcp 四层连接的源 ip 变量$remote_addr,完全忽略 http 请求头,包括x‑forwarded‑for。 即使 http 头部携带真实客户端内网 ip,allow/deny也不会读取,仅以 tcp 连接对端 ip 作为判断依据。
这是绝大多数开发容易踩坑的知识点:经过代理转发的请求,$remote_addr是代理服务器出口 ip,而不是浏览器真实 ip。真实客户端 ip 被放在 http 请求头x‑forwarded‑for中。
http://196.16.0.37/,直接在内网访问 nginx 服务。 tcp 连接来源 ip 就是浏览器机器196.16.0.2,命中白名单allow 196.16.0.2,请求放行,页面正常返回。1.80.211.195;虽然 http 头x‑forwarded‑for携带真实客户端196.16.0.2,但是allow/deny不识别 http 头,匹配不到白名单,执行deny all,返回 403。关键点:同一个浏览器,不同请求可以走完全独立的网络链路,nginx 看到的客户端 ip 可以完全不同,不是浏览器故障。
页面在内网访问,接口走公网代理;四层 tcp 源 ip 发生改变,http 头里的真实 ip 没有被 nginx 访问控制模块识别,最终出现页面正常,接口 403 的诡异现象。

说明:$remote_addr是 nginx 拿到的tcp 连接对端 ip,allow/deny 直接读取这个值。 下面全部是会改变服务端看到 ip 的场景,也就是:浏览器真实 ip 不变,但 nginx 日志里面记录的 ip 变成别的 ip。
客户端→代理 nginx→后端 nginx / 服务。后端 nginx 看到的 ip 是代理服务器 ip。 需要配置proxy_set_header x‑forwarded‑for $remote_addr传递真实 ip;但allow/deny仍然看 tcp 源 ip,不读该 header。
云 slb、硬件负载均衡,流量经过负载均衡转发,后端服务 tcp 对端 ip 变成 lb 节点 ip。
本次故障就是该场景:页面直连内网,接口走公网 slb,ip 发生变化。
域名接入 cdn 后,用户请求全部打到 cdn 节点,源站 nginx 看到的 ip 是 cdn 节点 ip,不是用户真实 ip。
公司内网配置 http 代理,浏览器所有请求经过代理服务器出去,服务端看到代理服务器 ip。
现象:本机真实网卡 ip 不变,但是服务端看到的 ip 已经切换。
浏览器配置 socks5 代理,全部流量经由代理节点转发,服务端记录代理节点 ip。
组建虚拟局域网,访问虚拟网络地址,tcp 源 ip 为虚拟网卡分配 ip,和物理网卡 ip 不一样。
同一个浏览器,不同域名,会走完全不同网络路径,服务端拿到不同源 ip
典型坑:页面用内网域名http://196.16.0.37访问,js 接口写死公网域名,虽然是同一台浏览器,两套请求 tcp 链路完全不一样,服务端拿到的源 ip 完全不同,就是我们故障案例。
关键点:域名 / dns 本身不会修改 ip,但是 dns 解析结果决定流量走哪条网络链路,最终导致服务端看到的 $remote_addr 改变。
大量企业内网出口防火墙做 snat,内网机器访问服务器,源 ip 被转换成防火墙网关 ip。
极易出现:同个浏览器,访问同服务器,不同访问路径,日志 ip 不一样。
容器内部访问外部服务,经过 docker0 网桥 snat,外部服务看到宿主机 ip,不是容器内部 ip。
1. 电脑多网卡:机器同时有内网网卡、wi‑fi、4g 上网卡。访问不同目标 ip,系统路由选择不同网卡出口,tcp 源 ip 随之改变。
例如:访问内网服务走内网网卡;访问公网域名走 wi‑fi 网卡,服务端看到不同 ip。
2. 双栈网络 ipv4/ipv6:服务器支持 ipv6,客户端优先 ipv6 连接,nginx 日志记录客户端 ipv6 地址,和 ipv4 内网 ip 完全不同。
allow/deny是四层 tcp 访问控制,只要中间任意设备做了代理、nat、vpn 转发,$remote_addr 就会被替换,哪怕 http 头携带真实 ip,allow/deny 完全无视。allow/deny做业务客户端 ip 白名单,需要读取x‑forwarded‑for做应用层 ip 校验,同时做好防请求头伪造。| 方式 | 是否改变 tcp 源 ip ($remote_addr) | 是否使用 x‑forwarded‑for 传递真实 ip | allow/deny 能否拿到真实客户端 ip |
|---|---|---|---|
| 反向代理 / slb/cdn | ✅改变(变成代理 ip) | ✅可以带上真实 ip | ❌不能,allow/deny 只看 tcp 源 ip,忽略 header |
| vpn、socks 代理 | ✅改变(网关 / 代理节点 ip) | ❌一般不带 x‑forwarded‑for | ❌ |
| dns 域名切换链路 | ✅间接改变(路由链路变化) | 看链路中间设备 | ❌ |
| snat 防火墙 nat | ✅改变(网关 ip) | ❌ | ❌ |
以上就是nginx allow/deny诡异问题:同一浏览器页面正常接口403问题分析与解决的详细内容,更多关于nginx allow/deny页面正常接口403的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论