chaitin / SafeLine

serve as a reverse proxy to protect your web services from attacks and exploits.
https://waf.chaitin.com
GNU General Public License v3.0
11.85k stars 727 forks source link

[建议] 支持接收PROXY Protocol,方便的获取真实IP #359

Open cddqssc opened 11 months ago

cddqssc commented 11 months ago

背景与遇到的问题

当waf的上游是端口转发(例如frp)或者负载均衡器的时候,waf无法获取真实IP,NGINX的PROXY Protocol就是解决这个问题的:https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/

建议的解决方案

实际上很简单:根据nginx文档只需要添加proxy_protocol字段到监听的端口后面,就能获取真实IP了 server { listen 80 proxy_protocol; listen 443 ssl proxy_protocol

...

}

目前手动修改配置文件服务重启会被覆盖,也无法在custom的config添加这个字段 建议:能不能UI加一个选项,然后就能在配置文件中加上这个proxy_protocol

cddqssc commented 11 months ago

目前waf可以从http header中获取真实IP(X-Real-IP),但是这样不太优雅,因为如果上游没有传递X-Real-IP(例如端口转发),就获取不到真实IP。而如果使用proxy_protocol,waf就能直接从网络连接中获取真实IP

Lorna0 commented 11 months ago

通过 Header 传递真实 IP 是 HTTP 下的标准解决方案,七层负载一般都支持,咋会不优雅。

proxy protocol 只在纯四层负载的情况下有意义,而且也不是很常用的方案(大多直接从网络层转发,不需要处理 IP。网络环境不支持的话也直接上七层负载),处理 SMTP、POP3、IMAP 这些协议的时候可能会用到,对代理 HTTP 的 WAF 来说使用场景似乎比较有限呀。

cddqssc commented 11 months ago

通过 Header 传递真实 IP 是 HTTP 下的标准解决方案,七层负载一般都支持,咋会不优雅。

proxy protocol 只在纯四层负载的情况下有意义,而且也不是很常用的方案(大多直接从网络层转发,不需要处理 IP。网络环境不支持的话也直接上七层负载),处理 SMTP、POP3、IMAP 这些协议的时候可能会用到,对代理 HTTP 的 WAF 来说使用场景似乎比较有限呀。

举个例子: 用户通过HTTPS访问服务器,服务器把HTTPS流量通过端口转发(或者负载均衡器)给WAF,如下图 image

这个时候,Header里面没有真实IP,WAF获取不到真实IP。想要在header里面添加XFF,就要在转发那一层解密后添加XFF后再传递给WAF,这样全程就不是HTTPS了,就造成了不安全因素,而且麻烦。 我希望到waf之前的流量全程都是HTTPS,然后WAF来解密处理,而且waf仅仅是添加一个proxy protocol就能获取真实IP,既安全又方便。

这种场景可能并不常见,但是也不能说很稀有吧,端口转发/负载均衡应该也是比较常见的吧?waf文档里面是支持这样的接入方式的,并且添加这个功能比较容易。

ac-sc commented 10 months ago

通过 Header 传递真实 IP 是 HTTP 下的标准解决方案,七层负载一般都支持,咋会不优雅。 proxy protocol 只在纯四层负载的情况下有意义,而且也不是很常用的方案(大多直接从网络层转发,不需要处理 IP。网络环境不支持的话也直接上七层负载),处理 SMTP、POP3、IMAP 这些协议的时候可能会用到,对代理 HTTP 的 WAF 来说使用场景似乎比较有限呀。

举个例子: 用户通过HTTPS访问服务器,服务器把HTTPS流量通过端口转发(或者负载均衡器)给WAF,如下图 image

这个时候,Header里面没有真实IP,WAF获取不到真实IP。想要在header里面添加XFF,就要在转发那一层解密后添加XFF后再传递给WAF,这样全程就不是HTTPS了,就造成了不安全因素,而且麻烦。 我希望到waf之前的流量全程都是HTTPS,然后WAF来解密处理,而且waf仅仅是添加一个proxy protocol就能获取真实IP,既安全又方便。

