xiaorouji / openwrt-passwall

7.28k stars 2.66k forks source link

[Feature Request]: 支持通过Geoip和Geosite进行捕获分流 #3492

Closed snowie2000 closed 2 days ago

snowie2000 commented 2 weeks ago

描述你想要的新功能

passwall在非全局模式(tcp默认不代理情况下),只能捕获代理列表和gfwlist中的域名和ip。 虽然在分流列表中可以使用geoip和geosite标签,但如果对应的ip和域名不在gfwlist中的话,实际上是不会生效的。

描述你想要的解决方案

这里有一个项目,支持通过shell将geoip和geosite中的ip范围和列表提取出来,以便被dnsmasq和ipset识别和处理。

makefile也已经提供并通过编译。只是我不知道怎么加入到pw的依赖库中。

描述你考虑过的替代方案

No response

其他信息

相关bug #3481 #3474

PS: 规则列表 和 规则管理 这两个名称实在是太相似了,我总是搞不清哪个是哪个,实际一个是手动输入域名来决定是否代理,另一个类似手机等软件的分流,建议就直接改名叫分流。

lwb1978 commented 2 weeks ago

不只是添加到依赖库这么简单,还得写程序支持,这个慢慢来。你看能否先编译个x86平台的程序发上来测试看。

snowie2000 commented 2 weeks ago

geoview.zip 附件是在普通linux/amd64下的geoview程序。我没有openwrt x64的环境,不确定在上面是否能运行。

lwb1978 commented 2 weeks ago

我迟点测试看,不过我发现go程序真的好大,这么简单的一个功能的小程序5M多,添加到PW里的话估计对小闪存的硬路由不太友好。

snowie2000 commented 2 weeks ago

我没有删除符号,所以体积会大一些,另外如果是mips或者arm的话,体积也会更小些,但不管怎么样内部都有一个运行库在里面,不可能太小的。sing-box和v2,frp全部都是go的,都是挺大的,小闪存的路由确实不好办,还是老老实实用ss吧。

如果有时间的话,可以考虑作为可选依赖,如果找不到geoview就显示一个提示并跳过对应的规则摘录

lwb1978 commented 2 weeks ago

我没有删除符号,所以体积会大一些,另外如果是mips或者arm的话,体积也会更小些,但不管怎么样内部都有一个运行库在里面,不可能太小的。sing-box和v2,frp全部都是go的,都是挺大的,小闪存的路由确实不好办,还是老老实实用ss吧。

如果有时间的话,可以考虑作为可选依赖,如果找不到geoview就显示一个提示并跳过对应的规则摘录

我先测试下,然后想想如何把它加到PW里,其实如果不考虑小闪存路由的话,直接做成依赖,系统只需要Geoip和Geosite数据库就行,chnlist、gfwlist、chnroute、chnroute6都可以不要了,本地生成就行。

snowie2000 commented 2 weeks ago

确实是可以的,geoip和geosite里面都包含了。 现在存在一个问题那就是虽然geoview同时支持v2和sing格式,但这两者自己却是互不兼容的,这导致在分流规则中,如果写了v2中的tag,sing会报错提示找不到,反过来也一样。

例如分流规则geosite:gfw,在xray下可以用,在singbox下就会报错,因为sing自己的geosite中并没有这个扩展标签

lwb1978 commented 2 weeks ago

sing-box已经废除geoip和geosite了,只是没有移除,如果真正移除的话还是个麻烦事,小肉鸡并不打算适配它,其实我个人也觉得现在新出的好几款插件都是针对sing-box专用的,如果sing-box真移除geoip和geosite的话干脆PW也移除sing-box的分流功能算了,只将它作为协议的转发器使用。让PW专注于做xray的插件。

SakuraFallingMad commented 2 weeks ago

sing-box已经废除geoip和geosite了,只是没有移除,如果真正移除的话还是个麻烦事,小肉鸡并不打算适配它,其实我个人也觉得现在新出的好几款插件都是针对sing-box专用的,如果sing-box真移除geoip和geosite的话干脆PW也移除sing-box的分流功能算了,只将它作为协议的转发器使用。让PW专注于做xray的插件。

现在主用sing-box分流是因为分流组域名dns匹配到分流,如果xray都可以做到,其实都无所谓了。

snowie2000 commented 2 weeks ago

其实也不是坏事,这意味着我们可以通过程序主动生成singbox的新格式,而新格式都是独立的碎片文件,很适合这个场景

SakuraFallingMad commented 2 weeks ago

