前言:常见分流方案探讨

要实现透明上网冲浪,分流总是一个绕不开的难题。由此,诞生了很多不同的软件和方案,最常见的莫过于All in One的开源路由器固件,界面也非常的傻瓜小白,点点点就能用。但是缺点也很明显,良莠不齐、碎片化的软件包集成在一起的All in One路由器,稳定性肯定大打折扣,首先这类软件通常是接管了所有流量再分流,一旦软件运行崩溃,那就可能造成整个网络崩溃,其次碎片化、臃肿的软件包集成在一起运行机制变得很迷,主路由更应该做的是路由器的路由工作,跑太多服务反而拖慢了网络性能。最后,这个方案的应用场景也很有限,对企业用户来说,不太可能把整个网络寄托于一个开源路由器上。
于是也有很多人使用了旁路由的方案。跟上面的方案一样,只是把开源路由器接在主路由的下面,然后把设备的网关设置成旁路由或者dhcp网关信息,这样万一旁路由挂了的影响会变小,一些重要的设备可以设置固定的主路由网关。但这样做的话,使用旁路由的设备就相当于经过了两层nat,一些没必要经过旁路由的流量也经过了,经过两层网关,性能和稳定性也打折扣。
为了更灵活,我们把目光聚焦到路由本身。假设我们有一条企业专线(相当于旁路由),我们怎么把需要走专线的流量走专线呢?最朴素的方案,那就是维护路由表,比如很多商业路由器内置有GEOIP库,一种简单粗暴的方法就是把默认路由走企业专线,然后CN IP走宽带线路,这样确实能正常工作,使用VRRP等协议也能一定程度避免全炸,但把默认路由设置成专线可能不是个好主意,首先并不是所有流量都真的需要走专线,比如P2P流量等,某些服务会根据IP分配到国内节点等,其次IP库的更新不够及时也会对体验造成一定影响。而如果单独维护需要访问的网站的IP段,似乎又是个更繁琐的工作。
如果能基于域名进行分流,那么灵活性就会大大地提高,毕竟维护域名列表比维护IP段还是要轻松不少的,虽然有部分应用需要通过IP直连,但也只需要维护少部分IP段,大部分都可以域名规则解决。而如何通过域名来分流又是一个问题。如果你在主路由上,不乏有很多基于ipset的方案,原理就是使用一个第三方的DNS程序,当查询到对应域名的IP地址之后,把这个域名的解析结果加入ipset(相当于一个你需要分流的IP集合),然后把这些个ipset做策略路由。这种方案先不讨论稳定性,显然你需要对主路由动手脚,All in One 不在这里的讨论范围,实际上这种方案也是很多具备域名分流功能的路由器插件的原理。
有没有办法基本不改动主路由的情况下,基于域名进行分流呢?在很多年前尝试过最朴素的http反向代理,因为常见的流量协议就http和https,搭建一个sniproxy,然后把需要分流的域名解析到sniproxy的服务器IP,可行,网站能访问。但之后出现一个奇怪的现象,自从浏览器升级之后,有些https的网站有时候能访问,有时候不能,最后经过查找原来是http2导致的问题,http2有个特性,如果几个域名解析出来的IP地址一样的话,他会把这些请求合并在一起发送过去,节省开销加快访问速度。正好是这个特性,导致sniproxy无法理解和正确处理返回扔过去的流量。如果为sniproxy增加多个服务器内网IP可以缓解但也不太现实。再后来,一些开源软件比如v2开发了域名嗅探(sniffing)的特性,可以从流量中检测出http/https的域名,并重新以域名请求出站到目的地,有了这个特性,我们就可以搭建一个网关,流量扔过去,然后嗅探,再出站,而跟上面一样,每个域名的IP不能一样,于是写了一个对域名进行hash后生产对应网段IP的服务程序,比如在11.0.0.0/8网段内的“假IP池”,每个域名对应唯一的IP值(经过多个参数构造的hash出来在同一个网站相同的概率很小),然后我只需要把11.0.0.0/8,写一条静态路由到这个网关,那么被解析到11.0.0.0/8里面的域名就会自动走到这个网关出站,用起来也很顺畅。而这个方案也是有一些缺点的,比如,由于他是嗅探出来才能处理,像ssh这种协议他就无法知道原来的IP是什么,好在是http/https协议能满足大部分需求,剩下的维护路由表搞定。有没有更好的方案呢?这就是接下来要说的基于FakeIP网关的方案。

