实在是受不了cloudflare的慢速,正好阿里云最近出了一个99/年的活动,搞了台服务器,速度啥的都还行,就还是直接从frp穿出去,至少速度啥的还是能保证的。
我的方案是直接是直接将阿里云的80端口和443端口全部转发到我自己的内网服务器上,然后frp再将流量全部转发到内外的nginx上做分发。方案在实施的过程中遇到了一个问题:我没有办法拿到请求者的ip了,会对我们的数据统计产生影响。看了frp是能够支持真实ip转发的,在不同的版本下有不同写法,主要是0.52.0之前的版本有较大差异,0.52.0支持使用toml格式来配置了,本文是基于toml来配置实现的。
环境
软件环境
- nginx 1.24.0
- frp 0.52.0
- 操作系统 ubuntu 22.04
网络环境
公网 -> 阿里云 ----FRP----> 内网网关(nginx) -> 具体应用服务器
nginx需要支持realIp
先通过nginx -V
查看当前的nginx是否支持realIp
$ ./nginx -V
nginx version: nginx/1.24.0
built by gcc 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
built with OpenSSL 3.0.2 15 Mar 2022
TLS SNI support enabled
configure arguments: --prefix=/data/software/nginx --with-http_ssl_module --with-http_realip_module
如果存在--with-http_realip_module
那么就不需要重新编译,否则就加上这个参数重新编译nginx安装
配置frp支持proxy_protocol
在FRP中需要配置transport.proxyProtocolVersion = "v2"
,注意:这个是frp0.52.0以后的版本配置。https://gofrp.org/zh-cn/docs/features/common/realip/,这个连接地址有官方说明。
[[proxies]]
name = "443_transfer"
type = "tcp"
localIP = "127.0.0.1"
localPort = 443
remotePort = 443
transport.proxyProtocolVersion = "v2"
配置NGINX支持proxy_protocol
nginx 上的改动有以下几点。 第一是改listen 支持proxy_protocol;
假定原来监听的是443端口,配置如下:
listen 443 ssl;
listen [::]:443 ssl;
调整后应该改为:
listen 443 ssl proxy_protocol;
listen [::]:443 ssl proxy_protocol;
相比较之下是多了proxy_protocol这个协议标识。
此外还要添加如下参数:
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
real_ip_recursive on;
注意127.0.0.1是frpc的ip,如果你的frpc安装到了局域网的其他主机,则需要修改为正确的ip。如果此处ip设置不正确,获取到的用户ip将仍为frpc的ip。
配置NGINX获取真实IP
上述配置能让FRP传递真实IP,nginx拿到真实的IP,但是在应用层面还是没有真实IP的,所以需要在nginx的代理配置上再做一些处理。主要是需要添加proxy_set_header X-Real-IP $remote_addr;
和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
这两段
location / {
proxy_ssl_server_name on;
proxy_ssl_name $host;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
完整的一个配置
server {
listen 443 ssl proxy_protocol;
listen [::]:443 ssl proxy_protocol;
server_name blog.alvinkwok.cn;
#charset koi8-r;
access_log logs/blog.alvinkwok.cn.log main;
#ssl
ssl_certificate ./cert/blog.alvinkwok.cn.pem;
ssl_certificate_key ./cert/blog.alvinkwok.cn.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
#自定义设置使用的TLS协议的类型以及加密套件(以下为配置示例,请您自行评估是否需要配置)
#TLS协议版本越高,HTTPS通信的安全性越高,但是相较于低版本TLS协议,高版本TLS协议对浏览器的兼容性较差。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
#表示优先使用服务端加密套件。默认开启
ssl_prefer_server_ciphers on;
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
real_ip_recursive on;
location / {
proxy_ssl_server_name on;
proxy_ssl_name $host;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}