我没有删除符号,所以体积会大一些,另外如果是mips或者arm的话,体积也会更小些,但不管怎么样内部都有一个运行库在里面,不可能太小的。sing-box和v2,frp全部都是go的,都是挺大的,小闪存的路由确实不好办,还是老老实实用ss吧。 如果有时间的话,可以考虑作为可选依赖,如果找不到geoview就显示一个提示并跳过对应的规则摘录

我先测试下,然后想想如何把它加到PW里,其实如果不考虑小闪存路由的话,直接做成依赖,系统只需要Geoip和Geosite数据库就行,chnlist、gfwlist、chnroute、chnroute6都可以不要了,本地生成就行。

chnlist、chnroute、chnroute6自定义还挺好使的,sing-box的用matacubex的geo也挺不错,xray的geo写死Loyalsoldier,可惜可惜

CharlesLocke commented 2 weeks ago

sing-box已经废除geoip和geosite了,只是没有移除,如果真正移除的话还是个麻烦事,小肉鸡并不打算适配它,其实我个人也觉得现在新出的好几款插件都是针对sing-box专用的,如果sing-box真移除geoip和geosite的话干脆PW也移除sing-box的分流功能算了,只将它作为协议的转发器使用。让PW专注于做xray的插件。

sing-box网站写了会在1.12.0版本中移除。

snowie2000 commented 2 weeks ago

geoview已经添加了对ruleset的支持,可以生成符合singbox要求的ruleset片段

xiaorouji commented 2 weeks ago

Actually... I have modified the sing-box core to achieve true direct connection a year ago. But for some reasons, it is not open source yet......

lwb1978 commented 2 weeks ago

Actually... I have modified the sing-box core to achieve true direct connection a year ago. But for some reasons, it is not open source yet......

终于等来老大的出现,期待能在合适的时机开源。

@snowie2000 另外我抽了点时间用楼主的项目简单修改了一下nftables.sh,能解析geoip并添加到passwall_shuntlist,楼主可以测试一下,开关部分还没有做,仅测试效果。 nftables.zip

@xiaorouji 同时征求一下老大的意见,是否有必要引入这个项目到PW中。

lwb1978 commented 2 weeks ago

如果老大认为有必要的话我再做开关,同时把dns部分添加geosite支持

qingtian110 commented 2 weeks ago

隔壁有个现成的 geo 数据提取 不过也是 go 的 7M
image

snowie2000 commented 2 weeks ago

隔壁有个现成的 geo 数据提取 不过也是 go 的 7M

image

确实,我之前都没有找到这样的项目。那也可以用他的项目,似乎更全面。

@lwb1978 我刚换了设备,现在回到iptables了……

snowie2000 commented 2 weeks ago

Actually... I have modified the sing-box core to achieve true direct connection a year ago. But for some reasons, it is not open source yet......

What is a "true direct" mode? Does this mean that it can rely solely on hardware to forward packets without consuming too much CPU power? If it does, it would be the end for openclash-like solutions!

Although you have immigrated to a foreign country, congrats, there is still a high demand for walkaround geo-blocked services for people outside of mainland China. Maybe, you could still be here to improve the project for that kind of purpose. One more people is one more possibility.

Anyways, if you decide to leave, would it be nice to give people who are still working on it more power and freedom to decide where the project goes?

lwb1978 commented 2 weeks ago

确实,我之前都没有找到这样的项目。那也可以用他的项目,似乎更全面。

@lwb1978 我刚换了设备,现在回到iptables了……

如果引用新组件,我跟倾向于用你的项目,毕竟沟通方便,也更容易进行针对性的开发和完善。

snowie2000 commented 2 weeks ago

确实,我之前都没有找到这样的项目。那也可以用他的项目,似乎更全面。 @lwb1978 我刚换了设备,现在回到iptables了……

如果引用新组件,我跟倾向于用你的项目,毕竟沟通方便,也更容易进行针对性的开发和完善。

mosdns依赖v2dat,所以如果用户已经安装了mosdns则很可能已经有v2dat了,这是依赖上的体积优势。 不过我简单看了下他的依赖,他没有依赖sing任何相关的代码,也没有任何和singbox相关的定义,只是使用protobuf来解析geo*,这意味着它是不能支持sing-box相关的任何功能的。

geoview是针对shell指令特化的,也会根据实际使用的需求进行调整,v2dat更加独立一些,需要你去适应它的输出

lwb1978 commented 2 weeks ago

@lwb1978 我刚换了设备,现在回到iptables了……