FakeIP网关的工作原理

FakeIP的概念源自RFC 3089,顾名思义就是给你返回一个假的IP地址,而这个假的IP地址作为key,来反向查找你的域名。与上面讨论的嗅探方案差不多,准备一个“假IP池”,不同的是,FakeIP把解析到的IP和域名记录下来,建立一个映射的关系,最终出站还原。以一个简单的访问qq为例:

1
2
3
4
5
6
7
8
9
# 假设你的FakeIP池是11.0.0.0/8
# 第一步,客户端发起访问请求
curl https://qq.com
# 第二步,客户端需要知道qq.com的IP地址
DNS从FakeIP地址池里返回一个FakeIP: 11.0.0.1,并把他和qq.com关联到自己的映射表里面
也就是在网关看来11.0.0.1=qq.com
# 第三步,11.0.0.0/8网段被静态路由到网关(此处不同方案策略不同,有的是在主路由上搞的)
网关接受到11.0.0.1的流量请求,从映射表里面找到11.0.0.1=qq.com
使用qq.com还原真实的请求,出站。

与嗅探的方案不同,FakeIP通过地址池和域名建立的映射关系,最终可以真实还原请求,也就是说,他理论上兼容任何协议,不管是ssh还是rdp,不管是TCP还是UDP。他还顺便解决了DNS污染和DNS泄露的问题,解析可以交给远端进行,而本地没有真实的解析过程,相比嗅探也有更低的性能开销和更好的延迟。但你也可能很早就听过了FakeIP的存在,这玩意怎么跟你说的不一样好像有很多bug?比如有什么跳过FakeIP的列表,什么米家设备不能用的问题?因为这些方案里面是All in One,先把所有域名不管是什么域名都解析成FakeIP,再扔给具备分流功能的程序里面处理分流,这样自然会产生很多奇奇怪怪的问题,因为有些协议不是所有域名请求都必须有回应的,而有些协议需要直连,而且本质稳定性跟前面的一炸全炸的方案一样。如果我们只把需要分流的域名解析到FakeIP池,除了和嗅探方案一样部分应用需要维护少量的静态路由IP段之外,理论上不会有啥问题,唯一的问题是,当FakeIP停止工作后,再重新启动,FakeIP的地址池和映射的域名就对不上了,由于客户端本地有DNS缓存,因此会经历短暂的无法连接。这个问题的缓解办法就是把FakeIP的TTL设置的尽量低(比如TTL=1),当FakeIP停止工作后DNS缓存马上失效,只要客户端遵从标准的TTL设置一般不会有太大的感知。简单来说,FakeIP的工作流程原理如下图:

主路由
主路由
FakeIP网关
FakeIP网关
客户端
客户端
DNS服务
DNS服务
FakeIP池
11.0.0.1=qq.com
......
........
FakeIP池...
被分流的域名
被分流的域名
静态路由11.0.0.0/8 下一跳是192.168.1.200
静态路由11.0.0.0/8 下一跳是192.168.1.200
192.168.1.1
192.16...
192.168.1.200
192.16...
192.168.1.2
192.16...
qq.com
qq.com
qq.com
.....
qq.com...
DNS查询
DNS查询
11.0.0.1
11.0.0...
域名命中分流列表
域名命中分流列表
返回解析11.0.0.1
返回解析11.0.0.1
192.168.1.53
192.16...
向FakeIP网关查询
向FakeIP网关查询
返回解析11.0.0.1
返回解析11.0.0.1
请求
请求
Viewer does not support full SVG 1.1

如何搭建一个FakeIP网关

