长亭百川云 - 技术讨论

雷池+frp 批量设置proxy_protocol实现真实IP透传

发布于 3 个月前

# 雷池 WAF
# 技术博客

发布于 3 个月前

头像

つ微凉徒眸意浅挚半

更新于 3 个月前

5

0

需求

内网部署safeline,通过frp让外网访问内部web网站服务,让safeline记录真实外网攻击IP
safeline 跟 frp都部署在同一台服务器:192.168.2.103

frp client 配置

frpc只需要在https上添加transport.proxyProtocolVersion = "v2"即可,例如

1root@safeline:~# cat /etc/frp/frpc.toml
2[[proxies]]
3name = "web1"
4type = "https"
5localIP = "192.168.2.103"
6localPort = 443
7subdomain = "web1"
8transport.proxyProtocolVersion = "v2"
9
10[[proxies]]
11name = "web2"
12type = "https"
13localIP = "192.168.2.103"
14localPort = 443
15subdomain = "web2"
16transport.proxyProtocolVersion = "v2"

保存并且重启frp服务

safeline配置

safeline不支持web界面添加proxy_protocol支持,无法正常搭配frp显示真实IP,需要直接修改配置文件

1. 修改proxy_params 配置文件

/data/safeline/resources/nginx/proxy_params配置文件不会随着safeline重启而重置,我们在这里给配置全局开启proxy_protocol

这里注意需要修改set_real_ip_from 服务器的 IP 地址;,改为自己frps服务器的ip地址

1root@safeline:/data/safeline/resources/nginx# cat /data/safeline/resources/nginx/proxy_params 
2# 内网地址范围
3set_real_ip_from 192.168.0.0/16;  # 覆盖 192.168.0.0 到 192.168.255.255
4set_real_ip_from 172.16.0.0/12;   # 覆盖 172.16.0.0 到 172.31.255.255
5set_real_ip_from 10.0.0.0/8;      # 覆盖 10.0.0.0 到 10.255.255.255
6
7# 公网 frps 服务器的 IP 地址
8set_real_ip_from 服务器的 IP 地址;
9
10real_ip_header proxy_protocol;
11
12# 其他代理设置
13proxy_set_header X-Real-IP $realip_remote_addr;
14proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
15proxy_set_header X-Forwarded-Proto $scheme;
16proxy_headers_hash_max_size 1024;
17proxy_headers_hash_bucket_size 128;
18
19proxy_http_version 1.1;
20proxy_set_header Upgrade $http_upgrade;
21proxy_set_header Connection $connection_upgrade;
22proxy_hide_header X-Powered-By;
23
24# 添加条件判断以兼容非 proxy_protocol 连接
25set $proxy_x_forwarded_for $proxy_add_x_forwarded_for;
26set $proxy_x_real_ip $remote_addr;
27
28if ($proxy_protocol_addr) {
29    set $proxy_x_forwarded_for "$proxy_protocol_addr, $proxy_x_forwarded_for";
30    set $proxy_x_real_ip $proxy_protocol_addr;
31}
32
33proxy_set_header X-Forwarded-For $proxy_x_forwarded_for;
34proxy_set_header X-Real-IP $proxy_x_real_ip;

2. 创建config-proxy_protocol.sh脚本

我们要给/data/safeline/resources/nginx/sites-enabled目录下所有的IF_backend文件,在监听部分上添加proxy_protocol支持,其中增加一个白名单域名,白名单中的域名不做任何更改,该脚本可实现批量添加或者移除所有proxy_protocol

我们把脚本放在/data/safeline/resources/nginx/sites-enabled目录下,即/data/safeline/resources/nginx/sites-enabled/config-proxy_protocol.sh

1)创建脚本

1vim /data/safeline/resources/nginx/sites-enabled/config-proxy_protocol.sh

2) 脚本内容如下,请注意要修改成自己的主域名子域名