@snowie2000 我临时改了个ipt的,麻烦测试一下效果,随便看看添加组件后分流效果是否达到预期,域名方面还没添加,先测试纯ip分流 iptables.zip

snowie2000 commented 2 weeks ago

timeout 0无法使用,提示list is not created with timeout support.

另外我发现geoview在运行时占用内存太大了,我需要优化一下

lwb1978 commented 2 weeks ago

timeout 0无法使用,提示list is not created with timeout support.

另外我发现geoview在运行时占用内存太大了,我需要优化一下

提示list is not created with timeout support.可能是你系统的ipset版本问题,我在imm的23.05的iptables模式下是可以支持timeout 0的; geoview我还没留意内存占用问题,毕竟它运行数据量小的话1-2秒甚至不到1秒就结束了,不过能优化肯定好,怕小内存设备瞬间爆了。

snowie2000 commented 2 weeks ago

timeout 0无法使用,提示list is not created with timeout support. 另外我发现geoview在运行时占用内存太大了,我需要优化一下

提示list is not created with timeout support.可能是你系统的ipset版本问题,我在imm的23.05的iptables模式下是可以支持timeout 0的; geoview我还没留意内存占用问题,毕竟它运行数据量小的话1-2秒甚至不到1秒就结束了,不过能优化肯定好,怕小内存设备瞬间爆了。

但是我的ipset之前都是正常的,也就是说原本的iptables脚本并没有用到timeout。 我正在参考xray的实现优化内存占用

lwb1978 commented 2 weeks ago

timeout 0无法使用,提示list is not created with timeout support. 另外我发现geoview在运行时占用内存太大了,我需要优化一下

提示list is not created with timeout support.可能是你系统的ipset版本问题,我在imm的23.05的iptables模式下是可以支持timeout 0的; geoview我还没留意内存占用问题,毕竟它运行数据量小的话1-2秒甚至不到1秒就结束了,不过能优化肯定好,怕小内存设备瞬间爆了。

但是我的ipset之前都是正常的,也就是说原本的iptables脚本并没有用到timeout。 我正在参考xray的实现优化内存占用

timeout是9月12日加入的 https://github.com/xiaorouji/openwrt-passwall/commit/f5ab6219bdd5fcac223b1f2fe104e96a3d746a25

snowie2000 commented 2 weeks ago

我的设备是刚装的pw,所以肯定是在9月12日之后的版本,但经过测试,geoip中的ip并没有添加成功,逐条手工执行后就发现是timeout的问题。删掉timeout那部分后可以正常添加。

lwb1978 commented 2 weeks ago

你是否没用我的文件直接替换?因为原来的sh里是: ipset -! create $IPSET_SHUNTLIST nethash maxelem 1048576 没有创建为支持timeout的列表,我发的sh里这里已经改为: ipset -! create $IPSET_SHUNTLIST nethash maxelem 1048576 timeout 172800 如果是直接用我修改的sh替换的,那手动执行一次清理ipset再试试

snowie2000 commented 2 weeks ago

我直接用你的代码替换的。也清理过了。。。一会儿我再试试

lwb1978 commented 2 weeks ago

那就奇怪了,如果出错那不应该只是geoip添加到IPSET_SHUNTLIST的代码出错,因为上面其他列表的ipset也都是用同样的参数追加ip到ipset的,要不重启路由试试。😂

snowie2000 commented 2 weeks ago

好像可以了,可能就是没有清空ipset导致的,很奇怪。目前内存占用在70-90M之间,发现最大的问题是geoip文件体积本身就很大,读入内存就已经用掉了20M,反序列化用到20M,就40M了,随后就是合并CIDR的性能开销存在问题,现在的代码占用内存相当大,需要优化一下。

lwb1978 commented 2 weeks ago

好像可以了,可能就是没有清空ipset导致的,很奇怪。目前内存占用在70-90M之间,发现最大的问题是geoip文件体积本身就很大,读入内存就已经用掉了20M,反序列化用到20M,就40M了,随后就是合并CIDR的性能开销存在问题,现在的代码占用内存相当大,需要优化一下。

其实这个也正是我担心的事情,如果引入geoview后,启用这个功能后根据分流列表和用户的设置情况,可能会有大量的geoip和geosite预读到系统,那系统也会消耗不少的内存。

snowie2000 commented 2 weeks ago

域名是dnsmasq控制的,ip是ipset控制的,这两个的内存控制都相当不错,不会有什么大问题。实际上也就美国的ip段特别夸张,别的国家哪有那么多ip

snowie2000 commented 2 weeks ago

