对于 VPN 客户端,NGINX 会记录哪个源地址
判断同一台主机上 NGINX 在 OpenVPN 旁边看到什么:隧道内网地址、公网出口地址,还是被转发的对端,取决于请求走的路径。
在同一台主机上同时运行 NGINX 与 OpenVPN 时,客户端地址会出现三种形态,分别对应请求可能走的每一条路径。访问隧道地址的浏览器、访问公网地址的浏览器,以及从网关的互联网路径出去的程序,在监听套接字上看起来完全不同。在解读日志行之前,先确定你在看哪条路径。判断取决于客户端使用的目标地址、它为外层 VPN 端点保留的例外,以及中途是否有东西改写了数据包。
按目标地址判断,而不是按用户是谁判断
从请求被发送到的地址开始,因为正是那个地址选择了路径。发往主机隧道地址的请求,从隧道接口进来,源是客户端的内网地址。发往主机公网地址的请求,通常从面向互联网的接口进来,源是客户端的公网地址,即使同一台笔记本此刻已经建立了隧道。因此,是否属于 VPN 地址池是数据包路径的属性,而不是跟随用户的属性。
| Path the request took | Source the site normally records |
|---|---|
| Client reaches the site at its tunnel address, 10.24.0.1 | Client inner address, 10.24.0.20 |
| Client reaches another internet site through the gateway | Gateway public egress address, 192.0.2.44 |
| Client reaches the gateway's public address through the endpoint exception | Client's own public access address |
当日志里出现一个与隧道毫无关系的 VPN 用户地址时,最该先核对的就是第三行。它也解释了为什么同一配置下的两个用户会产生不同记录:各自的接入网络不同,隧道里的任何东西都不会覆盖这一点。
为什么外层端点会造出第二条公网路径
客户端必须能到达网关的公网地址才能建立隧道,因此通往该地址的路由必须存在于隧道之外。当客户端把全部流量都指向内侧时,合理的实现会为服务器的公网地址保留一条明确的主机路由,以避免隧道依赖自身。这条例外不区分服务,因此任何发往同一公网地址的请求都会走它,包括浏览器对托管在网关上的站点的请求。
这就是该领域大多数混乱报告的机制,而且它取决于客户端实现而非服务器。所以两个配置相同的客户端行为可能不同。为 »修好« 日志而删掉例外,会连隧道一起弄断,因此保留它并围绕它做设计。
把套接字、路由表和日志格式放在一起读
三点观察决定你在看哪条路径:套接字在哪里监听、哪个接口应答该目标地址、日志格式实际记录了什么。如果监听只绑定在隧道地址上,公网请求根本到不了它,这一条就排除了两行。如果针对客户端查询返回的是隧道设备,说明请求带着内网源地址进来,日志应当如实显示。
ss -lntp 'sport = :443'
ip route get 10.24.0.20
ip route get 192.0.2.44然后读格式而不是读那一行。由转发头填充的字段记录的是声称,而不是套接字对端,只有当下游对端是受信代理时这个声称才有意义。把两个值都写进日志能了结日后的争论,因为直接对端和被替换的地址是两个不同的事实,只有一个来自网络。
log_format tunneled '$remote_addr $realip_remote_addr $request $status';
grep -n 'log_format' /etc/nginx/nginx.conf选定你想要的入口,并让 DNS 保持一致
如果站点只应通过隧道访问,就给它一个对 VPN 客户端解析到隧道地址的名字,并在监听套接字上执行策略。为内网名称返回 10.24.0.1 的分域 DNS 答案,是披着名称解析细节外衣的路由决定。如果站点也必须是公网的,就保留两个名字或两个端口,让日志告诉你哪一个服务了该请求。
放行规则遵循同一逻辑。放行隧道地址池并不授权公网请求,也不会在从互联网进来的连接上填上内网地址。把两个入口混在同一个名字下,会让被记录的源地址变成客户端路由的副作用,而不是设计选择。
先验证路径,再验证策略
用网关上的抓包和你掌控的请求确认路径。隧道设备上的抓包和公网接口上的抓包能看出哪一边承载了字节,数据包顺序则告诉你中间是否发生过地址转换。
tcpdump -ni tun0 port 443 -c 5
tcpdump -ni eth0 port 443 -c 5接着双向验证访问:预期的命名入口对预期的客户端有效,而未获准的公网路径是被拒绝,而不是仅仅变慢。通用的 IP 回显站点只能证明网关的互联网出口,对这个同主机站点什么也证明不了。当页面与 WebSocket 表现不一致时,先比较它们的 URL、地址族和 DNS 应答,再去动服务器配置。