网上搭建FakeIP网关的教程太多了,这里不打算讨论具体的搭建细节,而是方案选型。首先,搞个docker镜像是否可行?答案是可行,也不可行。因为docker本身的网络特性不太适合作为网关使用,搞个macvlan已经够复杂了,性能也不够好,其次更重要的原因是受到内核的限制。docker本身并不能改变宿主的内核,而无论是通过tun,tproxy或者其他方式,都依赖内核的实现,如果内核没有相应的模块,或者模块有但是对不上(比如nft和ipt),那么你做的镜像别人就不一定能跑起来。最后,因为涉及到路由转发和内核,你往往需要给容器特权,这对容器来说也不是一个好主意。简单来说,使用docker会让问题变得复杂,失去了标准化的意义。因此,我们选择使用虚拟机来搭建,linux系统选什么不太重要,能装模块就行。流量入口方面,建议使用tproxy,因为对TCP和UDP支持都很好,特别是UDP,处理链也比较高效。支持FakeIP的程序有很多,程序的官方文档一般也有附带教程,推荐的话,建议选择配置比较清晰简明的clash,配置FakeIP的DNS也比较方便。最后就是一些配合程序使用的iptables规则/nft规则,以及策略路由,这个可以很轻松在网上找到(可以搜索tproxy透明代理)。如果你觉得这个过程还是太复杂太难了,那么接下来就是我做好的一个现成的网关,轻松上手即用。

PaoPao GateWay

PaoPaoDNS

PaoPao GateWay是一个体积小巧、稳定强大的FakeIP网关系统,核心由clash/mihomo驱动,支持Full Cone NAT ,支持多种方式下发配置,支持多种出站方式,包括自定义socks5、自定义openvpn、自定义yaml节点、订阅模式和自由出站,支持节点测速自动选择、节点排除等功能,并附带web面板可供查看日志连接信息等。PaoPao GateWay可以和其他DNS服务器一起结合使用,比如配合PaoPaoDNSCUSTOM_FORWARD功能就可以完成简单精巧的分流。
Github 项目地址https://github.com/kkkgo/PaoPaoGateWay
(っ◞‸◟c)都看到这里了,点个Star
你可以从Github Release下载到最新的镜像:https://github.com/kkkgo/PaoPaoGateWay/releases

以下文档说明以Github最新文档为准

运行要求和配置下发

类型要求
虚拟机CPUx86-64
内存最低128MB,推荐256MB
硬盘不需要
网卡1
光驱1

注意:如果节点数量很多或者连接数很多或者你的配置文件比较复杂的话,建议适当增加内存和CPU核心数

方式一:使用docker内嵌配置

你可以使用Docker一键定制ISO镜像,其中包括为ISO配置静态IP、替换Clash/mihomo核心、内嵌ppgw.ini等功能,详情见使用Docker定制ISO镜像一节

方式二:使用DHCP下发配置

PaoPao GateWay是一个iso镜像,为虚拟机运行优化设计,你只需要添加一个网络接口和一个虚拟光驱塞iso即可。虚拟机启动之后,会自动使用DHCP初始化eth0接口,因此你需要在路由器里为这个虚拟机绑定静态的IP地址,如果你在路由器里面找不到哪个是PaoPao GateWay的话,他的主机名是PaoPaoGW,虚拟机也会滚动显示获取到的eth0接口的IP地址和MAC信息。
为了实现配置和虚拟机分离,达到类似docker的效果,PaoPaoGateWay采用了配置下发的方式进行配置,你需要把配置文件放在对应位置,假设系统启动后通过DHCP获取到以下信息:

1
2
3
4
IP: 10.10.10.3
DNS1: 10.10.10.8
DNS2: 10.10.10.9
网关: 10.10.10.1

系统会依次尝试以下方式获取配置,并记忆最后一次成功的连接,下次循环优先使用:

  • 1 从http://paopao.dns:7889/ppgw.ini下载配置。使用此方式,你需要配合你的DNS服务,把paopao.dns这个域名解析到你的静态文件服务IP,服务端口是7889。如果配合PaoPaoDNS使用,你只需要设置SERVER_IP参数和设置HTTP_FILE=yes,映射7889端口即可,你可以直接把配置文件ppgw.ini放在PaoPaoDNS/data目录。
  • 2 从http://10.10.10.1:7889/ppgw.ini下载配置。使用此方式,你可以在主路由上映射7889端口到你的静态文件服务。
  • 3 从http://10.10.10.8:7889/ppgw.ini下载配置。如果你直接使用PaoPaoDNS作为你的DNS服务IP,那么你只需要设置PaoPaoDNS的HTTP_FILE=yes,映射7889端口即可。
  • 4 从http://10.10.10.9:7889/ppgw.ini下载配置。同上。