至于性能太差的设备,我的sft1200连chnroute都会挂……

snowie2000 commented 2 weeks ago

@lwb1978 新的脚本出现了一个新的问题:如果某个分流规则只对udp生效,对tcp不生效,则根本不会被加入到shuntlist,旧版本脚本无此问题

lwb1978 commented 2 weeks ago

@lwb1978 新的脚本出现了一个新的问题:如果某个分流规则只对udp生效,对tcp不生效,则根本不会被加入到shuntlist,旧版本脚本无此问题

我并没有对tcp和udp做判断啊,只要是在xray的分流列表内都加到shuntlist中,不过我区分开了直连的分流列表,直连的列表我是加到了白名单中

snowie2000 commented 2 weeks ago

@lwb1978 新的脚本出现了一个新的问题:如果某个分流规则只对udp生效,对tcp不生效,则根本不会被加入到shuntlist,旧版本脚本无此问题

我并没有对tcp和udp做判断啊,只要是在xray的分流列表内都加到shuntlist中,不过我区分开了直连的分流列表,直连的列表我是加到了白名单中

经过测试就是如果某分流规则,在tcp节点中是关闭,在udp节点中是启用,则会被忽略,不会加入ipset中

lwb1978 commented 2 weeks ago

明白了

lwb1978 commented 2 weeks ago

修改时没有考虑到tcp和udp分开两个分流节点的情况,再试试下面的代码: iptables.zip

snowie2000 commented 2 weeks ago

经过测试代码是可以正常工作的。在我的r3s上测试的内存占用是,加了10万的us ip后,内存总占用大约多出10M,这同时包括了ipset和singbox两者的占用,所以内存压力是完全可以接受的。

另外在测试过程中发现脚本会调用两次geoview,而且第一次的参数是错误的,缺少了list信息,却多了-ipv4这样的无效参数,不知道怎么回事

lwb1978 commented 2 weeks ago

经过测试代码是可以正常工作的。在我的r3s上测试的内存占用是,加了10万的us ip后,内存总占用大约多出10M,这同时包括了ipset和singbox两者的占用,所以内存压力是完全可以接受的。

另外在测试过程中发现脚本会调用两次geoview,而且第一次的参数是错误的,缺少了list信息,却多了-ipv4这样的无效参数,不知道怎么回事

我写了函数的,分别提取v4和v6的地址加入对应的ipset,最终调用你程序的格式是以函数内的为准,你大概看一眼我的sh函数脚本就知道了:

get_geoip() {
    local geoip_code="$1"
    local geoip_type_flag=""
    local geoip_path="$(config_t_get global_rules v2ray_location_asset)"
    geoip_path="${geoip_path%*/}/geoip.dat"
    [ -e "$geoip_path" ] || { echo ""; return; }
    case "$2" in
        "ipv4") geoip_type_flag="-ipv6=false" ;;
        "ipv6") geoip_type_flag="-ipv4=false" ;;
    esac
    if type geoview &> /dev/null; then
        geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag
    else
        echo ""
    fi
}

第一个参数是geoip文件的路径,第二个是要提取的ip的列表名称,第三个是取出的是v4还是v6的ip。

lwb1978 commented 2 weeks ago

另外我想了解下,你添加10万的us ip时,pw从启动到完成启动大概多花了多少时间?

