深入浅出【迷雾通】之第一篇
正文开始:https://pincong.rocks/article/10365
速度很快、特别难封:迷雾通的翻墙协议niaucchi4是我自己根据ScrambleSuit等在学术界认可的协议写的,基于UDP并在保证性能的前提下有高强度的混淆和加密。niaucchi4即使通过机械学习也难以辨别(初步用各种机械学习算法做过实测)。迷雾通运营两年多了,官网也早被封了(说明不是没有被盯上),但协议从未被封。根据两年内几千个用户的反馈,迷雾通稳定性和速度都非常好,包括在十一等敏感期间。
我们不是来找茬,只是一起审视代码!
niaucchi4协议,我没有细读,但是大概看过来是跑在KCP协议上,KCP底层用的UDP。
因为KCP的协议有24字节的报文头,所以GFW可以很容易识别出KCP协议,并封杀。
我给作者讲一些事情,v2ray也曾经有人用过KCP和mKCP,都失败了。。。所以KCP这条路是走不通的。。。但是我相信niaucchi4协议仍然是很出色的~有空我去读读!
可能作者也发现KCP这条路走不通,所以改了下面的代码
func dialBridge(host string, cookie []byte) (net.Conn, error) {
// return niaucchi4.DialKCP(host, cookie)
conn, err := net.DialTimeout("tcp", host, time.Second*5)
if err != nil {
return nil, err
}
conn.(*net.TCPConn).SetKeepAlive(false)
return cshirt2.Client(cookie, conn)
}
把
niaucchi4.DialKCP(host, cookie)
给注释掉了,改成了tcp连接。。。
第一部分总结:因为用了KCP协议,通过牺牲带宽来提升网速30%,所以很快。但是KCP的特征太明显,所以直接被识别,无条件封杀了。。。
「傻瓜式」软件前所未有的私密性:基本上任何付费梯子都有一个问题,就是注册和支付很容易暴露自己的隐私。即使你用假电话注册,用门罗币付款,如果服务商是黑心的(或者被共匪控制),在同一个用户名下的活动时间久了也很可能足够推断出谁是谁。自己搭梯子也很难避免这个问题(VPS提供商同样有可能有问题)。与其相反,迷雾通使用一个基于blind signature的加密学概念来进行用户验证。简而言之,就是用户可以向翻墙代理证明自己是注册过并付费过的用户,而不透露自己是哪一个用户。这样,注册支付这种「敏感」信息就和浏览活动从数学上隔离了,尽管用户体验上和付费VPN基本一样,实际隐私可以和自由门之类的不记名软件媲美。(当然要完全私密的话强烈建议开双重代理+Tor)
这里是作者亲自告诉我代码在哪里,省了我很多时间,谢谢作者!
https://github.com/geph-official/next.geph.io/blob/master/src/billing/PlanPicker.jsx
https://github.com/geph-official/next.geph.io/blob/master/racket/billing.rkt
先看PlanPicker,划重点,通过Stripe付费的!所以我们代码里搜索stripe
const STRIPEKEY = "pk_live_Wk781YzANKGuLBl2NzFkRu5n00YdYjObFY";
作者stripe账号的公钥,类似TLS里的serverhello,证明你付费对象的身份
然后我们选择付费plan,付款成功以后会调用webhook函数,返回
customerEmail: 你的迷雾通用户名@receipts.geph.io
接下来看/racket/billing.rkt,我不懂lisp,不好意思!!!
我们来搜关键字吧!
首先,我们搜索webhook,看看webhook函数在干嘛。
这里,我看到了Erlang语言的模式匹配,现在看checkout.session.completed这个case
register-subscription // 这里说下 前缀、中缀、后缀表达式(逆波兰表达式) 发现很多程序员数据结构没学。。。光学设计模式了?
如果习惯了前缀表达式,估计代码就看懂了。。。我们就不细讲了。。。
接下来,我们搜索第二个关键字,query-,记住带减号!
看不懂lisp,但是可以看懂sql,看着sql,把大概搞懂了~
subscriptions,stripeSubs,users,invoices 这几张表是干嘛的,了解下就可以了。
第二部分总结:作者把银行卡信息和用户账号隔离,没法通过迷雾通账号,知道对应的银行卡号。
第三部分总结:因为第一部分的结论,kcp协议走不通,作者使用了tcp协议,所以客户端和网桥的交互代码就基本废了重写。。。
现在回过来说下geph-binder,就是一个 端口号9080的http服务器。。。甚至不是https?
客户端,通过TLS连接到CDN,因为用了前置域名,所以GFW无法区分内容是什么。
CDN转发请求给binder,我们只要看 cmd\geph-binder\main.go里的路由就好了
重点关注add-bridge,get-bridges, 【warpfronts 新加的,我还没看】
读到这里的时候,我挺好奇的,如果GFW,给binder发了add-bridge,然后用户调用了
get-bridges得到了GFW的钓鱼网桥,不就玩大了么?
然后,我发现有鉴权。所以鉴权部分,我去研究下。。。还没看第二篇给你们补上!
继续,我们说下get-bridges,客户端代码,调用 getBridges 函数的时候,会发送get-bridges请求给binder
这个时候,binder返回自己存储的4个bridges~
客户端,得到应答以后,就通过调用 dialBridge 去连接网桥【tcp协议,kcp协议已经废掉了】
第四部分总结:网桥代码在境外VPS部署,启动以后,通过给binder发送add bridges请求,把自己的信息发给binder,binder鉴权以后,存储到cache。以后客户端可以通过CDN访问binder得到网桥信息。
最后客户端通过tcp协议连接到网桥~