系统会不停尝试直到成功获取到配置文件为止,并在后续定期获取新配置(默认值是30秒),当配置的值发生变化的时候将会重新加载网关。你也可以手动进入虚拟机本地终端输入reload回车强制马上重载所有配置。

ppgw.ini配置说明

ppgw.ini的所有配置项如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#paopao-gateway

# mode=socks5|ovpn|yaml|suburl|free
# default: free
mode=free

# Set fakeip's CIDR here
# default: fake_cidr=7.0.0.0/8
fake_cidr=7.0.0.0/8

# Set your trusted DNS here
# default: dns_ip=1.0.0.1
dns_ip=10.10.10.8
# default: dns_port=53
# If used with PaoPaoDNS, you can set the 5304 port
dns_port=5304

# Clash's web dashboard
clash_web_port="80"
clash_web_password="clashpass"

# default:openport=no
# socks+http mixed 1080
openport=no

# default: udp_enable=no
udp_enable=no

# default:30
sleeptime=30

# socks5 mode settting
# default: socks5_ip=gatewayIP
socks5_ip="10.10.10.5"
# default: socks5_port="7890"
socks5_port="7890"

# ovpn mode settting
# The ovpn file in the same directory as the ppgw.ini.
# default: ovpnfile=custom.ovpn
ovpnfile="custom.ovpn"
ovpn_username=""
ovpn_password=""

# yaml mode settting
# The yaml file in the same directory as the ppgw.ini.
# default: yamlfile=custom.yaml
yamlfile="custom.yaml"

# suburl mode settting
suburl="https://..."
subtime=1d

# fast_node=check/yes/no
fast_node=yes
test_node_url="https://www.youtube.com/generate_204"
ext_node="Traffic|Expire| GB|Days|Date"
cpudelay="3000"

# dns burn setting
# depend on fast_node=yes & mode=suburl/yaml
dns_burn=no
# If used with PaoPaoDNS, you can set the PaoPaoDNS:53
ex_dns="223.5.5.5:53"

# Network traffic records
net_rec=no
max_rec=5000

