查询dns泄露:https://ipleak.net
透明代理文档:https://xtls.github.io/document/level-2
视频教程
视频地址:https://youtu.be/50iVDmqzDW8
上节我们已经讲过了clash
在系统代理
和透明代理下的执行流程
由于redir-host的模式存在诸多问题
原版clash已经将该功能移除了
只剩下fake-ip模式
我们也说过fake-ip虽然能降低延迟
但是这种侵入式的解决方案并不完美
在某些使用场景下会出现问题
难道就没有更好的解决方案了吗
这就是我们本期的主要内容
通过v2ray的流量嗅探以及DNS代理
解决DNS泄漏和DNS污染的问题
并且没有fake-ip存在的那些问题
v2ray也有fake-ip功能
叫做fakeDNS
由于上期已经介绍过了clash的fake-ip
关于v2ray的fake DNS就不再讨论了
原理是一样的
另外
视频中讲的v2ray并不仅仅指代v2ray
像是xray
sing-box以及clash.Meta
都能进行类似的处理
只是配置的方式不太一样
所以把视频中的v2ray换成其他内核
也是同样的理解方式
先来回顾上节的内容
创建一个最常见的家庭网络环境
你在运营商拉了一条宽带
他会给你分配一个光猫
一般来讲
你会单独再购买一台路由器连接光猫
路由器通过PPPOE拨号
获取运营商分配的公网IP
同时运营商作为局域网的网关
会有自己的内网ip地址
假设为192.168.0.1
家里的所有网络设备都
会连接到这台路由器
路由器通过DHCP
为每一台网络设备分配一个内网IP
以及默认网关
DNS等信息
一般情况下
默认网关和DNS服务器都是路由器
这是最常见的家庭网络拓扑
先以第一节介绍过的系统代理为例
当我们在电脑上运行v2rayN时
其实它是调用了v2ray
或者xray的内核
并且加载了同目录下的config.json配置文件
配置文件里主要用到了3个功能模块
inbounDNS outbounDNS routting
分别为入站 出站 路由
我这里主要给大家讲讲
数据包是怎么处理的
不会给大家讲每一条命令的意思
完整的说明请自行查阅官方文档
首先inbounDNS通过socks协议
监听了本机的10808端口
此时浏览器访问谷歌
由于设置了系统代理
访问谷歌的请求会发送给10808端口
v2ray从入站
也就是inbounDNS的10808端口收到数据后
得知浏览器要访问谷歌
他要判断这个数据包该怎么走
于是进入路由模块
路由你可以理解为分流
里面通过一系列的规则
来确定数据包该走哪条路
第一条指令确定了整个路由模块的
域名解析策略为IPIfNonMatch
先记住这个 很关键
下面设置了3条路由规则
会从上到下一条条进行匹配
首先
根据geosite判断域名是不是广告域名
geosite是一个数据库
里面包含了常见的域名分类
如果是广告域名
则将数据包发给tag为block的出站
也就是outbounDNS里tag为block的这一条
tag只是一个标识
用于定位不同的出站连接
标识可以随便填写 但是不能重复
每条出站都要指定一个协议
表示用什么协议
来处理转发过来的数据
block用到的协议是blackhole
意为黑洞
也就是你发过来的数据扔到黑洞里去
相当于直接丢弃数据包
达到广告屏蔽的效果
很显然Google并不是一个广告域名
无法匹配这条规则
于是来到下一条
匹配国内的ip地址
geoip是一个IP数据库
里面包含了常见的IP归属地分类
如果匹配
则将数据包发给tag为direct的出站
也就是这条
这条的出站协议为freedom
相当于直连
而我们用来进行匹配的是google.com
这个域名
很显然
ip地址和域名是无法进行对比的
此时
就需要通过路由模块配置的域名解析策略
来决定该怎么处理
有3个选项AsIs IPIfNonMatch IPOnDomand
如果使用的是IPOnDomand
则会发起DNS请求获取谷歌的ip地址
再和这条基于IP的规则进行对比
由于我们的v2ray并没有配置DNS模块
所以会使用系统的本地DNS进行解析
v2ray会构建一条查询谷歌
域名的DNS请求
发送给电脑配置的本地DNS服器
也就是路由器
路由器再转发给上游DNS
由于DNS是明文的
此时就产生了DNS泄漏
后面的DNS解析步骤就是之前
泄露那期讲过的内容了
大概率你会收到一条被污染的DNS响应
假设谷歌的真实IP是4.4.4.4
但是你收到的谷歌IP却是5.5.5.5
这就是DNS污染
v2ray拿到这个被污染的DNS响应
以为谷歌的IP就是5.5.5.5
于是用这个IP和geoip的规则进行匹配
发现归属地不是国内
所以不匹配
于是进入下一条规则
这是域名解析策略为IPOnDomand的行为
而如果使用的是AsIs
或者使用IPIfNonMatch
则不会将域名解析成IP进行对比
相当于上节讲的
clash的IP规则后面加了no-resolve
直接跳过了上面这条基于IP的规则
接下来匹配CN的国内网站
如果是访问国内的网站也走direct直连
很显然谷歌不是
于是继续向下匹配
可是没有规则了
此时又要根据域名解析策略来判断
如果我们用的是AsIs或者IPOnDomand
当没有匹配到任何规则时
直接走第一条出站
也就是tag为proxy的出站
协议为shadowsocks
也就是说数据会使用SS协议进行加密
再发送给节点服务器
而我们现在用的是IPIfNonMatch
这种策略的行为是
当没有匹配到任何规则时
先判断是否
之前有基于IP的匹配规则被跳过了
如果有就将域名解析成IP进行匹配
也就是说IPIfNonMatch
第一次匹配的时候
虽然跳过了基于IP的匹配规则
但是当没有任何匹配的时候
还是会回过头来
再次进行IP规则的匹配
所以需要将谷歌的域名解析成IP
再来匹配一次
此时v2ray发起了获取谷歌IP的DNS
请求DNS的执行流程和刚才讲的
IPOnDomand的一样
大概率会获得一条被污染的IP
用这个IP和geoip的规则进行匹配
发现这个IP的归属地不是国内
结果还是不匹配
当没有匹配任何规则的时候
会走第一条出站
也就是走shadowsocks的代理
这里要注意的是
我们刚才解析
获取到的被污染的谷歌IP
仅仅是用来路由匹配规则的
我们交给shadowsocks代理的内容
还是谷歌的域名
而不是被污染的ip地址
代理收到数据后
会在他的网络环境中进行DNS解析
获取正确的谷歌ip地址
所以即使本地被污染了
也不影响代理正常访问谷歌
但是由于刚才发起了明文的DNS请求
所以使用这个配置的话存在DNS泄露
解决方法就是我在DNS
泄漏那期给大家讲的
使用v2rayN的绕过大陆配置
可以防止DNS泄漏
但是如果使用绕过大陆模式
而域名解析策略却使用IPOnDomand
则还是存在DNS泄漏
大家可以自己测试一下
相信你能理解其中的原因
其实使用黑名单模式
也可以防止关键网站的DNS泄露
比如YouTube Google等等
只是测泄露的时候不太好判断
屏幕上面这两条路由规则分别是v2rayN
自带的绕过大陆模式和黑名单模式
如果你理解了我刚才讲的内容
看懂这几条规则也没什么难度了
总结一下3种域名解析策略的区别
AsIs 如果使用域名
却碰到了基于IP的匹配规则
则直接跳过
IPOnDomand碰到基于IP的规则
就马上发起DNS请求获取域名的IP
进行匹配
IPIfNonMatch
首次匹配的时候
直接跳过基于IP的规则
当没有任何匹配的时候
会发起DNS请求获取域名的IP
回过头再来和刚才跳过的IP
规则进行匹配
最终没有任何匹配的时候
三种策略都是一样 走第一条出站
以上是v2ray
在系统代理模式下的执行流程
不难理解
真正让人难以理解的是和上节讲clash
一样在透明代理模式下的执行流程
如果你是软路由的用户
要想玩明白v2ray
透明代理的知识必不可少
否则只能抄作业
而且也不知道抄的作业
到底适不适合你自己
我之前讲过我还没有用上软路由
有些朋友说要给我众筹
大家可能误会了
我只是不想用并不是说用不起
也不是说软路由不好
只是大家的需求不一样
我平时的使用场景很简单
大多数情况下使用系统代理
就够了 没必要使用软路由
而且网络越复杂越难以控制
比如DNS泄露的问题
使用系统代理就很容易解决
使用透明代理就很麻烦
以后我也可能会为了做教程使用软路由
先来改变一下当前的网络结构
v2ray直接运行在路由器里
路由器会通过iptables的redirect
或者Tproxy功能
将局域网其他设备访问互联网的数据
转发给v2ray的入站
具体iptables是怎么配
我会把相关的链接放在视频下方的描述栏
不过大家一般都用不到
基本上都是直接使用软路由的插件
SSRplus或者passwall会帮我们配置好
电脑上没有运行任何代理工具
跟系统代理主要的区别是
透明代理的配置文件中
添加了DNS模块
和相应的分流配置
此时浏览器访问谷歌
根据DNS泄露篇讲的内容
浏览器首先需要发起DNS请求
获取谷歌的IP
DNS默认使用UDP协议
默认端口为53
目标IP为本地配置的DNS服务器
也就是路由器
即使你的本地DNS不是路由器
而是你自己填的公共DNS服务器
比如114 数据包还是会来到路由器
因为路由器作为局域网的网关
是局域网设备通往互联网的出口
路由器收到数据后
会将DNS请求
劫持到v2ray监听的12345端口
v2ray从tag为all-in的入站
收到数据后
首先来到路由模块
从上到下一条条进行规则
匹配第一条 有好几个条件
需要都满足才能匹配上
首先查看入站tag是不是all-in
也就是数据是不是从all-in进来的
我们的数据确实是从tag为
all-in的入站进来的
所以匹配上了
再看看目标端口是不是53也匹配上了
再看看是不是UDP协议的数据包
很明显也匹配上了
所以这个数据包会交给tag为dns-out
的出站处理
数据将会来到这里
由于这条出站的协议是DNS
所以dns-out拿到数据后
会交给内置的DNS模块
相当于劫持了这条DNS请求
内置的DNS
模块会用自己配置的上游DNS
查询谷歌的ip地址
这里配置了两个DNS服务器
8.8.8.8和114
不像clash的并行查询
v2ray会按顺序从上到下
一个一个查询
也不一定是按顺序
具体要看你的DNS怎么配
比如114配置了geosite
表示国内的网站
优先使用114进行DNS查询
防止国内的网站交给国外的8.8.8.8解析
导致绕路
我这里只是视频演示
v2ray的内置DNS功能非常强大
你可以参考官方文档
将DNS配置的非常细致
由于谷歌并不是国内的网站
所以不会优先使用114解析
会从上到下开始进行DNS查询
首先交给8.8.8.8
构建了一条发给8.8.8.8的查询谷歌IP的DNS请求
这条请求再次来到路由模块进行规则匹配
首先匹配第一条规则
虽然是发给53号端口的UDP协议
但是数据并不是从tag为all-in的入站进来的
而是从内置的DNS模块发过来的
所以不匹配 下一条
匹配114走direct 也不匹配
再匹配下一条规则
如果目标IP是1.1.1.1
或者8.8.8.8
就交给proxy
很显然这条匹配上了
于是数据会来到tag为proxy的出站
所以这条DNS请求将会交给vmess
协议加密处理
由于vmess协议不支持原生UDP
所以这条UDP的DNS请求会被
封装到vmess的TCP协议里进行传输
这种行为叫做UDP over TCP
简称UoT
加密后的vmess数据发送给了节点服务器
节点拿到数据后会进行解密
然后帮我们发起DNS请求
获取到IP后再加密返回给我们
v2ray收到数据后进行解密
得到了谷歌的IP
这个IP是节点服务器返回的正确
无污染IP
4.4.4.4
然后v2ray将这个结果返回给浏览器
浏览器拿到IP之后
才能开始发起访问谷歌的HTTP请求
这是第一种DNS的情况
通过代理进行DNS查询
再来看另一种情况
假设一不小心手滑
把8.8.8.8的分流规则
配置成了直连
也就是查询谷歌IP的DNS请求
将会通过直连的方式交给8.8.8.8
这样就存在DNS泄露并且得到的
谷歌IP大概率是被污染的
假设为5.5.5.5
浏览器拿到这个被污染的IP
发起了访问谷歌的HTTP请求
数据来到路由器
路由器会将数据转发给v2ray的入站
v2ray拿到数据后
如果直接交给路由模块处理
由于被污染的IP没有匹配到任何规则
最终将会走第一个出站
也就是交给vmess处理
数据包里封装的是被污染的IP
就会出现
和上期讲clash的redir-host的模式一样
无法正确的访问谷歌
但是我们的入站开启了sniffing
也就是流量嗅探
这个功能会探测HTTP请求里的域名
通过嗅探
v2ray将获得google.com这个域名
然后用这个域名进行路由匹配
由于没有匹配到任何规则
将会走第一个出站
也就是发给vmess节点
由于我们开启了嗅探
vmess加密的将会是嗅探到的域名
节点拿到的是域名而不是被污染的IP
将会在他的网络环境中
再次发请DNS请求
获取正确的谷歌IP
并帮我们访问谷歌
这就是流量嗅探的作用
即使我们本地没有开启流量嗅探
如果节点服务器开启了流量嗅探
也可以解决被污染的问题
我们发给节点服务器
虽然是被污染的IP
但节点可以嗅探出HTTP里面的域名
重新发起DNS请求获取正确的谷歌IP
这也是clash关闭redir-host的对远程DNS后
使用有些节点代理
被污染的IP也可以正常访问谷歌的原因
不过clash已经弃用了redir-host的模式
而clash.Meta
对原版clash的DNS功能做了大幅增强
同时支持域名嗅探
所以redir-host的模式
在clash.Meta中得以保留
这就是v2ray
在透明代理中
数据的处理流程
要比系统代理复杂的多
对比clash的fake-ip返回一个假的IP
v2ray这种处理方式返回真实的IP
所以不会有fake-ip存在的那些问题
不过也正因为需要返回真实的IP
所以必须要发起DNS请求
为了防止泄漏和污染
可以将DNS请求发送给代理服务器
帮我们查询
但是这样做必然会增加延迟
如果你的节点延迟比较高
会肉眼可见的发现
打开网页的速度变慢了
而fake-ip虽然存在一些问题
但是由于不用发起DNS请求
获取真实的IP
所以不会增加延迟
具体哪种方式适合你
就看各位的需求了