不开DOH也能用ECH
2023-10-22 20:38:30 Author: itlanyan.com(查看原文) 阅读量:52 收藏

安全

本文续上文: ECH隐私保护与SNI白名单,整理自TG网友,点击查看 原消息

结论

我做了三组实验,设置->隐私和安全->使用安全DNS,关闭和设置doh对照,访问下面三个网站:

  1. https://tls-ech.dev/
  2. https://defo.ie/ech-check.php
  3. https://www.cloudflare.com/zh-tw/ssl/encrypted-sni/

多方验证:

  1. firefox不允许在不设置doh的情况下使用ech
  2. chrome允许在不设置doh的情况下使用ech
  3. edge 即便开启doh还是使用不了ech,但是从dns服务器日志里可以看到不光有A和AAAA类型请求,还有https请求类型,说明它已经准备好开启ech了,我期待这个“dns大漏斗”的推送。

所以没有doh使用不了ECH单纯是浏览器行为,ech是ech,doh是doh,他们俩并不是must绑定,而是should绑定

浏览器处理机制

对比下三者的处理机制:

FirefoxChromeEdge dev版本
设置dohclient ech打开client ech打开client ech打开
不设置client ech关闭client ech打开client ech打开

由于ech需要三端同时支持,client 这里我们姑且狭义的定义为浏览器,ech public 草案里叫Client-Facing Server 、provider、 public_name、Outer ClientHello 这里我们狭义的定义为cdn 事实上确实也需要cdn才能真正完成ech的设计意图,server 在草案里它叫 backend server 真正想要访问的网站。

当三端有任何一端不支持时,ech访问就不成立,那么只要确认一个网站的cdn和server 都是支持ech的,访问时没有开启ech,那就必然是client的问题

firefox 强制doh开启才能使用ech,我不能说它就是错,毕竟若使用明文dns返回的https记录里的ech信息,这个ech是有可能被污染的,但我认为firefox应该处理的更智能一些?我给不出建议。https://github.com/net4people/bbs/issues/280 这里有更多的讨论

不论firefox还是chrome,当ech访问方式不成立时(例如访问的网站没开启ech)会退回到暴露sni的普通clienthello连接,两者都没有特定的退回提醒来保证client感知到自己并没有以ech方式访问网站,希望它们可以在浏览器上出一个features来告知client。

而在使用系统代理的情况下,情况更加复杂 篇幅过长,我不放上来了,firefox在开启doh的情况下,doh请求到网页请求全部进入代理,可以说是正真意义上的全连接走代理比较完美的

目前edge稳定版就不说了,它本身就不能开启ech,edge的dns大漏斗,指的是在代理工具下,edge在通过代理发起连接时,依旧会往网卡指定dns或者指定doh发送dns查询,我原本以为edge这样的作法是为了在代理情况下,获得通过代理工具无法获得dns type65记录,结果依旧是not using ECH,令人感叹。

友情提示,在上述测试的时候,每次切换浏览器dns后,最好关闭浏览器再打开,我遇到好几次chrome、edge,切换开关dns后 https://tls-ech.dev/ 强制刷新也不动的情况,甚至 https://defo.ie/ech-check.phphttps://tls-ech.dev 两个结果的情况

另外提一嘴doh实操,firefox、chrome在设置一个错误的doh,比如 abcdefghijklmn.com/dns-query 的情况下,也会马上保存,表现为输入可到达网页出现dns查询不了,我认为这样是比较好的,可以判断这个doh是否被墙,或别的什么问题

edge就很特殊,如果之前不设doh或者设可用doh,在修改为错误的doh后,edge打开可到达网址,依旧顺利连接。刷新设置页面,发现doh设置被还原回上一次可用设置去了,不能即时保存,你连自己的dns查询已经发送出去(可以认为是泄露)都不知道,还容易误判一个被墙的doh以为能用!

明文DNS能否获得ech信息

那我们来看下明文dns下能不能获得ech信息。

输入 dig -t https tls-ech.dev,会得到如下结果:

ech=AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA

PS:gfw应该还没来得及对ech产生污染