下面逐项来解释选项的用法:

    1. 配置文件第一行必须以#paopao-gateway开头。配置格式为选项="值"
    1. mode是网关的运行模式,也就是当静态路由的流量到达网关之后,怎么出去。一共有五种模式可以选择(socks5,ovpn,yaml,suburl,free):
    • socks5:配置为socks5代理出站,这是最简单也是最通用的配置方式,如果其他模式不能满足你的需求,你可以把能满足你需求的服务程序开一个socks5代理给网关使用。
    • ovpn:配置为openvpn出站,适用于一些专线场景。
    • yaml:自定义clash的yaml配置文件出站。你可以自己写一个clash格式的yaml配置文件,clash支持多种出站协议,具体写法请看官方wiki。只写proxies:字段即可,也可以包含rules:字段。如果只有proxies:字段,在网关启动后你可以在web端选择节点;如果有rules:字段,则会按照你写的规则来执行。注意,网关使用开源的官方clash核心,如果你的rules:包含闭源Premium core的规则,则无法加载并报错,导致clash无法启动。使用开源的Clash核心是因为功能已经可以满足需求,网关本身也不适合加载过于复杂的规则,Premium core的功能会降低稳定性、增加崩溃的几率,比如RULE-SET功能在启动的时候下载远程url文件失败的话可能会导致clash无法正常启动,而clash无法启动的时候文件可能不能被正常下载,进入了死循环。此外,由于网关也不适用GEOIP规则,请勿写入任何GEOIP规则,因为GEOIP规则依赖GEOIP库更新,此外碰到GEOIP规则会触发DNS解析,降低了处理效率。如果有更复杂的规则需求,建议单独跑一个docker配置你所需的规则,开放socks5端口,让网关使用socks5模式,或者参考使用docker定制ISO镜像一节更换定制的clash核心。选择该模式,你需要把配置文件放在和ppgw.ini同一目录,系统将会在指定的sleeptime内循环检测配置值的变化并重载网关。
    • suburl:自定义远程订阅clash配置,不过是从给定的url下载配置。注意事项与yaml模式基本一样,不能使用包含开源clash功能之外的规则的订阅,或者参考使用docker定制ISO镜像一节更换定制的clash核心。推荐nodelist类型订阅,或者使用subconverter等程序转换订阅。
    • free: 自由出站模式,选择此模式的场景是,假定你在IP层面把虚拟机IP出口走了专线,流量直接出站处理。
    1. fake_cidr是指定你的FakeIP地址池范围。比如默认值是7.0.0.0/8,你需要在主路由上设置一条静态路由7.0.0.0/8到PaoPaoGateWay。你应该使用一些看起来是公网但实际上不是(或者不会被实际使用)的地址段,比如实验用地址段、DoD网络地址段。如果你有其他真实的公网IP段需要被网关处理,直接写对应的静态路由即可(比如某些聊天软件走的是IP直连而不是域名),除了指定的fake_cidr段会被建立域名映射,其他公网IP地址段都会被网关按普通流量处理分流。【ROS用户看这里】 【爱快用户看这里】 除了静态路由,或者你可以顺便添加DHCP option 121优化
    1. dns_ipdns_port用于设置可信任的DNS服务器,“可信任”意味着真实无污染的原始解析结果。如果你配合PaoPaoDNS使用,可以把dns_ip设置成PaoPaoDNS的IP,把dns_port设置成映射的5304端口,详情可参见PaoPaoDNS的可映射端口说明。该DNS服务在代理出站的时候实际上不会被用到,流量还是会以域名发送到远端,更多的是用于其他模式的节点解析、规则匹配。
    1. clash_web_portclash_web_password是clash web仪表板的设置,分别设置web的端口和访问密码,默认值为80clashpass。网页登录地址为http://网关IP:端口/ui。你可以在web端查看流量和日志,以及选择节点等。不要忘了登录地址是/ui
    1. openport设置是否向局域网开启一个1080端口的socks5+http代理,默认值为no,需要开启可以设置为yes
    1. udp_enable: 是否允许UDP流量通过网关,默认值为no,设置为no则禁止UDP流量进入网关。(此选项只影响路由,不影响openport选项)注意:如果你的节点不支持UDP或者不稳定不建议开启,开启UDP将会导致QUIC失败导致网站有时候上不去的现象。
    1. sleeptime是拉取配置检测更新的时间间隔,默认值是30,单位是秒。sleeptime在第一次成功获取到配置后生效,如果配置的值发生变化,将会重载网关配置。如果设置sleeptime低于30会被赋值为30。
    1. socks5_ipsocks5_port: socks5运行模式的专用设置,指定socks5的服务器IP和端口。
    1. ovpnfileovpn_usernameovpn_password: ovpn运行模式的专用设置,ovpnfile指定ovpn的文件名,系统将会从ppgw.ini的同一目录下载该文件。如果你的ovpn需要用户名和密码认证,可以指定ovpn_usernameovpn_password
    1. yamlfile: yaml运行模式的专用设置,指定yaml的文件名,系统将会从ppgw.ini的同一目录下载该文件,并使用sleeptime的值循环刷新检测配置文件变化,值发生变化则重载网关。
    1. suburlsubtime: suburl运行模式的专用配置,suburl指定订阅的地址(记得加英文半角双引号),而subtime则指定刷新订阅的时间间隔,单位可以是m(分钟),h(小时)或者d(天),默认值为1d。与yaml模式不同,suburl模式使用单独的刷新间隔而不是sleeptime,因为订阅一般都是动态生成,每次刷新都不一样,会导致刷新网关必定重载。需要注意的是subtime仅配置订阅的时间间隔,检测配置变化仍然是由sleeptime进行。注意如果开了fast_node功能,检测不通的时候会主动拉新订阅。
    1. fast_nodetest_node_urlext_node:测试最快的节点并自动选择该节点的功能。fast_node默认值为no。如果fast_node值为空,并且yaml模式或者suburl的配置文件中不包含rules,则会被设置为yes。test_node_url是用于测速的网址,将会使用clash的api测试延迟,默认值是https://www.youtube.com/generate_204ext_node是排除测速的节点,多个关键字用竖线隔开,默认值是ext_node="Traffic|Expire| GB|Days|Date"fast_node的行为如下:
    • fast_node=yes或者fast_node=check,系统将会在sleeptime间隔检测test_node_url是否可达,若可达,则不进行任何操作;若不可达,则立即停止clash并秒重载网关配置,如果是suburl模式,还会在重载前拉新订阅配置。
    • 仅当fast_node=yes,在网关重载后对所有节点(不包括ext_node)进行测速,并自动选择延迟最低的节点。fast_node=yes会忽略加载rules:规则并开启global模式
    • fast_node=yes仅会在test_node_url不可达的时候主动切换节点,不会影响你在Web手动选择节点使用。因此强烈建议习惯单节点使用的开启该项功能。或者可以使用fast_node=check来实现当test_node_url不可达的时候主动拉新订阅而不主动选择节点。
    • 注意,设置为check不会测速,设置为yes测速失败到阈值会杀死进程并终止应用网关并重载,而check不会杀死进程,仅重载所有配置并关闭所有现有的旧连接。
    • 如果你的所有的节点都延迟过高不稳定,建议设置为no避免增加意外的断流的情况,同时你需要手动切换节点。
    • cpudelay选项是设定如果CPU处理延迟大于指定值则放弃本次测速。该选项是防止低性能设备负载过高导致死机,默认值为3000。设置更小的值可能会放弃更多测速,设置更高的值可能会让低性能设备负载过高。
    1. dns_burn选项和ex_dns选项:dns_burn功能可以把所有节点的域名解析成所有可能的IP结果,把server字段替换为解析的IP结果,以节点名-IP的名称作为新节点加入,临时硬编码到配置文件中。上面设置的dns_ipdns_port,和ex_dns选项会被用于dns_burn功能,ex_dns选项用于指定额外的DNS用于解析节点,建议设置为境内DNS以获得不同的结果,如果为空默认值为223.5.5.5:53,如果配合PaoPaoDNS使用,则可以设置为PaoPaoDNSIP:53。你也可以设置多个ex_dns,格式为逗号分隔,比如ex_dns=223.5.5.5:53,119.29.29.29:53dns_burn功能默认为no,适用于suburl模式和yaml模式,依赖于fast_node=yes。该功能的优点和应用场景如下:
    • 1、节点使用了分区域解析,只有使用了境内DNS才能连接,参见issuedns_burn功能可以额外对节点进行解析。
    • 2、节点DNS解析存在多个解析入口,dns_burn功能会把所有可能的入口都作为新节点加入到配置文件中,在测速的时候就可以选择到速度最好的入口,而不是随机选择。
    • 3、节点的所有可能的解析结果都会被临时硬编码到配置文件中,除非所有节点都测速失败或者订阅更新,该配置文件不会变化,可以减少节点的DNS查询,使用IP直连,并有效避免节点临时出现可能的DNS污染或者DNS故障的情况,比如节点域名忘记续费导致解析失败。