1#!/bin/bash
2
3# 主域名 ;改为自己的主域名,例如 ttxs.com
4main_domain="ttxs.com"
5
6# 白名单子域名列表,如:op1.ttxs.com、op2.ttxs.com
7whitelist_subdomains=(
8    "op1"
9    "op2"
10)
11
12# 帮助函数
13show_help() {
14    echo "用法:$0 [true|false]"
15    echo "  true  - 添加 proxy_protocol 支持"
16    echo "  false - 移除 proxy_protocol 支持"
17    echo "  ?     - 显示此帮助信息"
18}
19
20# 检查参数
21case "$1" in
22    true|false) action=$1 ;;
23    ""|"?") show_help; exit 0 ;;
24    *) echo "错误:参数必须是 true 或 false。"; exit 1 ;;
25esac
26
27# 修改配置函数
28modify_config() {
29    local file=$1
30    local add_proxy=$2
31    local changed=false
32
33    while IFS= read -r line; do
34        if [[ $line =~ listen.*:443 ]]; then
35            if $add_proxy && [[ ! $line =~ proxy_protocol ]]; then
36                line="${line/ssl http2;/ssl http2 proxy_protocol;}"
37                changed=true
38            elif ! $add_proxy && [[ $line =~ proxy_protocol ]]; then
39                line="${line/ proxy_protocol/}"
40                changed=true
41            fi
42        fi
43        echo "$line"
44    done < "$file" > "${file}.tmp"
45
46    if $changed; then
47        mv "${file}.tmp" "$file"
48        if $add_proxy; then
49            echo "已添加 proxy_protocol 支持: $file"
50        else
51            echo "已移除 proxy_protocol 支持: $file"
52        fi
53    else
54        rm "${file}.tmp"
55        if $add_proxy; then
56            echo "已支持 proxy_protocol,无需修改: $file"
57        else
58            echo "无 proxy_protocol 支持,无需修改: $file"
59        fi
60    fi
61}
62
63# 主处理逻辑
64for file in IF_backend_*; do
65    [ -f "$file" ] || continue
66
67    server_name=$(grep "server_name" "$file" | awk '{print $2}' | tr -d ';\n' | sed 's/on$//')
68    subdomain=${server_name%%.*}
69    
70    if [[ " ${whitelist_subdomains[*]} " =~ " $subdomain " ]]; then
71        echo "白名单域名,跳过修改: $file ($server_name)"
72        continue
73    fi
74    
75    case "$action" in
76        true)  modify_config "$file" true ;;
77        false) modify_config "$file" false ;;
78        *)     modify_config "$file" true ;; # 默认添加支持
79    esac
80done
81
82# 测试并重新加载 Nginx 配置
83echo "测试 Nginx 配置..."
84if docker exec safeline-tengine nginx -t; then
85    echo "重新加载 Nginx 配置..."
86    docker exec safeline-tengine nginx -s reload
87    echo "操作完成"
88else
89    echo "Nginx 配置测试失败,未重新加载配置"
90    exit 1
91fi

3)给脚本添加执行权限

1chmod +x /data/safeline/resources/nginx/sites-enabled/config-proxy_protocol.sh

3. 执行脚本进行批量修改

执行脚本,可传入参数truefalse
用法

1root@safeline:/data/safeline/resources/nginx/sites-enabled# bash config-proxy_protocol.sh 
2用法:config-proxy_protocol.sh [true|false]
3  true  - 添加 proxy_protocol 支持
4  false - 移除 proxy_protocol 支持
5  ?     - 显示此帮助信息

image.png

1)执行批量添加proxy_protocol示例

bash config-proxy_protocol.sh true

image.png

2)批量取消proxy_protocol添加示例

bash config-proxy_protocol.sh false

image.png

因为我们添加有白名单,而所有的防护站点都是监听同一个443端口,所以当有站点加白没有添加protocol支持的时候,执行会打印如下告警

1nginx: [warn] protocol options redefined for 0.0.0.0:443 in /etc/nginx/sites-enabled/IF_backend_3:13

含义是:"protocol options redefined" 表示在 Nginx 配置中,对于同一个监听地址和端口(在这个例子中是 0.0.0.0:443),协议选项被重复定义了。我们忽略这个报警即可。

当我们不做白名单,所有站点都添加proxy_protocol,那就不会打印这个告警了

如果重启服务器或者服务,IF_backend文件被重置,那么直接执行一下该脚本即可

4. 测试

上面都配置好之后,访问配置好的域名,发现小地图已经正常显示归属地,配置成功

image.png

头像

齐天大圣孙悟空

管理员

更新于 3 个月前

0

0

可以发图片,直接粘贴就行

头像

つ微凉徒眸意浅挚半

更新于 3 个月前

刚开始预览的时候,发现图片没加载,发布之后才有,已纠正

头像

樊高峰

更新于 21 天前

0

0

2024年12月6日,如果按照帖主的教程配置后出现无法访问的问题,例如浏览器出现 “ERR_CONNECTION_CLOSED” 的错误,nginx的错误日志中出现 “while reading PROXY protocol,client:127.0.0.1,server: 0.0.0.0:443”,可将frp.ini配置文件中的 transport.proxyProtocolVersion = "v2" 更换为 proxy_protocol_version = v2 ,可解决frp不使用proxy_protocol协议的问题。

头像
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备2024055124号-2