将ech=后的结果 base64 转十六进:

0049fe0d00452b00200020015881d41a3e2ef8f2208185dc479245d20624ddd0918a8056f2e26af47e26280008000100010001000340127075626c69632e746c732d6563682e6465760000

再从十六进制转ascii:

IþE+ XÔ >.øò …ÜG’EÒ $ÝБŠ€Vòâjô~&( @ public.tls-ech.dev

只能看到一个域名 public.tls-ech.dev,这个应该是草案里提到的Client-Facing Server,也是outer用的sni,剩下的实在摸索不出来,希望有大佬详解。

nslookup获取

另外说一下 nslookup

192.168.X.X 是设置的dns服务器,当要做这个实验的时候,请确保此dns服务器可以准确获得ech ,以及查询的网站已开启分发ech

当初次使用 nslookup -q=https tls-ech.dev 192.168.X.X,是不可获得ech的,dns查询日志里只能看到A和AAAA类型查询。但是在同命令框下使用过bind命令 dig -t https tls-ech.devnslookup 再查询https又可用了,不知道为什么。

个人建议,查询https还是放弃nslookup吧

doh下怎么获得ech信息

那么我们再来看下doh下怎么获得ech信息。

谷歌家提供了两种api (https://developers.google.com/speed/public-dns/docs/doh),另外也提供网页查询。

第一种 https://dns.google/dns-query

根据文档,GET 请求必须具有包含 Base64Url 编码的 DNS 消息的 ?dns= 查询参数。根据 https://cloud.tencent.com/developer/article/2018599,我们手搓一个dns请求包:

000101000001000000000000
07tls-ech
03dev
0000 65
0001

转十六进制:

000101000001000000000000
07 74 6C 73 2D 65 63 68
03 64 65 76
0000 41
0001

base64:

AAEBAAABAAAAAAAAB3Rscy1lY2gDZGV2AABBAAE

拼接上谷歌家的api :https://dns.google/dns-query?dns=AAEBAAABAAAAAAAAB3Rscy1lY2gDZGV2AABBAAE ,会下载一个文件。找一个十六进制编辑器查看:

00 01 81 80 00 01 00 01 00 00 00 00

07 74 6C 73 2D 65 63 68 03 64 65 76 00 00 41 00 01 C0 0C 00 41 00 01 00 00 00 3C 00 52 00 01 00 00 05 00 4B

00 49 FE 0D 00 45 2B 00 20 00 20 01 58 81 D4 1A 3E 2E F8 F2 20 81 85 DC 47 92 45 D2 06 24 DD D0 91 8A 80 56 F2 E2 6A F4 7E 26 28 00 08 00 01 00 01 00 01 00 03 40 12 70 75 62 6C 69 63 2E 74 6C 73 2D 65 63 68 2E 64 65 76 00 00

部分转ascii看看:

00 01 81 80 00 01 00 01 00 00 00 00 07tls-ech 03 dev 00
00 41 00 01 C0 0C 00 41 00 01 00 00 00 3C 00 52 00 01 00 00 05 00 4B

00 49 FE 0D 00 45 2B 00 20 00 20 01 58 81 D4 1A 3E 2E F8 F2 20 81 85 DC 47 92 45 D2 06 24 DD D0 91 8A 80 56 F2 E2 6A F4 7E 26 28 00 08 00 01 00 01 00 01 00 03 40 12
public.tls-ech.dev
00 00

把第三大段base64:

AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA

与dig查出来的ech吻合

由于 tls-ech.dev 并没有明确告知他家的 OUTER_SNI 会是什么,我们再使用defo.ie尝试:

000101000001000000000000
04 defo
02 ie
0000 65
0001

ascii转 十六进制:

000101000001000000000000
04 64 65 66 6F
02 69 65
0000 41
0001

base64:

AAEBAAABAAAAAAAABGRlZm8CaWUAAEEAAQ

向google查询 https://dns.google/dns-query?dns=AAEBAAABAAAAAAAABGRlZm8CaWUAAEEAAQ
获得文件下载,导入十六进制编辑:

00 01 81 80 00 01 00 01 00 00 00 00

04 64 65 66 6F
02 69 65

00 00 41 00 01 C0 0C 00 41 00 01 00 00 07 08 00 65 00 01 00 00 04 00 04 D5 6C 6C 65 00 05 00 42
00 40 FE 0D 00 3C 88 00 20 00 20 4C DD 98 BD FD D1 CF AE 73 7E DC 97 C7 71 1F 4A FE 04 10 19 4D 71 9C 54 4B A4 B7 D7 74 47 FD 69 00 04 00 01 00 01 00 0D 63 6F 76 65 72 2E 64 65 66 6F 2E 69 65 00 00
00 06 00 10 2A 00 C6 C0 00 00 01 16 00 05 00 0000 00 00 10

63 6F 76 65 72 2E 64 65 66 6F 2E 69 65

转ascii:cover.defo.ie ,与网站提供 SSL_ECH_OUTER_SNI: cover.defo.ie 相符

00 40 FE 0D 00 3C 88 00 20 00 20 4C DD 98 BD FD D1 CF AE 73 7E DC 97 C7 71 1F 4A FE 04 10 19 4D 71 9C 54 4B A4 B7 D7 74 47 FD 69 00 04 00 01 00 01 00 0D 63 6F 76 65 72 2E 64 65 66 6F 2E 69 65 00 00

base64 与 dig 返回的ech结果相同

第二种 https://dns.google/resolve

第一种太难读,我们使用第二种api:https://dns.google/resolve?name=tls-ech.dev&type=HTTPS

name里填域名,type里填记录类型 (https://en.wikipedia.org/wiki/List_of_DNS_record_types),如A、AAAA、HTTPS 也可以写对应的数字 1、28、65。

结果:

{“Status”:0,”TC”:false,”RD”:true,”RA”:true,”AD”:false,”CD”:false,”Question”:[{“name”:”tls-ech.dev.”,”type”:65}],”Answer”:[{“name”:”tls-ech.dev.”,”type”:65,”TTL”:60,”data”:”1 . ech=AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA”}],”Comment”:”Response from * “}

同样还提供name而非dns base64url格式 api接口的还有这几家

https://dns.twnic.tw/dns-query?name=tls-ech.dev&type=HTTPS

https://doh-fi.blahdns.com/dns-query?name=tls-ech.dev&type=HTTPS

https://dns.adguard-dns.com/resolve?name=tls-ech.dev&type=HTTPS

国内的doh也同样可以获得:

https://doh.360.cn/resolve?name=tls-ech.dev&type=HTTPS

不过有一家已经返回给客户端的 HTTPS 资源记录中删除 ECH 配置:

https://web.archive.org/web/20231016143836/https://dns.alidns.com/resolve?name=tls-ech.dev&type=HTTPS

{“Status”:0,”TC”:false,”RD”:true,”RA”:true,”AD”:false,”CD”:false,”Question”:{“name”:”tls-ech.dev.”,”type”:65},”Answer”:[{“name”:”tls-ech.dev.”,”TTL”:60,”type”:65,”data”:”Not support now”}]}

网页查看 https://dns.google/query

第三种办法就是直接在网页上查:https://dns.google/query?name=tls-ech.dev&rr_type=https

但是目前大部分提供dns查询服务的网站都没有提供type HTTPS参数,暂时只找到谷歌家的

只要查询时能看到ech,就说明这个网站已开启ech,参见

https://www.reddit.com/r/CloudFlare/comments/171fvih/how_do_i_check_if_a_site_supports_the_newly/

https://techcommunity.microsoft.com/t5/discussions/you-can-now-enable-encrypted-client-hello-encrypted-sni-or-esni/m-p/3600372#:~:text=detects%20it%20too.-,Here,-i%20checked%20it

抓包也只能看到outer sni,如果是发往cloudflare下支持ech的网站,分离模式下应该是 OuterSni:cloudflare-ech.com InnerSni: you_servername.com。

GFW可能的手段

再回来看本文,ech利用outer sni来为inner sni作掩护,是一种把鸡蛋放在一个篮子里的行为?鸡蛋越多,则每个鸡蛋越安全,外部只能看到outer sni,猜中的概率是1/鸡蛋数量。

gfw接下来无非那么几条路:

一、污染明文dns中ech、更严厉的封doh

二、把具有ech特征的包全封了,esni的时候就这么干的https://gfw.report/blog/gfw_esni_blocking/zh

三、封掉提供ech cdn的sni,也许把OuterSni 比如cloudflare-ech.com更精准一些?

为了碰瓷站方更像一点,多点断断续续的老套路:

一旦浏览器可以开始发起ech,他就会发送查询类型为HTTPS的请求,这可以在dns本地服务端清晰的看到三条请求一条A 一条AAAA 一条HTTPS

只要不是很老的浏览器,一般都会发起HTTPS请求,但是用不用返回记录里的ech,那就是浏览器自己的事了,能不能获得ech,那就是gfw的事情了

相关文档

Good-bye ESNI, hello ECH! 文章里的有链接到草案 https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-08
草案 10.2提到:

Moreover, as noted in the introduction, SNI encryption is less useful without encryption of DNS queries in transit via DoH or DPRIVE mechanisms.

不搭配doh使用,sni加密用处就不大了,主要指ClientHelloInner的sni在dns查询时的泄露,跟ESNI一个原因,你都用明文dns了,请求的域名也就是加密在inner里的sni早就被看走了,你再加密它,等于脱了裤子放屁,但当时没阻止esni的上马使用,是在当时没有doh的环境下的无奈选择。

草案没有提及doh会影响连接时的握手。

草案3.2:

A client-facing server enables ECH by publishing an ECH configuration, which is an encryption public key and associated metadata. The server must publish this for all the domains it serves via Shared or Split Mode. This document defines the ECH configuration’s format, but delegates DNS publication details to [HTTPS-RR]. Other delivery mechanisms are also possible. For example, the client may have the ECH configuration preconfigured.

面向客户端的服务器通过发布 ECH 配置来启用 ECH,该配置适用于 ECH 是加密公钥和关联的元数据。服务器必须发布 这适用于它通过共享或拆分模式提供的所有域。本文档 定义 ECH 配置的格式,但委派 DNS 发布详细信息 到 [HTTPS-RR]。其他交付机制也是 可能。例如,客户端可能预配置了 ECH 配置。

客户端可以预置ech,这种一般就不是浏览器,而是app的情况。

草案3.2 :

When a client wants to form a TLS connection to any of the domains
served by an ESNI-supporting provider, it replaces the “server_name”
extension in the ClientHello with an “encrypted_server_name”
extension, which contains the true extension encrypted under the
provider’s public key. The provider can then decrypt the extension
and either terminate the connection (in Shared Mode) or forward it to
the backend server (in Split Mode).

当客户端想要与支持 ESNI 的提供商所服务的任何域形成 TLS 连接时,它会将把ClientHello 中的“server_name”扩展替换为“encrypted_server_name”扩展 ,其中包含在提供商的公钥下加密的真实扩展。然后,提供者可以解密扩展并终止连接(在共享模式下)或将其转发到后端服务器(在分离模式下)
。整个ClientHelloInner都会被加密放在ClinetHelloOuter的encrypted_server_name扩展里面,而加密整个inner的公钥和方法就在那串ech里。

Encrypted Client Hello (ECH) – Frequently asked questions 里关于doh和ech的描述:

How will ECH interact with DoH’s opt-outs?
DoH opt-outs will disable ECH encryption by default in Firefox. These opt-outs can be configured by the user or software installed on their device, by signals from the network or by an administrator via group policy. If the user or administrator explicitly opt-ins to increased or maximum DoH protection, their choice overrides signals from the network.

仅表达了不用doh会在firefox中默认禁用ech加密,而不是说没有doh就无法进行ech加密

最后,目前cloudflare已经停了ech:

https://community.cloudflare.com/t/early-hints-and-encrypted-client-hello-ech-are-currently-disabled-globally/567730

赞(1)


文章来源: https://itlanyan.com/ech-without-doh-is-possible/
如有侵权请联系:admin#unsafe.sh