snowie2000 commented 2 weeks ago
> 2024-11-15 10:48:08: 删除iptables防火墙规则完成。 > 2024-11-15 10:48:08: 清空并关闭相关程序和缓存完成。 > 2024-11-15 10:48:09: TCP节点:[分流总节点],监听端口:1041 > 2024-11-15 10:48:09: UDP节点:[UDP分流],监听端口:1051 > 2024-11-15 10:48:10: DNS域名解析: > 2024-11-15 10:48:10: - Sing-Box DNS(127.0.0.1#15353) -> tcp://1.1.1.1 > 2024-11-15 10:48:10: - 节点列表中的域名(vpslist):127.0.0.1#5553 > 2024-11-15 10:48:10: - 域名白名单(whitelist):127.0.0.1#5553 > 2024-11-15 10:48:10: - 代理域名表(blacklist):127.0.0.1#15353 > 2024-11-15 10:48:11: - 防火墙域名表(gfwlist):127.0.0.1#15353 > 2024-11-15 10:48:11: - V2ray/Xray分流规则(DisneyPlus):127.0.0.1#15353 > 2024-11-15 10:48:11: - V2ray/Xray分流规则(Australia):127.0.0.1#15353 > 2024-11-15 10:48:11: - V2ray/Xray分流规则(US):127.0.0.1#15353 > 2024-11-15 10:48:12: - 默认:127.0.0.1#5553 > 2024-11-15 10:48:12: - PassWall必须依赖于Dnsmasq,如果你自行配置了错误的DNS流程,将会导致域名(直连/代理域名)分流失效!!! > 2024-11-15 10:48:12: 开始加载防火墙规则... > 2024-11-15 10:48:28: - [0]追加ISP IPv4 DNS到白名单:223.5.5.5 > 2024-11-15 10:48:28: - [0]追加ISP IPv6 DNS到白名单:fd34:5aa2:87d3:4::2 > 2024-11-15 10:48:28: - [0]加入所有IPv4节点到ipset[passwall_vpslist]直连完成 > 2024-11-15 10:48:28: - [0]加入所有IPv6节点到ipset[passwall_vpslist6]直连完成 > 2024-11-15 10:48:28: - [0]追加WAN IP到iptables:192.168.1.2 > 2024-11-15 10:48:28: - 【路由器本机】,屏蔽代理 UDP 端口[80,443] > 2024-11-15 10:48:28: - 访问控制: > 2024-11-15 10:48:29: - 【默认】,屏蔽代理 UDP 端口[80,443] > 2024-11-15 10:48:29: - 【默认】,使用 TCP 节点[分流总节点](REDIRECT:1041) > 2024-11-15 10:48:29: - 【默认】,使用 UDP 节点[UDP分流](TPROXY:1051) > 2024-11-15 10:48:29: 防火墙规则加载完成! > 2024-11-15 10:48:30: 重启 dnsmasq 服务 > 2024-11-15 10:48:30: 配置定时任务:自动更新规则。 > 2024-11-15 10:48:30: 运行完成!

应该是16秒,其中生成geoip规则大约在3秒-5秒左右.

snowie2000 commented 2 weeks ago

另外我优化了内存占用后,在大内存的机器上似乎效果不明显,但在小内存机器上较为明显一些。

在linux/amd64上的测试表明现在geoip读取us大约占用在50M上下,jp等小地区则要小得多。 geosite占用内存在3-5M之间,可以忽略不计。

profile002

snowie2000 commented 2 weeks ago

geoview发布了0.0.5版本,进一步降低了内存占用。但在sft1200这台设备上依然会OOM,这台的配置太低了,开启singbox后剩余内存不到50M,甚至不使用geoview,只要打开chnroute就会OOM崩溃,实在是用不了。不过只要不用us这样的超级国家,是可以正常使用的。

另外我发现pw的逻辑存在一个问题,那就是pw会先启动singbox/xray,然后再执行iptables等相关操作。本来应用内核就很吃内存,启动时还会伴随大量硬盘读取,这时候还要去操作ipset和geoview,就会大大增加内存和IO的压力,导致速度更加缓慢

经过测试在关闭singbox的情况下,sft1200下操作20w条us规则不会发生OOM,但开启singbox再执行就不行了

SakuraFallingMad commented 2 weeks ago

这个好,下一版本最好规则管理中,geo资源也开放自定义设定,这样可用性更好。

lwb1978 commented 2 weeks ago

现在最担心的就是怕用户在设置分流是写了一大堆的类似geoip:us这里的规则就玩完了,到时把整个geoip加载到ipset都有可能😂

snowie2000 commented 2 weeks ago

现在最担心的就是怕用户在设置分流是写了一大堆的类似geoip:us这里的规则就玩完了,到时把整个geoip加载到ipset都有可能😂

不需要担心这个问题,因为你会发现…………geoip整个列表和us列表的大小其实差不多…………而且geoview有合并列表功能,选择的地区越多,最终生成的列表反而会越小(0.0.5版本新增)

lwb1978 commented 2 weeks ago

现在的修改没有考虑到访问控制使用分流节点的情况,终于想明白当时为何把列表中所有的分流规则ip一股脑全部加入分流的设计初衷了。我估计得改回原来一股脑的方式,因为如果去判断所有分流节点的规则是否启用或者是直连是否tcp/udp的话代码相当复杂。

lwb1978 commented 2 weeks ago

我计划只判断所有节点如果使用分流且仅使用GFW模式的时候将ip加入shuntlist,如果已经是使用中国列表以外或者全局模式的话就不需要加入shuntlist了

snowie2000 commented 2 weeks ago

我都忘了还是访问控制这个功能了,这确实会导致代码变得更加复杂,如果能用lua完成这些判断就好了,用bash做确实有些复杂