这种场景可能并不常见,但是也不能说很稀有吧,端口转发/负载均衡应该也是比较常见的吧?waf文档里面是支持这样的接入方式的,并且添加这个功能比较容易。

如果是图上的这种方式,就算waf支持pp协议,从转口转发过来的数据如果做了源地址转换,waf是不是也无法获取到客户端的真实ip地址?

Trenck commented 10 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

cddqssc commented 10 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

你是认真的吗?

Lorna0 commented 10 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

你是认真的吗?

一般正式网站确实是这样部的,最外层的设备放证书,源 IP 信息用 XFF 或 X-Real-IP 来传递。中间需要全程加密的话,就都走 HTTPS。例如证书放 CDN 上,CDN 给源站生成一个自己信任的自签证书,然后用 https 连源站,这样全程都是 HTTPS。

对于负载均衡来说,web 流量的目的端口都是 80,站点信息是放在 host 里,解了密才知道是哪个站。有时候还需要根据URL、UA 等进行负载,这些都需要解密。如果没有这些需求,想只通过目的端口进行转发,那也可以直接四层路由来转发和负载,比七层代理的方案性能还高些,所以一般正式网站的负载均衡都会解密。Proxy protocol 主要是用来代理 SMTP、POP3、IMAP 这些 TCP 协议,代理网站的情况比较少见。

我盲猜你的情况是个人自建了很多 TCP 服务,包括一个 http 服务,然后想要统一通过负载代理出去?这种情况企业级 waf 确实几乎没有,可能是社区版特有需求吧,看看大家反馈。

cddqssc commented 10 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

你是认真的吗?

一般正式网站确实是这样部的,最外层的设备放证书,源 IP 信息用 XFF 或 X-Real-IP 来传递。中间需要全程加密的话,就都走 HTTPS。例如证书放 CDN 上,CDN 给源站生成一个自己信任的自签证书,然后用 https 连源站,这样全程都是 HTTPS。

对于负载均衡来说,web 流量的目的端口都是 80,站点信息是放在 host 里,解了密才知道是哪个站。有时候还需要根据URL、UA 等进行负载,这些都需要解密。如果没有这些需求,想只通过目的端口进行转发,那也可以直接四层路由来转发和负载,比七层代理的方案性能还高些,所以一般正式网站的负载均衡都会解密。Proxy protocol 主要是用来代理 SMTP、POP3、IMAP 这些 TCP 协议,代理网站的情况比较少见。

我盲猜你的情况是个人自建了很多 TCP 服务,包括一个 http 服务,然后想要统一通过负载代理出去?这种情况企业级 waf 确实几乎没有,可能是社区版特有需求吧,看看大家反馈。

感谢答复,这个问题对我个人来说已经解决,之前不太清楚如何手动编辑conf文件,修改后老是自动被覆盖。 现在已经手动修改了,并且可以正常运行了,需要此功能的可以参考如何修改conf文件:https://waf-ce.chaitin.cn/docs/faq/other

guorenxi commented 9 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

你是认真的吗?

一般正式网站确实是这样部的,最外层的设备放证书,源 IP 信息用 XFF 或 X-Real-IP 来传递。中间需要全程加密的话,就都走 HTTPS。例如证书放 CDN 上,CDN 给源站生成一个自己信任的自签证书,然后用 https 连源站,这样全程都是 HTTPS。 对于负载均衡来说,web 流量的目的端口都是 80,站点信息是放在 host 里,解了密才知道是哪个站。有时候还需要根据URL、UA 等进行负载,这些都需要解密。如果没有这些需求,想只通过目的端口进行转发,那也可以直接四层路由来转发和负载,比七层代理的方案性能还高些,所以一般正式网站的负载均衡都会解密。Proxy protocol 主要是用来代理 SMTP、POP3、IMAP 这些 TCP 协议,代理网站的情况比较少见。 我盲猜你的情况是个人自建了很多 TCP 服务,包括一个 http 服务,然后想要统一通过负载代理出去?这种情况企业级 waf 确实几乎没有,可能是社区版特有需求吧,看看大家反馈。

