frp透传,nginx日志打印客户端ip

云服务器配置的frp服务端,内网机器部署了frp客户端,客户端再把流量传给NGINX。

发现NGINX的access_log打印的客户端ip都是我客户端frp客户的服务ip,不是真实客户的ip地址,想做一些统计分析或者其他工作感觉不是很方便,所以想能有什么办法能拿到客户端的真实ip。

查阅官方文档,有这样一段话

Get Real IP
HTTP X-Forwarded-For
This feature is for http proxy only.

You can get user's real IP from HTTP request headers X-Forwarded-For and X-Real-IP.

大概意思,如果你用的http代理模式,frp默认会把用户的真实ip传给你的服务,通过头 X-Forwarded-For and X-Real-IP。哟呵?默认就传了,然后我尝试定义一个日志头,把我NGINX的x-real-ip头设置注释掉,然后在新日志头打印出来$x-real-ip,发现不行。难道哪里配置错了吗?

log_format  main_real_ip  '$x-real-ip - $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_real_ip; 

这里说下NGINX日志的语法,有2个语法,一个是 log_format 是定义日志格式的, 后面接 格式名字 和格式。还有个是 access_log 是用来定义日志路径和样式的,后面接路径 空格样式名称;

发现这样并不行,不知道哪里出了问题。于是乎查了点资料,发现frp支持一个高级的玩意,叫 Proxy Protocol ,据说这玩意是工作在tcp层的,不管是不是http都行,NGINX也支持。

# frpc.ini
[web]
type = https
local_port = 443
custom_domains = test.example.com

# now v1 and v2 are supported
proxy_protocol_version = v2

只需要在你的frpc的配置里面加一行 proxy_protocol_version = v2即可支持。

等待我配置之后,发现并不能访问,还报了个ssl的错误。查了资料发现,NGINX也需要相关配置的。

首先检查你的NGINX支不支持这个协议

nginx -V 2>&1 | grep -- 'http_realip_module'

如果不支持,要去编译了,我的是支持的。

然后需要在NGINX上加一点点配置。

http {
    #...
    server {
        listen 80   proxy_protocol;
        listen 443  ssl proxy_protocol;
        #...
    }
}

需要在之前的listen后加个 proxy_protocol

然后改下你的日志格式

http {
    #...
    log_format combined_proxy_addr '$proxy_protocol_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';
}
access_log  /var/log/nginx/access.log combined_proxy_addr; 

经过测试,能够正确打印客户端的真实ip了,收工。

相关资料:

https://www.fenghong.tech/blog/ops/frp-get-realip/

https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/

https://github.com/fatedier/frp

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll to Top