dig TXT 2049bbs.xyz +short
这条命令,可以查到 2049 的esni record
dig TXT 2049bbs.xyz +short
这条命令,可以查到 2049 的esni record
我看了下树洞,全是吵架的,我希望大家可以听听这歌
单曲循环30分钟,我觉得你们心就静了。
我们改变不了别人,只能改变自己的心境。
和人吵架,得不到自己想要的结果。
别理让自己生气的人就好了。
夏天快到了,这歌很好听的~~~
传统过程:
1.火狐向传统DNS请求 Google的IP地址
2.火狐连接得到的IP地址,并给出带SNI的ClientHello
3.正常浏览网页
DoH + ESNI过程
1.火狐通过DoH请求Google的IP地址,并得到TXT record
2.火狐根据TXT record得到公钥,和自己的私钥,计算得到AEAD的密钥
3.火狐用AEAD密钥加密了SNI
4.火狐连接Google的IP地址,并发起TLS握手,其中SNI字段被加密了
5.正常浏览网页
代码流程:
第一步
firefox\netwerk\dns\TRR.cpp 文件的 TRR::SendHTTPRequest() 发起了DoH请求,查询服务器的IP地址
同文件的TRR::On200Response(nsIChannel* aChannel)函数解析了DoH的应答,根据TXT字段,设置了公钥
第二步
firefox\security\nss\lib\ssl\tls13esni.c 文件的 SSLExp_SetESNIKeyPair 把得到的record记录,设置到 ss->esniKeys = keys; 里去,完成了服务器公钥的设置
第三步
firefox\security\nss\lib\ssl\ssl3con.c 文件的 tls13_SetupClientHello 开始组装ClientHello报文,和ESNI相关的这行
rv = tls13_ClientSetupESNI(ss);
firefox\security\nss\lib\ssl\tls13esni.c的tls13_ClientSetupESNI函数 调用 tls13_CreateKeyShare函数,得到
ss->xtnData.esniPrivateKey = keyPair;
ss->xtnData.esniSuite = suite;
ss->xtnData.peerEsniShare = share;
第四步
firefox\security\nss\lib\ssl\ssl3ext.c 文件的 ssl_ConstructExtensions 开始组装clienthello的ext部分
重点是
rv = (*sender->ex_sender)(ss, &ss->xtnData, buf, &append);
其中 ex_sender 函数指针指向 static const ssl3ExtensionHandler clientHelloHandlers[] 的 ex_sender
因为我们关心的是ESNI,所以看 tls13_ServerHandleEsniXtn, 每种ext都有自己的ex_sender函数,挺方便扩展的
第五步
firefox\security\nss\lib\ssl\tls13exthandle.c 文件的tls13_ClientSendEsniXtn函数
aead = tls13_GetAead(ssl_GetBulkCipherDef(suiteDef));
得到了具体的aead算法加密函数,并调用 tls13_ComputeESNIKeys 得到了AEAD的密钥
rv = aead(&keyMat, PR_FALSE /* Encrypt */,
outBuf, &outLen, sizeof(outBuf),
SSL_BUFFER_BASE(&sni),
SSL_BUFFER_LEN(&sni),
SSL_BUFFER_BASE(&aadInput),
SSL_BUFFER_LEN(&aadInput));
最后调用aead函数加密sni,得到esni字符串outBuf,并完成最后的ext组装!
@张怀义 我讲完火狐的ESNI加密流程代码分析了
@v2rayuser 我解释下你的DoH发起的时候,有没有ESNI的问题。
首先DoH的地址,可以是这样的 https://1.1.1.1/dns-query
也是可以 https://dns.couldflare-dns.com/dns-query 这样的
如果是第一种情况,因为是IP地址,自然不存在SNI,也就不可能存在ESNI
如果是第二种情况,因为是域名,所以要先去查这个域名的具体IP,也就是用传统的DNS查找
在about:config配置页,输入 network.trr.bootstrapAddress 这个配置后面填入具体的DNS地址
完整过程就是火狐,先从network.trr.bootstrapAddress 配置的DNS地址,查找具体的IP,再发起TLS连接。这个时候,没有使用DoH,用的是传统的DNS,所以SNI没有加密
火狐使用ESNI,必须配合DoH,使用传统的DNS是无效的
先啰嗦一句,估计这是全网唯一一篇中文讲解ESNI的文章。其他语言有没有,我就不知道了。
先讲流程和细节:
Q1. SNI被加密了,用的是什么加密算法,加密密钥从哪里来?
A1.使用的加密算法是AEAD,具体是哪种AEAD,是协商出来的。密钥是通过PSK协商出来的。
Q2.如果是通过PSK协商,那么服务器的公钥是从哪里来的?
A2.通过DNS得到,具体来说是DNS的 TXT record。
Q3.发起DoH的时候,SNI有没有加密呢?
A3.没有,原因我下面解释
大致流程:
1.火狐通过DNS over HTTPS 发起 请求 服务器的ip地址,还有txt record
2.如果txt record里有公钥信息,说明服务器支持esni,用这个record协商出了aes的密钥
3.用aes密钥加密sni,拼到clienthello的esni字段
4.发送给服务器
@v2rayuser #44 你应该是没有理解DoH和ESNI,所以这么问,我开个新帖子具体解释下
后生可畏。。。
看了这么多?
@小二 #10 可以看看能不能在首页,标题太长截断 后面追加... 这样的方式显示?
不刷屏,所以今天就发这么多了
乌篷点纱灯
沿上青石悄着新纹
喃喃细语时
归来燕子它不等人
五指方扣桨
蓑衣翁正系桥下绳
春雨轻敛去
绣花鞋落起唢吶声
爆竹燃 黯淡月弯弯
锣鼓转 踏醒路长长
烛火晃 斑驳旧时廊旁谁家白墙
照湿谁家女儿脸庞
摇啊摇 十五摇过春分 就是外婆桥
盼啊盼 阿麽阿麽地甜甜叫
吵啊吵 米花糖挂嘴角 总是吃不饱
美啊美 小脚桥上翘啊翘
乌篷点纱灯
沿上青石悄着新纹
喃喃细语时
归来燕子它不等人
五指方扣桨
蓑衣翁正系桥下绳
春雨轻敛去
绣花鞋落起唢吶声
步儿缓 踩得泪潸潸
穿弄堂 望去忆满满
石阶上 转身零落多少银铃啷啷
收起了多少晨与晚
摇啊摇 十五摇过秋分 就是外婆桥
乐啊乐 阿麽阿麽地紧紧抱
跳啊跳 牛郎织女遥遥 总是够不着
眨啊眨 对着它们笑啊笑
摇啊摇 十五摇过春分 就是外婆桥
盼啊盼 阿麽阿麽地甜甜叫
吵啊吵 米花糖挂嘴角 总是吃不饱
美啊美 小脚桥上翘啊翘
我觉得男生可以给女生密码啊,女生也可以给男生啊。
哎,感觉是一个很有争议的话题,还是不趟浑水了
@张怀义 #8 《一点旧一点新》我觉得挺好的。师太的小说少看吧
@小二 #3
左边的标题比较短,右边的标题比较长
导致右边item的高度比左边高,最后的效果就是右边比左边长
限制标题长度,估计可以解决这个问题
@饱读书名 #11
11个硬币里选择2个硬币 C(11,2) = 55 种组合 每次使用天平,有<,=,>三种情况,使用4次,可以得到3^4次方,81种结果
根据信息论得知,通过可以设计一种编码方式,实现用一个3进制的数来表示对应的一个组合
用枚举的方式去找到这个对应关系。 我贴的代码,就是在用枚举的办法,遍历去找这个对应关系。 具体由两种方案编码
方案1
ABC-DEF
BEH-CDJ
DGH-EIJ
AGI-FHJ
方案2
ABC-DEF
DGH-EIJ
AGI-BHJ
CDEHI-ABFGJ @小二 #4
这个是IBM自己研发的编程语言,类似LINGO
execute 这个关键字 ,类似 main函数
subject to 这个表示设定限制条件
不知道你学过线性优化没有
y < 7*x + 3 (1)
y < 8*x + 20 (2)
求y的最大值
subject to 类似 条件1,2
execute 相当于求y的最大值
@饱读书名 #3 对不起,你说的对。原题目是说2枚比其他轻。是我的问题
@Phragmites #40 感情的事情,刚开始大家都觉得忘了,现在想起来,是因为看到了当时留下来的东西,记忆就自己回来了。
只是都是甜蜜的记忆,回忆起来却是苦的。
这歌是真虐!
他:喝了这碗孟婆汤吧。
流萤:喝了我会不记得你了吗
他:是
流萤:那……如果再遇见你……我要怎么记得……那是你?
他:……若你看到萤火虫……或许会想起我。
流萤:我会努力记住的。
流萤:会苦么?
他:你喝的时候,听我说一句话,就不觉得苦了。
流萤:什么话?
他:喝的时候再告诉你。
流萤:哦。
……(仰起头慢饮)……
他:我爱你。
流萤:我这是……在哪里?
龙王:忘川河畔,三生石旁。
流萤:我现在要去哪?
他:河上有船渡魂至彼岸。只要到了对岸,便能投胎转世。
流萤:原来是要坐船么?咦?所以刚才那两个鬼差是骗我的么?
龙王:是的。他们想骗你跳下忘川河。不论你是妖是人是鬼——只要从那跳下去,便会被无妄火打散三魂六魄。再难转生。
流萤:他们两为什么要骗我?心也太坏了吧。
龙王:呵,他们俩不仅心坏,还长得丑。以后如果还见到像他们那么丑的妖怪,不要搭理。也不要相信他们说的任何话,懂么?
流萤:多谢……这位公子好生面熟……我们是不是在哪里见过?
龙王:呵。我就只是个……路人罢了……
鶯哥:容潯,你是不是覺得,殺手都是沒有心的?怎麼可能沒有心呢,我把心放在你那裡,可容潯,你把我的心丟到哪裡去了?丟到……哪裡去了?
十几年前的歌了,估计听过的人都不多了。。。
当时,我还在看8号当铺,估计很多人没看过这个电视剧。。。
结局拍的太差了,小说没看过。。。
睡觉了。。。
@小二 #37
很古老了,当年知道的是老品葱。有一次不知道什么原因,找到了新品葱。
偶尔看看你们写了什么,那时候也没几个人说话,你那个时候叫小二8964,头像是新垣结衣
后来一次上品葱,一只鹿儿说自己借你的尸体发了个帖子。我是没看她发的内容,只是明白了你离开了
我有老年痴呆,很多东西记不清了。。。
我印象里,我注册品葱一个星期后就是管理员了。。。
也许刷声望太快了,被某些人排挤。。
各种人怀疑我的性别,怀疑我的年龄,怀疑我的职业。。。
明明只需要关心我说了什么就好了,老是研究我干嘛
@梅菲斯特 #5 在水楼里说要看《飞鸟不鸣》是你么?还是羊城?
@小二 #33
你退葱以后,我才注册,有印象才神奇。
我怀疑品葱某些人怀疑我是BE4之类的。。。
小说的话,我觉得《爱书的下克上》很好看!
@小二 #31 能不能把上面的大叔都换成lisa。。。
我习惯别人叫我lisa
我在品葱,也是为了推广小说,那些被共产党封杀的小说。。。
爱书的下克上
CLANNAD
寒蝉鸣泣之时
Angel Beats
太多了,我有很多想推荐你看怎么办。。。
@梅菲斯特 #3
好吧。我觉得那些都很好看。。。男生不喜欢看。。。
东京不太热【回应版】
youtu.be/MuUlJGgSw1w@小二 #29
额。。。
你是第一个叫我大叔的。。。
我不是程序员。我在品葱,更多是发些情感小说和音乐。。。
我看的小说动漫电影电视剧,听的音乐,N多东西被共产党封杀了,所以跑到墙外备份这些东西。
所以发现了品葱,在品葱反共,是因为共产党封杀我看的小说之类的。
唱的很好听~加拿大的小姑娘
睡你麻痹起来嗨
一直嗨到大天亮
就算天亮也不怕
反正不回家
睡你麻痹起来嗨
怎么嗨都嗨不完
人生就是这么短
得意须尽欢
睡你麻痹起来嗨
一直嗨到大天亮
夜晚非常的美妙
谁都别想逃
睡你麻痹起来嗨
怎么嗨都嗨不完
小妹妹呀快快来
跟我一起嗨
睡你麻痹起来嗨
一直嗨到大天亮
啤酒炸鸡土豆块
说教靠边排
睡你麻痹起来嗨
怎么嗨都嗨不完
做人就要任性点
世界才有爱
睡你麻痹起来嗨
一直嗨到大天亮
嗨完就不想起床
被子外面凉
睡你麻痹起来嗨
怎么嗨都嗨不完
人生就是这么短
得意须尽欢
我觉得,我发了这么多歌,你们总笑了吧~
我们有11枚硬币,其中2枚硬币重量一样,却和其他9枚不一样。现在需要找出这两枚硬币。 但是,我们只有一个没有刻度的天平。需要4次使用天平就找到这2枚硬币
用编程实现~
作曲 : 封茗囧菌
作詞 : 袖藍
編曲:宇狗與狗
混音:封茗囧菌
昨天還口口聲聲叫著寶貝
用甜言蜜語
一句一句 哄人沉醉
轉眼之間 你
已經品嚐下個口味
擁抱著誰
每個夜晚枕著不同香水
每次遲到的約會
每次都只是誤會
每次都溫柔地 親吻著說給一個機會
別生氣 這位那位 是我的妹妹
拜託滾開閉上嘴
鬼才會相信你說什麼妹妹
嗨咿呀
再也不要隨便掉下眼淚
淚水多昂貴
為你浪費不過可笑可悲
(可是你不配)
嗨咿呀
你和別人曖昧也無所謂
總該學會 拆穿你的虛偽
把假面撕碎
穿上漂亮的高跟鞋
向背後揮手告別
沒有美好的故事
足夠用來紀念回味
(丟進垃圾堆)
嗨咿呀a~ a~ a~
把那些謊言都用冷水煮沸
沸騰蒸發的疲憊
自己也能好好面對
昨天還口口聲聲說我最美
在你的心裡
只有一個我的空位(由你守衛)
轉眼之間 你
已經騰給 其他花蕊(其他花蕊)
面對著誰
燈光照出你的笑容諂媚
每次遲到的約會
每次都只是誤會
每次都溫柔地親吻著說給一個機會
別生氣 這位那位是我的妹妹
ha~ah(拜託滾開閉上嘴)
鬼都不相信你所謂的妹妹
嗨咿呀
再也不要隨便掉下眼淚
淚水多昂貴
為你浪費換來可笑可悲
(可是你不配)
嗨咿呀
你和別人曖昧也無所謂
總該學會 拆穿你的虛偽
把假面撕碎
穿上漂亮的高跟鞋
向背後揮手告別
沒有美好的故事足夠用來紀念回味
(丟進垃圾堆)
嗨咿呀a~ a~ a~
把那些你賜予的盲目愚昧
留給你自己體會
扔掉手中那支玫瑰
题目非常难!!!
我先给答案
using CP;
int nbTrials=4;
range trials=1..nbTrials;
int n=11;
range coins=1..n;
tuple comb // the light ones
{
int x;
int y;
}
{comb} combs={<i,j> | ordered i,j in coins}; // i and j are the bad coins
dvar boolean x[trials][coins][1..2]; // 4 trials n coins right and left side
dvar int y[combs][trials] in -1..1; // result of the weight -1 : less 0 : equal 1 : more
subject to
{
// same number of coins both side
forall(i in trials) sum(j in coins) x[i][j][1]==sum(j in coins) x[i][j][2];
// a coin is either left or right or not there
forall(i in trials) forall(j in coins) x[i][j][1]+x[i][j][2]<=1;
// not empty
forall(i in trials) sum(j in coins) x[i][j][1]!=0;
// results of the balance
forall(c in combs)
forall(i in trials)
y[c][i]
==
sgn(x[i][c.x][1]+x[i][c.y][1]-x[i][c.x][2]-x[i][c.y][2]);
// To be able to find the fraud
forall(ordered c1,c2 in combs) or(i in trials) (y[c1][i]!=y[c2][i]);
}
execute
{
function display(v)
{
return String.fromCharCode(64+v);
}
for(i in trials)
{
for(var j in coins) if (x[i][j][1]==1) write(display(j));
write("-");
for(var j in coins) if (x[i][j][2]==1) write(display(j));
writeln();
}
}
ABC-DEF BEH-CDJ DGH-EIJ AGI-FHJ and ABC-DEF DGH-EIJ AGI-BHJ CDEHI-ABFGJ
我觉得小二发帖的时候,情绪不好
只是希望我的歪楼,可以转变大家的心情,在屏幕前自己笑一笑,忘记不开心的事情
现在大家应该忘了自己不开心的情绪了,收工~
@小二 #12
你绕不开js,那是因为你开发web的缘故。可以试试我上面说的行业。都不需要js的
@electron8964 #13
有个小说《爱书的下克上》,女主角一心想当图书馆里,我是一样的
@Phragmites #27
不是的,我是想起了初恋。。。
等你有一天长大了,结婚了。如果和我一样的情况,保留着初恋的一些东西,几十年后再看到,也会想起过去。只是你们不会有我这么大触动罢了
@electron8964 #6 我只是一个图书管理员而已,不是技术大牛
@小二 #8 我知道啊,但是RoR的设计理念非常先进,我觉得其他语言的web框架都是对RoR的模仿而已
而且我已经说了,自娱自乐推荐RoR,找工作的确是没希望了
我是看着Ruby China起来,看着它没落。。。都去玩Erlang了
Erlang和OCaml我觉得也不错, Erlang在通信行业还是可以找到饭碗的,工资也不低,
OCaml可以去Jane Street看看,类似F#,金融行业,工资不低啊
但这些都不是web开发主力语言。
不同行业,语言不同,隔行如隔山。比如,我看人工智能的时候,会python更多,主流框架tensorflow pytorch keras
比如量子力学 python
统计学 python R语言 SPSS
建筑 matlab maple lingo
金融 F# OCaml
以上内容,我都不会,但是都用过这些编程语言。。。
再来写冷门的~
IBM有一个叫ILOG的编程语言。。。我感觉很牛逼。。。
算了。。。不说了,说太多,把自己是谁都泄露了
瞄了一眼2049的代码。。
代码是golang写的,MVC架构。数据库是youdb,抛弃了ORM,将obj直接序列化存储到key -value的数据库。
好处是不需要mybatis这样的orm框架了,坏处是很多复杂业务,代码写起来就很变态,而且性能很糟。
youdb和leveldb一样,属于文件型数据库,同类是sqlite,但是sqlite是传统数据库,youdb是key-value数据库。
++++++++++++++
话说这代码是真的轻量级啊,MVC分的也算清楚,内部实现也不复杂。
说了这么多废话,就是觉得不喜欢这里的人,回家自己搭一个bbs自娱自乐也挺好的~
我也用discuz搭过一个bbs,可惜被共产党封杀了
对于小白的建议
先去学习Ruby on Rails,等你入门了,基本就可以自己写个BBS了
然后学习下RESTFul 规范,让你学会约束自己的代码【培养CRUD思维方式】
最后,网上搜索下前后端分离,前端可以看看vue,我觉得挺好用的!
写web,万变不离其宗,说到底也就是CRUD+js画界面
前端,html+js+css三板斧而已,MDN上学习,一个下午就搞定了
后端,我建议RoR入门,或者python入门。真的玩进阶版,php已经淘汰了,估计是golang会是将来的趋势,国内目前java为主
如果是找工作,建议java或者golang,如果是自娱自乐,推荐RoR和Python
繼續查看ext_sni_add_clienthello函數
發現CBB_add_bytes(&name, (const uint8_t *)ssl->hostname.get(),這行代碼,會對SNI賦值hostname
也就是說,爲什麽我們通過wireshark抓包,可以明文看到自己訪問什麽網站,就是這行代碼造成的!
GFW通過全網檢查ClientHello的SNI字段,來判斷你在訪問什麽網站!而且因爲是明文,所以GFW的工作很簡單,只要檢查你的TLS握手SNI字段,如果是敏感詞,就RST掉你的tcp連接。你就上不去了。品蔥就是這樣,所以上不去,需要開啓ESNI功能,就沒事了~
代碼修改:
1.增加一個ext,取名叫ESNI,參考SNI的實現,完成相關代碼
2.移植火狐的esni加密代碼到boringssl,完成第一步的esni報文拼接
3.編譯自己的boringssl庫,替換掉chrome自帶的boringssl
4.chrome有自己dll校驗機制,你手動替換有點問題,好像跑不起來,得網上找下教程,學習如何替換chrome的boringssl
別找我要代碼或者已經編譯好的dll !我要是寫好了,早提PR給chrome了~
關於爲什麽不自己寫代碼完成剛才我説的這麽多事情:
我翻墻的條件很糟糕,下載chrome的源碼,經常斷掉!失敗就得重新下載。至今沒有下載到chrome源碼。
另外編譯環境配置非常複雜,我沒有那個功夫去完成這麽費時間的工作。老了啊,想當年自己花了3個星期,搭了Gentoo Linux,現在搭個chrome的編譯環境都覺得浪費時間
言歸正傳!
我們講解Chrome了,chrome的TLS實現叫做BoringSSL,fork自著名的openSSL。
開始講如何boringssl的代碼。
翻開課本,boringssl\ssl\handshake_client.cc這個代碼。開始閲讀ssl_client_handshake
對!ESNI是在客戶端發起握手的時候發送的!所以從握手開始讀起。
找到do_start_connect這個函數!很多人覺得看著這個代碼,很嚇人。別怕,其實關鍵信息就i是ssl_write_client_hello這麽一行罷了。其他的都不重要~
ssl_write_client_hello這個函數,什麽都不做,純粹拼報文而已!二進制級別拼寫,類似給一個struct賦值。
我們就看ssl_add_clienthello_tlsext這個函數!因爲ESNI或者SNI都是放在ext字段。
翻開課本 boringssl\ssl\t1_lib.cc 找到 ssl_add_clienthello_tlsext
for (size_t i = 0; i < kNumExtensions; i++) {
const size_t len_before = CBB_len(&extensions);
if (!kExtensions[i].add_clienthello(hs, &extensions)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
return false;
}
意思是遍歷所有的ext,調用對應ext的add_clienthello函數,拼clienthello報文
// kExtensions contains all the supported extensions.
static const struct tls_extension kExtensions[] = {
{
TLSEXT_TYPE_server_name,
NULL,
ext_sni_add_clienthello,
ext_sni_parse_serverhello,
ext_sni_parse_clienthello,
ext_sni_add_serverhello,
},
{
TLSEXT_TYPE_extended_master_secret,
NULL,
ext_ems_add_clienthello,
ext_ems_parse_serverhello,
ext_ems_parse_clienthello,
ext_ems_add_serverhello,
},
{
TLSEXT_TYPE_renegotiate,
NULL,
ext_ri_add_clienthello,
ext_ri_parse_serverhello,
ext_ri_parse_clienthello,
ext_ri_add_serverhello,
},
{
TLSEXT_TYPE_supported_groups,
NULL,
ext_supported_groups_add_clienthello,
ext_supported_groups_parse_serverhello,
ext_supported_groups_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_ec_point_formats,
NULL,
ext_ec_point_add_clienthello,
ext_ec_point_parse_serverhello,
ext_ec_point_parse_clienthello,
ext_ec_point_add_serverhello,
},
{
TLSEXT_TYPE_session_ticket,
NULL,
ext_ticket_add_clienthello,
ext_ticket_parse_serverhello,
// Ticket extension client parsing is handled in ssl_session.c
ignore_parse_clienthello,
ext_ticket_add_serverhello,
},
{
TLSEXT_TYPE_application_layer_protocol_negotiation,
NULL,
ext_alpn_add_clienthello,
ext_alpn_parse_serverhello,
// ALPN is negotiated late in |ssl_negotiate_alpn|.
ignore_parse_clienthello,
ext_alpn_add_serverhello,
},
{
TLSEXT_TYPE_status_request,
NULL,
ext_ocsp_add_clienthello,
ext_ocsp_parse_serverhello,
ext_ocsp_parse_clienthello,
ext_ocsp_add_serverhello,
},
{
TLSEXT_TYPE_signature_algorithms,
NULL,
ext_sigalgs_add_clienthello,
forbid_parse_serverhello,
ext_sigalgs_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_next_proto_neg,
NULL,
ext_npn_add_clienthello,
ext_npn_parse_serverhello,
ext_npn_parse_clienthello,
ext_npn_add_serverhello,
},
{
TLSEXT_TYPE_certificate_timestamp,
NULL,
ext_sct_add_clienthello,
ext_sct_parse_serverhello,
ext_sct_parse_clienthello,
ext_sct_add_serverhello,
},
{
TLSEXT_TYPE_channel_id,
ext_channel_id_init,
ext_channel_id_add_clienthello,
ext_channel_id_parse_serverhello,
ext_channel_id_parse_clienthello,
ext_channel_id_add_serverhello,
},
{
TLSEXT_TYPE_srtp,
ext_srtp_init,
ext_srtp_add_clienthello,
ext_srtp_parse_serverhello,
ext_srtp_parse_clienthello,
ext_srtp_add_serverhello,
},
{
TLSEXT_TYPE_key_share,
NULL,
ext_key_share_add_clienthello,
forbid_parse_serverhello,
ignore_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_psk_key_exchange_modes,
NULL,
ext_psk_key_exchange_modes_add_clienthello,
forbid_parse_serverhello,
ext_psk_key_exchange_modes_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_early_data,
NULL,
ext_early_data_add_clienthello,
ext_early_data_parse_serverhello,
ext_early_data_parse_clienthello,
ext_early_data_add_serverhello,
},
{
TLSEXT_TYPE_supported_versions,
NULL,
ext_supported_versions_add_clienthello,
forbid_parse_serverhello,
ignore_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_cookie,
NULL,
ext_cookie_add_clienthello,
forbid_parse_serverhello,
ignore_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_quic_transport_parameters,
NULL,
ext_quic_transport_params_add_clienthello,
ext_quic_transport_params_parse_serverhello,
ext_quic_transport_params_parse_clienthello,
ext_quic_transport_params_add_serverhello,
},
{
TLSEXT_TYPE_token_binding,
NULL,
ext_token_binding_add_clienthello,
ext_token_binding_parse_serverhello,
ext_token_binding_parse_clienthello,
ext_token_binding_add_serverhello,
},
{
TLSEXT_TYPE_cert_compression,
NULL,
cert_compression_add_clienthello,
cert_compression_parse_serverhello,
cert_compression_parse_clienthello,
cert_compression_add_serverhello,
},
{
TLSEXT_TYPE_delegated_credential,
NULL,
ext_delegated_credential_add_clienthello,
forbid_parse_serverhello,
ext_delegated_credential_parse_clienthello,
dont_add_serverhello,
},
};
因爲我們要做的是SNI,所以看到了第一個ext,找到了它對應的add_clienthello是ext_sni_add_clienthello
同學們先自己去看下火狐的源碼,理解下火狐的ESNI代碼實現!
我昨天剛下好,300多MB的壓縮包!你們慢慢解壓縮吧。。。
代碼太深了,估計很多人不知道ESNI的代碼實現在哪裏。我解釋下,代碼在
security/nss/lib/ssl/tls13esni.c
函數是SSLExp_EnableESNI和tls13_ClientSetupESNI,整個代碼實現其實不難,當然,前提是你和我一樣無聊看完了openssl的代碼
重點講解,我放到https://2049bbs.xyz/t/3750 這裏了
漏了剛才的代碼,補上
conn, resp, err := dialer.Dial(uri, wsSettings.GetRequestHeader())
return internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
第一行代碼表示調用了開源的github.com/gorilla/websocket庫文件,不在此解讀了,你只要知道,通過這個開源庫,去建立了wss連接就好了,v2ray沒有自己實現wss,只是調用了第三方庫。
第二行代碼,表示去建立了一個tcp連接,無它~
希望我的講解,可以幫助大家少走很多彎路,看代碼知道哪些是v2ray實現的,哪些是第三方庫
遇到問題,需要解決的時候,有一個思路,知道去看什麽代碼文件!
比如爲什麽不像SS一樣需要自己指定加密算法呢?因爲這個是TLS自己協商出來的,而不是我們指定的,我們可以通過刪減剛才的config.CipherSuites來指定加密算法
以及被中間人攻擊怎麽辦?我們可以通過config.Certificates 來設置自己的根證書解決
爲什麽看不到AEAD加密算法實現呢?因爲在github.com/gorilla/websocket庫文件實現的數據AEAD加密
等等問題,可以通過閲讀代碼自己回答。有需要,可以自己提issue。但是我都是自己改代碼,完成自我功能需求的客制化~
有什麽v2ray的問題,可以給我留言。或者在v2ray的GitHub上提issue。