使用docker定制ISO镜像:ppwgiso

pull size

    1. net_rec选项:网络流量记录功能,可以记录网关连接了哪些域名、上传下载消耗了多少流量、客户端IP,并默认按照消耗流量的大小排序,该功能可以根据实际情况方便地调整分析自己的域名规则列表。设置为yes开启该功能后可以在web界面点击[记录],选择下载表格或者在线加载。其中max_rec选项指定最大记录数,默认为5000,当记录的内容超过max_rec的2倍后,仅保留前max_rec项记录。注意事项:
    • 1、重启或者修改ppgw的密码、Web端口、max_rec选项、关了再开net_rec选项会导致数据清空。
    • 2、如果流量太小连接持续时间过短,有可能在记录之前连接已经关闭,流量会显示为0B。
    • 3、客户端IP记录的是最后一次连接该域名的客户端IP。
    • 4、理论上会略微增加资源占用,取决于你的并发连接数量以及max_rec,可适当增加运行资源。

默认的ISO是通过DHCP下发配置的,这个通常能满足大部分场景需求,然而一些企业内部的服务器网段也许只能设置静态IP,或者通过公开的http端口拉取配置觉得不够安全,或者自带的标准开源clash核心支持的功能和协议不够多等等,现在你可以通过docker镜像sliamb/ppgwiso,来定制你的专属ISO镜像。

