1216 字
6 分钟
折腾日记:解决获取FRP真实IP后OpenResty监控报错问题

问题背景#

最近在配置FRP反向代理服务时,为了让后端服务能够获取到客户端的真实IP地址,我按照常规做法在FRP服务端配置了proxy_protocol_version = v2,并在OpenResty配置中添加了 set_real_ip_fromreal_ip_header 等指令。配置完成后,网站功能一切正常,客户端IP也能正确获取,但OpenResty的监控系统却开始频繁报错。

错误现象#

错误代码:服务内部错误: Get "http://127.0.0.1/nginx_status": EOF

报错截图,OpenResty监控完全崩溃

排查过程#

理解PROXY协议#

首先我查阅了PROXY协议的文档,了解到这是HAProxy开发的一种协议,用于在代理服务器和后端服务器之间传递客户端原始信息。樱花FRP支持v1、v2和simple三个版本的PROXY协议,我使用的是v2版本协议。

检查配置#

检查我的站点OpenResty配置:

listen 80 proxy_protocol default_server;
listen [::]:80 default_server;
listen 443 ssl http2 proxy_protocol default_server;
listen [::]:443 ssl http2 default_server;
...
real_ip_header proxy_protocol; # 启用 PROXY 协议支持
real_ip_recursive on; # 递归处理 PROXY 协议中的 IP 地址
set_real_ip_from 127.0.0.1; # 这里的127.0.0.1表示可信的代理服务器 IP 地址
...

FRP服务端的配置:

[common]
proxy_protocol_version = v2

看起来配置是正确的,但为什么监控会报错?

分析监控组件#

我使用的OpenResty是1Panel运维面板提供的,查看其文档发现它默认不支持PROXY协议。当监控请求到达时,监控模块尝试解析请求头,但遇到了PROXY协议头而不是常规的HTTP请求头,因此报错。

解决方案#

为FRP流量单独配置监听端口#

因为OpenResty监控流量来源于127.0.0.1:80这个地址和端口且1Panel的OpenResty只占用80和443端口,所以我只需要避免在这个80端口启用PROXY协议就行,因此我们可以有两种做法。

这两种做法的前提是配置穿透地址为本地IP127.0.0.1端口为443:

FRP配置

  1. 网站服务的443端口启用PROXY协议,80端口保持默认配置不变。
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl http2 proxy_protocol default_server; # 因为樱花FRP只提供IPV4穿透,所以这需要监听IPV4的443端口 proxy_protocol
listen [::]:443 ssl http2 default_server;
...
real_ip_header proxy_protocol; # 启用 PROXY 协议支持
real_ip_recursive on; # 递归处理 PROXY 协议中的 IP 地址
set_real_ip_from 127.0.0.1; # 这里的127.0.0.1表示可信的代理服务器 IP 地址
...
  1. 单独监听127.0.0.1:443这个地址,将其作为FRP的专属监听配置(更推荐这种做法)。

将下面这几行代码添加到网站的server块中:

listen 127.0.0.1:443 ssl http2 proxy_protocol; # 这里监听FRP代理的本地端口
real_ip_header proxy_protocol; # 启用 PROXY 协议支持
real_ip_recursive on; # 递归处理 PROXY 协议中的 IP 地址
set_real_ip_from 127.0.0.1; # 这里的127.0.0.1表示可信的代理服务器 IP 地址

示例:

server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
listen 127.0.0.1:443 ssl http2 proxy_protocol; # 这里监听FRP代理的本地端口 proxy_protocol
proxy_set_header X-Real-IP $remote_addr;
...
real_ip_header proxy_protocol; # 启用 PROXY 协议支持
real_ip_recursive on; # 递归处理 PROXY 协议中的 IP 地址
set_real_ip_from 127.0.0.1; # 这里的127.0.0.1表示可信的代理服务器 IP 地址
...
proxy_http_version 1.1;

为监控单独配置监听端口#

修改网站配置文件,在配置文件最末端添加下列server块(一定要在末端添加这个server块,不然1Panel内网站的基本设置会有部分失效)

server {
listen 127.0.0.1:80;
server_name localhost;
location /nginx_status {
stub_status on; # 启用状态模块
access_log off; # 关闭访问日志
allow 127.0.0.1; # 仅允许本机访问
deny all; # 禁止其他IP
}
}

配置文件总览:

server {
listen 80 proxy_protocol default_server;
listen [::]:80 default_server;
listen 443 ssl http2 proxy_protocol default_server;
listen [::]:443 ssl http2 default_server;
...
real_ip_header proxy_protocol; # 启用 PROXY 协议支持
real_ip_recursive on; # 递归处理 PROXY 协议中的 IP 地址
set_real_ip_from 127.0.0.1; # 这里的127.0.0.1表示可信的代理服务器 IP 地址
...
# 粘贴在配置文件最末端
server {
listen 127.0.0.1:80;
server_name localhost;
location /nginx_status {
stub_status on; # 启用状态模块
access_log off; # 关闭访问日志
allow 127.0.0.1; # 仅允许本机访问
deny all; # 禁止其他IP
}
}

server块配置截图

验证结果#

可以看到通过配置这个server块之后,OpenResty已经可以正常监控全部的网站服务了。

经验总结#

  1. 协议兼容性:在引入新协议时要考虑所有相关组件的兼容性

  2. 监控隔离:监控端点最好与业务端点分离,避免相互影响

  3. 逐步排查:从错误日志出发,逐步分析各组件的行为,能更快定位问题

希望这篇折腾日记能帮助遇到类似问题的朋友。如果你有更好的解决方案,欢迎在评论区分享!

折腾日记:解决获取FRP真实IP后OpenResty监控报错问题
https://blog.puresky.top/posts/折腾日记解决获取frp真实ip后openresty监控报错问题/
作者
Cyon
发布于
2025-03-26
许可协议
CC BY-NC-SA 4.0