感谢答复,这个问题对我个人来说已经解决,之前不太清楚如何手动编辑conf文件,修改后老是自动被覆盖。 现在已经手动修改了,并且可以正常运行了,需要此功能的可以参考如何修改conf文件:https://waf-ce.chaitin.cn/docs/faq/other

谢谢,我也正在找这个解决方法。

gospider007 commented 8 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

你是认真的吗

wuyue92tree commented 5 months ago

在header里面添加XFF,再以https转给waf,这中间还是可以是加密的

你是认真的吗?

一般正式网站确实是这样部的,最外层的设备放证书,源 IP 信息用 XFF 或 X-Real-IP 来传递。中间需要全程加密的话,就都走 HTTPS。例如证书放 CDN 上,CDN 给源站生成一个自己信任的自签证书,然后用 https 连源站,这样全程都是 HTTPS。 对于负载均衡来说,web 流量的目的端口都是 80,站点信息是放在 host 里,解了密才知道是哪个站。有时候还需要根据URL、UA 等进行负载,这些都需要解密。如果没有这些需求,想只通过目的端口进行转发,那也可以直接四层路由来转发和负载,比七层代理的方案性能还高些,所以一般正式网站的负载均衡都会解密。Proxy protocol 主要是用来代理 SMTP、POP3、IMAP 这些 TCP 协议,代理网站的情况比较少见。 我盲猜你的情况是个人自建了很多 TCP 服务,包括一个 http 服务,然后想要统一通过负载代理出去?这种情况企业级 waf 确实几乎没有,可能是社区版特有需求吧,看看大家反馈。

感谢答复,这个问题对我个人来说已经解决,之前不太清楚如何手动编辑conf文件,修改后老是自动被覆盖。 现在已经手动修改了,并且可以正常运行了,需要此功能的可以参考如何修改conf文件:https://waf-ce.chaitin.cn/docs/faq/other

proxy protocol 好像只能在server中修改listen设置,location下怎么处理呢,能给个配置参考一下吗,谢谢~

1447262390 commented 5 months ago

目前我也碰到这个问题,希望能找到支持接收PROXY Protocol获取真实ip。希望后续能得到支持

zlq1503 commented 2 months ago

楼主是怎么修改的nginx 模版文件支持 proxy protocol 能说明下吗?

QLozin commented 2 months ago

楼主是怎么修改的nginx 模版文件支持 proxy protocol 能说明下吗?

找到一个 博客 里有教程,但是使用的是自建的FRP,也许需要挑着看,我也在找解决方法。

目前使用一个简单的办法解决这个问题:

  1. 在FRP服务商/自建FRP设 修改设置,使得它们使用 proxy_protocol_version = V2 协议来进行访问,否则你的访问会出现问题且能在NGINX error.log 里看到 broken header 字样
  2. 在机器内额外增加一个NGINX作为前置反代,端口避免使用80/443 (雷池默认监听,会冲突)
  3. 将流量使用HTTP反代理到本地的雷池(localhost:80),同时listen块增加proxy_protocol,并且增加proxy_set_header X-Real-IP $proxy_protocol_addr;
  4. 雷池修改获取IP地址的地方为 X-Real-IP

虽然稍微麻烦但是大概解决了问题,能看到地图上中国的地方出现颜色了。

sollyu commented 3 weeks ago

我也遇到了这个问题(我是FRP),我的解决方案是:每次启动WAF后手动修改配置文件IF_backend_XX,在配置里增加

server {
    listen 0.0.0.0:9444 ssl http2 proxy_protocol;
    listen [::]:9444 ssl http2 proxy_protocol;
}

修改完后,使用命令重新waf的nginx:

docker exec safeline-tengine nginx -s reload

能用,也是麻烦,期待支持这个特性,就和支持http2一样,应该难度不大吧。

shengjidaguai2 commented 1 week ago

+1