使用方法

现在,你可以准备一个文件夹,根据需求,选择性放入以下文件,或者不放:

配置网络:network.ini

如果你要配置静态IP等信息,可以新建一个network.ini如下:

1
2
3
4
5
ip=10.10.10.3
mask=255.255.255.0
gw=10.10.10.1
dns1=10.10.10.8
dns2=10.10.10.9

*虚拟机网卡分配的dns仅用于拉取ppgw.ini无其他作用。只有一个dns就只填dns1。

指定ppgw.ini的下载地址:ppgwurl.ini

如果你要指定ppgw.ini的下载地址而不是按上面的规则来寻找,比如你弄了一个带鉴权的http服务器提高安全性,防止配置泄露,你可以新建一个ppgwurl.ini如下:

1
ppgwurl="http://...."

内嵌ppgw.ini

如果你想固定ppgw.ini的配置而不是通过http远程拉取,你可以直接在当前目录放入ppgw.ini
注意:内嵌ppgw.ini优先级比ppgwurl.ini高,同时内嵌ppgwurl.ini不生效。

内嵌custom.ovpn

你可以把节点信息custom.ovpn放入当前目录,当mode=ovpn的时候将会强制使用该文件。
注意:你仍然需要在ppgw.ini中指定mode=ovpn才会使用到该文件。

内嵌custom.yaml

你可以把节点信息custom.yaml放入当前目录,当mode=yaml的时候将会强制使用该文件。
注意:你仍然需要在ppgw.ini中指定mode=yaml才会使用到该文件。

替换clash/mihomo核心

由于第三方稳定性未知,不建议替换核心,除非内置核心不能满足需求 你可以把你的amd64的clash/mihomo二进制文件重命名为clash放到当前目录即可。通过替换clash核心,你可以支持更多的协议和规则功能,比如替换为mihomo
注意:使用Wireguard出站建议设置remote-dns-resolve: false

替换Country.mmdb

默认的GEOIP数据Country.mmdb仅包含CNPRIVATE地址,你可以在当前目录放入你自己的Country.mmdb。
默认的数据来源:https://github.com/kkkgo/Country-only-cn-private.mmdb

最后一步:一键生成ISO

你只需要在放好文件的当前目录执行以下命令即可一键生成镜像。
确保在每次进行操作之前,使用docker pull拉取最新的镜像(不同于release版本,docker版本会每天同步最新所有上游代码)。
在Linux上或者Windows上操作均可(在Linux路径错误的话,.:/data可以换成$(pwd):/data):

1
2
docker pull sliamb/ppgwiso
docker run --rm -v .:/data sliamb/ppgwiso

如果你的网络环境访问Dokcer镜像有困难,可以尝试使用上海交大的镜像。

只需等待十几秒,你就可以在当前目录看到你定制的paopao-gateway-x86-64-custom-[hash].iso

可选:物理网卡直通

镜像因为是虚拟机专用默认仅包含虚拟网卡驱动,如果有物理网卡直通需求,你可以把定制的docker镜像切换成fullmod版本,增加驱动(还包含qemu-ga/open-vm-tools):

1
2
docker pull sliamb/ppgwiso:fullmod
docker run --rm -v .:/data sliamb/ppgwiso:fullmod

注:fullmod附带了所有可能支持的网卡驱动和相关模块,生成的镜像会大20M左右,可适当增加运行内存。

可选:生成前置嗅探的ISO

生成前置嗅探的ISO,流量到达网关后先尝试嗅探出域名再使用FAKEIP,更适合企业环境使用:

优点:

  • 即使FAKE DNS缓存出错也能正确连接常见协议(http/tls),可以避免因网站使用了QUIC不稳定导致网页断流;
  • 重启虚拟机也不会因FAKE IP映射不正确而引起无法访问的短暂故障、对DNS TTL处理不正常的客户端兼容更好;

缺点:

  • Web面板看不到请求的IP来源
  • 需要占用更多内存

使用该功能,只需要在生成的时候加入环境变量参数SNIFF=yes即可:

1
2
docker pull sliamb/ppgwiso
docker run --rm -e SNIFF=yes -v .:/data sliamb/ppgwiso

此外,有时候节点远程解析的DNS存在问题或者其他自定义原因,而又没有节点服务器的控制权,出于避免DNS请求泄漏到节点或者其他场景,如果你想在嗅探的基础上,使用本地可信任DNS(ppgw.ini中所配置的)来解析所有请求来代替远程解析,可以使用SNIFF=dns

1
2
docker pull sliamb/ppgwiso
docker run --rm -e SNIFF=dns -v .:/data sliamb/ppgwiso

注:一般情况下,远程解析可以获得更快的连接速度,如无特殊自定义需求不建议定制SNIFF=dns

与DNS服务器配合完成分流

PaoPao GateWay启动后会监听53端口作为FAKEIP的DNS服务器,所有域名的查询到达的话这里都会解析成fake_cidr内的IP。当你在主路由添加fake_cidr段到PaoPao GateWay的静态路由后,你只需要把需要走网关的域名解析转发到PaoPao GateWay的53端口即可,能实现这个功能的DNS软件很多,比如有些系统自带的dnsmasq就可以指定某个域名使用某个DNS服务器。
配合PaoPaoDNSCUSTOM_FORWARD功能就可以完成简单精巧的分流,以下是一个简单的非CN IP的域名转发到PaoPao GateWay的docker compose配置:
假设PaoPaoDNS容器IP是10.10.10.8。PaoPao GateWay的IP是10.10.10.3,还开启了openport功能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: "3"

services:
  paopaodns:
    image: sliamb/paopaodns:latest
    container_name: PaoPaoDNS
    restart: always
    volumes:
      - /home/paopaodns:/data
    environment:
      - TZ=Asia/Shanghai
      - UPDATE=weekly
      - DNS_SERVERNAME=PaoPaoDNS,blog.03k.org
      - DNSPORT=53
      - CNAUTO=yes
      - CNFALL=yes
      - CN_TRACKER=yes
      - USE_HOSTS=no
      - IPV6=no
      - SOCKS5=10.10.10.3:1080
      - SERVER_IP=10.10.10.8
      - CUSTOM_FORWARD=10.10.10.3:53
      - AUTO_FORWARD=yes
      - AUTO_FORWARD_CHECK=yes
      - HTTP_FILE=yes
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "5304:5304/udp"
      - "5304:5304/tcp"
      - "7889:7889/tcp"

需要注意的是,一小部分应用不走域名而是IP直连,比如某些聊天软件应用,你只需要网上搜索一下对应的IP段,添加少量对应的的静态路由即可。
如果配合PaoPaoDNS使用,强烈建议开启PaoPaoDNSUSE_MARK_DATA功能,提升分流精准度。
注:抓取跳过域名参考

更多教程

由于每个人的网络拓扑平台和路由系统不一样,可能没有通用的详细教程,你可以在论坛查看其他人的配置分享,如果你成功部署了网关,欢迎在论坛分享你的相关过程或者解决方案给其他人参考。

构建说明

PaoPao GateWayiso镜像由Github Actions自动构建仓库代码构建推送,你可以在Actions查看构建日志并对比下载的镜像sha256值。

附录

PaoPaoDNS: https://github.com/kkkgo/PaoPaoDNS
mihomo releases: https://github.com/MetaCubeX/mihomo/releases
mihomo config: https://github.com/MetaCubeX/mihomo/blob/Alpha/docs/config.yaml
mihomo wiki: https://wiki.metacubex.one/config/proxies/ Yacd: https://github.com/haishanh/yacd