bbs icon indicating copy to clipboard operation
bbs copied to clipboard

Is it possible to use ODoH (Oblivious DoH) to bypass DoH server blocking? 能否使用 ODoH (Oblivious DoH) 绕过 DoH 服务器封锁?

Open 0x391F opened this issue 9 months ago • 34 comments

China seems has been block Cloudflare DNS. Is it possible to use ODoH (Oblivious DoH) to bypass DoH server blocking?

About ODoH https://petsymposium.org/popets/2021/popets-2021-0085.php

AFAIK, here're some project: https://github.com/cloudflare/odoh-rs https://github.com/DNSCrypt/doh-server (complied binaries avaliable)

0x391F avatar Mar 08 '25 04:03 0x391F

可以,但起作用的点在于搭了个 proxy,如果这个 proxy 是公开的则迟早会被封

即使是私有的,Chrome 的 DoH 具有类似 TLS in TLS 那样相对固定的长度特征,ODoH 应该也无法幸免,GFW 可以分析大量数据后认为该服务器在提供 DoH/ODoH 服务并封锁它,解决办法是加 padding,比如 Xray 前几天给 DoH request 的 header 加了 padding:https://github.com/XTLS/Xray-core/commit/e466b0497c3c563622146e2595d4870e4a43f56e#diff-70be69743619b578d48e9a299311b5fde596a003f7a65668d01c05a2a9ac2eafR284

当时有这个 commit 是因为我认为 GFW 会干扰境外公共 DoH、未来在于自建,所以与其装成 Chrome 的 DoH 请求特征,不如消除 DoH 特征,结果第二天开始 DoH 就被大规模封锁(2025.3.4),也可能更早,不确定这次封锁是否会成为 GFW 的长期策略

当然 response 也要加 padding,应当由 DoH 服务端来完成,并且要注意 HTTP 中间件是否会分离 response header 和 body 的粘合


Yes, but the point is that a proxy is used, and if this proxy is public, it will be blocked sooner or later.

Even if it is private, Chrome's DoH has a relatively fixed length feature similar to TLS in TLS, and ODoH should not be immune. The GFW can analyze a large amount of data and determine that the server is providing DoH/ODoH services and block it. The solution is to add padding. For example, Xray added padding to the header of the DoH request a few days ago: https://github.com/XTLS/Xray-core/commit/e466b0497c3c563622146e2595d4870e4a43f56e#diff-70be69743619b578d48e9a299311b5fde596a003f7a65668d01c05a2a9ac2eafR284

The reason for this commit at the time was that I believed that GFW would interfere with public DoH outside the country and that the future lied in self-construction. So instead of pretending to have the DoH request feature of Chrome, it was better to eliminate the DoH feature. As a result, DoH was massively blocked the next day (2025-03-04), or perhaps even earlier. It is uncertain whether this block will become a long-term strategy of GFW.

Of course, the response should also be padded, which should be done by the DoH server, and care should be taken to ensure that the HTTP middleware does not separate the response header from the body.

RPRX avatar Mar 08 '25 09:03 RPRX

可以,但起作用的点在于搭了个 proxy,如果这个 proxy 是公开的则迟早会被封

即使是私有的,Chrome 的 DoH 具有类似 TLS in TLS 那样相对固定的长度特征,ODoH 应该也无法幸免,GFW 可以分析大量数据后认为该服务器在提供 DoH/ODoH 服务并封锁它,解决办法是加 padding,比如 Xray 前几天给 DoH request 的 header 加了 padding:XTLS/Xray-core@e466b04#diff-70be69743619b578d48e9a299311b5fde596a003f7a65668d01c05a2a9ac2eafR284

当时有这个 commit 是因为我认为 GFW 会干扰境外公共 DoH、未来在于自建,所以与其装成 Chrome 的 DoH 请求特征,不如消除 DoH 特征,结果第二天开始 DoH 就被大规模封锁(2025.3.4),也可能更早,不确定这次封锁是否会成为 GFW 的长期策略

当然 response 也要加 padding,应当由 DoH 服务端来完成,并且要注意 HTTP 中间件是否会分离 response header 和 body 的粘合

Firefox 默认对 DoH 启用了填充,不过糟糕的是长度是固定的: about:config 设置:

network.trr.padding = true
network.trr.padding.length = 128

Firefox has been enable padding for DoH by default, but unfortunately the length is fixed: about:config configuration:

network.trr.padding = true
network.trr.padding.length = 128

0x391F avatar Mar 08 '25 10:03 0x391F

它这个填充应该不是 request header 吧,也就是说 DoH 有可供填充的结构?我还没研究

It's not a request header, is it? In other words, DoH has a structure that can be filled in? I haven't researched it yet.

RPRX avatar Mar 08 '25 11:03 RPRX

选项的定义在此可以找到 https://searchfox.org/mozilla-central/source/modules/libpref/init/StaticPrefList.yaml#14270 The definition of options could be found in here: https://searchfox.org/mozilla-central/source/modules/libpref/init/StaticPrefList.yaml#14270

# Whether to add padding in the doh dns queries (rfc 7830)

  • name: network.trr.padding type: RelaxedAtomicBool value: true mirror: always

# The block size to pad to. Capped at 1024 bytes. # Setting it to 0 doesn't add additional padding, but allows the server to # respond with padding (RFC7930 Sec 4)

  • name: network.trr.padding.length type: RelaxedAtomicUint32 value: 128 mirror: always

0x391F avatar Mar 08 '25 11:03 0x391F

这样的话以后 Xray 也给 DoH body 本身加个随机 padding 吧,不过 Golang 应该是默认把 request header 和确定的 body 粘了起来

现在更加重要的事情是给 Xray 加个自建 DoH server with padding 的功能,并且禁止不带 padding 的请求

至于 Chrome 没给 DoH 加 padding 倒不是大问题,可以叠加 MITM https://github.com/net4people/bbs/issues/454 来解决

话说 @Fangliding 提到过 ECH 可以绕过近期的 DoH 封锁,或许 domain fronting 也行?你可以先用 Xray DNS 的 h2c:// 测试下

测试成功的话就可以给 Chrome 强制 domain fronting,我觉得它是个比 ECH 更好的解决方案,因为那个 SNI 未来可能也会被封


In that case, in the future, Xray should also add random padding to the DoH body itself. However, Golang should already be defaulting to pasting the request header to the determined body.

The more important thing now is to add a function to Xray to build a DoH server with padding, and to prohibit requests without padding

As for Chrome not adding padding to DoH, it's not a big deal. It can be solved by superimposing MITM https://github.com/net4people/bbs/issues/454

Anyway, @Fangliding mentioned that ECH can bypass the recent DoH blocking, and maybe domain fronting will work too? You can first test it with Xray DNS's h2c://

If the test is successful, you can force Chrome to use domain fronting. I think it's a better solution than ECH, because SNI may also be blocked in the future.

RPRX avatar Mar 08 '25 11:03 RPRX

这个方案其实是为了解决最近 Cloudflare DNS 在中国被封锁的问题。

In fact, this solution is used to resolve the problem that Cloudflare DNS has been blocked in China recently.

0x391F avatar Mar 08 '25 14:03 0x391F

The only ODoH client now is dnscrypt-proxy, and there are 4 relays (proxy) listed.

  • https://odoh-nl.alekberg.net:443/proxy
  • https://odoh-relay.edgecompute.app/
  • https://ibksturm.synology.me:443/proxy
  • https://odoh-se.alekberg.net:443/proxy

Already been blocked with SNI except the .app one.

Also, the DoH server needs to opt in to become ODoH; among the popular providers, it seems only Cloudflare did this.

So the answer is No, not yet.

UjuiUjuMandan avatar Mar 09 '25 05:03 UjuiUjuMandan

TLS in TLS 那样相对固定的长度特征,ODoH 应该也无法幸免

ODoH or OHTTP is not TLS in TLS.

UjuiUjuMandan avatar Mar 09 '25 05:03 UjuiUjuMandan

才发现,现在 Firefox 中的 ODoH 被 OHTTP 取代了: https://bugzilla.mozilla.org/show_bug.cgi?id=1835805 ,所以现在应该换成用 OHTTP。

I just find that ODoH in Firefox has been replaced by OHTTP: https://bugzilla.mozilla.org/show_bug.cgi?id=1835805, so we need to use OHTTP instead.

0x391F avatar Mar 09 '25 05:03 0x391F

In fact, this solution is used to resolve the problem that Cloudflare DNS has been blocked in China recently.

如果要以非自建 proxy server 的形式解决 DoH 被封的问题,则可能只有 domain fronting 这一条路,比如找到个可用 IP,SNI 填 cloudflare.com 或其它没被封的 SNI,但 HTTP 请求是 dns-query,虽然这样对 CF 不一定可行,但一定会有可行的公共 DoH

If you want to solve the problem of DoH being blocked without setting up your own proxy server, the only way may be domain fronting. For example, you can find an available IP address and set the Server Name Indication (SNI) to cloudflare.com or another SNI that has not been blocked. However, HTTP requests are DNS queries. Although this may not be feasible for Cloudflare, there must be a feasible public DoH solution.

RPRX avatar Mar 09 '25 07:03 RPRX

ODoH or OHTTP is not TLS in TLS.

Plain DoH in TLS / Plain ODoH in TLS / Plain DoH in OHTTP in TLS

RPRX avatar Mar 09 '25 07:03 RPRX

In fact, this solution is used to resolve the problem that Cloudflare DNS has been blocked in China recently.

如果要以非自建 proxy server 的形式解决 DoH 被封的问题,则可能只有 domain fronting 这一条路,比如找到个可用 IP,SNI 填 cloudflare.com 或其它没被封的 SNI,但 HTTP 请求是 dns-query,虽然这样对 CF 不一定可行,但一定会有可行的公共 DoH

不用啊,非自建的话唯一需要的是 OHTTP 中继,只要它没被封,就可以使用 DoH。它是端到端加密的,中继无法窃听或篡改:https://blog.cloudflare.com/oblivious-dns/

Nope, if the server is not build by yourself, what you only need is OHTTP relay, if it hasn't blocked, you can use DoH. It's end-to-end, the delay couldn't wiretap or tamper: https://blog.cloudflare.com/oblivious-dns/

In ODoH, the ‘O’ stands for oblivious, and this property comes from the level of encryption of the DNS messages themselves. This added encryption is end-to-end between client and target, and independent from the connection-level encryption provided by TLS/HTTPS.

翻译:在 ODoH 中,“O ”代表遗忘,这一特性来自 DNS 消息本身的加密级别。这种附加加密在客户端和目标之间是 “端到端 ”的,独立于 TLS/HTTPS 提供的连接级加密。

0x391F avatar Mar 09 '25 08:03 0x391F

我第一句评论就是:

“可以,但起作用的点在于搭了个 proxy,如果这个 proxy 是公开的则迟早会被封”

而 domain fronting 是在 GFW 把 SNI 封了之后仍然能访问 DoH 的东西

My first comment was:

“Yes, but the point is that a proxy is used, and if this proxy is public, it will be blocked sooner or later.”

Domain fronting is something that can still access DoH after GFW blocks SNI.

RPRX avatar Mar 09 '25 08:03 RPRX

DoH in TLS

Yes.

ODoH in TLS / OHTTP in TLS

The identifiable component of TLS is handshake, HPKE encryption inside TLS doesn't need a handshake.

UjuiUjuMandan avatar Mar 09 '25 09:03 UjuiUjuMandan

原描述有歧义,我修改了描述为 "Plain DoH in TLS / Plain ODoH in TLS / Plain DoH in OHTTP in TLS"

就像 TLS handshake 有相对固定的长度特征,DoH / ODoH 请求与响应本身也有相对固定的长度特征,你可以用 WireShark 观察到

The original description was ambiguous, so I revised it to read "Plain DoH in TLS / Plain ODoH in TLS / Plain DoH in OHTTP in TLS"

Just as TLS handshakes have a relatively fixed length, DoH/ODoH requests and responses also have a relatively fixed length. You can observe this with WireShark.

RPRX avatar Mar 09 '25 09:03 RPRX

而 domain fronting 是在 GFW 把 SNI 封了之后仍然能访问 DoH 的东西

https://github.com/net4people/bbs/issues/67#issuecomment-2649513559

Built-in meek bridge on Azure was removed from Tor Browser 3 weeks ago.

https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/merge_requests/1141

_Azure 上内置的 meek bridge 已于 3 周前从 Tor 浏览器中删除。

https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/merge_requests/1141_ 恐怕支持域前置的 CDN/云服务器厂商会越来越少。

https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/merge_requests/1141 I afraid that CDN/cloud servers which support domain fronting will become less an less._

0x391F avatar Mar 09 '25 09:03 0x391F

I afraid that CDN/cloud servers which support domain fronting will become less an less.

对于 DoH 来说,几乎只要有可用的就行,而你总能找到一个能够域前置的 DoH,~~实在不行就自己建一个~~

还有 ECH 能暂时解决问题,但它们用的固定 SNI 在未来也可能会被封

For DoH, almost anything that is available is fine, and you can always find a DoH that can be domain-fronted. ~~If that doesn't work, just build your own.~~

ECH can also temporarily solve the problem, but the fixed SNI they use may also be blocked in the future

RPRX avatar Mar 09 '25 09:03 RPRX

https://bugzilla.mozilla.org/show_bug.cgi?id=1952777#c2 给出了正确步骤。

https://bugzilla.mozilla.org/show_bug.cgi?id=1952777#c2 gives the correct steps.

The following about:config settings work for me:

network.trr.mode 3 network.trr.ohttp.config_uri https://dooh.cloudflare-dns.com/.well-known/doohconfig network.trr.ohttp.relay_uri https://mozilla-ohttp-relay.edgecompute.app/dooh network.trr.ohttp.uri https://dooh.cloudflare-dns.com/dns-query network.trr.use_ohttp true

If the URI settings had default values, you would only need to toggle network.trr.use_ohttp.

network.trr.ohttp.uri https://dooh.cloudflare-dns.com/dns-query 可以用 https://1.1.1.1/dns-queryhttps://1.0.0.1/dns-query 代替。

network.trr.ohttp.uri https://dooh.cloudflare-dns.com/dns-query could be use https://1.1.1.1/dns-query or https://1.0.0.1/dns-query instead.

0x391F avatar Mar 11 '25 14:03 0x391F

Oops, I close this issue by accident. Please help me to reopen it, thanks! @wkrp

0x391F avatar Mar 11 '25 14:03 0x391F

@0x391F You are able to reopen the issue as it was closed by yourself.

RPRX avatar Mar 13 '25 09:03 RPRX

@0x391F You are able to reopen the issue as it was closed by yourself.

Yes, you're right, but I don't know why I couldn't reopen it that day, it said that I did't have permission.

0x391F avatar Mar 13 '25 09:03 0x391F

不过有个致命缺陷:如果 network.trr.ohttp.config_uri ——在这里是 https://dooh.cloudflare-dns.com/.well-known/doohconfig 被封锁了,OHTTP 就不能用了。

But here're a fatal defect: If network.trr.ohttp.config_uri - at here is https://dooh.cloudflare-dns.com/.well-known/doohconfig - be blocked, OHTTP will not work.

0x391F avatar Mar 13 '25 10:03 0x391F

这就是我的意思,ODoH / OHTTP 对于“绕过封锁”这个目标只是起到了“代理”的作用,并且公开的“代理”迟早会被封锁

我认为最佳的绕过 DoH 封锁的方式是 domain fronting + padding,因为你总能找到允许域前置的服务商

This is what I mean. ODoH/ODHTTP only serves as a “proxy” for the goal of “bypassing the blockade”, and sooner or later, the overt “proxy” will be blocked

I think the best way to bypass DoH blocking is domain fronting + padding, because you can always find a service provider that allows domain fronting.

RPRX avatar Mar 13 '25 10:03 RPRX

这就是我的意思,ODoH / OHTTP 对于“绕过封锁”这个目标只是起到了“代理”的作用,并且公开的“代理”迟早会被封锁

甚至更糟,除非有其他方法得到 OHTTP config,否则换其他中继(“代理”)(network.trr.ohttp.relay_uri)也没有用。

Even worse - unless have other ways to get OHTTP config, otherwise use other relays ("proxy") (network.trr.ohttp.relay_uri) will also useless.

0x391F avatar Mar 13 '25 11:03 0x391F

在“要先获取信息”这一缺点上我觉得区别不大,比如说 domain fronting 你也要先获取相关配置,区别在于它公开后 GFW 也不容易封

I don't think there is much difference in the drawback of “you need to obtain information first”. For example, with domain fronting, you also need to obtain the relevant configuration first. The difference is that after it is made public, it is not easy for the GFW to block it.

RPRX avatar Mar 13 '25 15:03 RPRX

just curios,has anyone in china tried tcp fragment for doh?cf doh has been blocked for a long time in my country but tcp fragment can bypass that easily,in xray core u can manually resolve cloudflare-dns.com to a non blocked cf ip and use cloudflare-dns.com/dns-query for doh and set up fragment in freedom,it works well it is the same story as ECH though , as this trick can also get blocked in the future

CyrusTheG avatar Mar 13 '25 23:03 CyrusTheG

在“要先获取信息”这一缺点上我觉得区别不大,比如说 domain fronting 你也要先获取相关配置,区别在于它公开后 GFW 也不容易封

那倒不一定,OHTTP config 服务器被封了的话可以自己用 Nginx 或者 Cloudflare 搭一个反向代理,这种情况下部署应该比 DNS 服务器简单,只要确保 Relay 可用就行。

Maybe not, If OHTTP server has been blocked, user could use Nginx or Cloudflare to build a reverse proxy for it. I think it may eaiser than build an DNS server, it only needs to make sure that Relay is available.

0x391F avatar Mar 14 '25 00:03 0x391F

我说的重点一直在于这个配置公开后 GFW 容不容易封,也就是对大多数人而言是不是 serverless,因为如果要每个人都自己去搭反向代理,那还不如直接搭一个通用代理,在这里我们要的是即使把配置给 GFW 看,GFW 也不好封的东西,也就是 domain fronting

The main point I have been making is whether it is easy for the GFW to block this configuration after it is made public. In other words, for most people, is it serverless? Because if everyone has to set up their own reverse proxy, it is better to set up a universal proxy. Here, what we want is something that is difficult for the GFW to block even if the configuration is shown to it. In other words, domain fronting.

RPRX avatar Mar 14 '25 07:03 RPRX

我说的重点一直在于这个配置公开后 GFW 容不容易封,也就是对大多数人而言是不是 serverless,因为如果要每个人都自己去搭反向代理,那还不如直接搭一个通用代理,在这里我们要的是即使把配置给 GFW 看,GFW 也不好封的东西,也就是 domain fronting

可能容易被封。一旦 dooh.cloudflare-dns.com (OHTTP config 服务器)被封锁了,OHTTPS 就用不了了,换什么中继都没有用,除非通过其他服务器获取 config 或者换 DNS 服务器(注意不是中继)和 OHTTP config 服务器,因为必须先获取 OHTTP config,才能进行 DNS 查询。此时无法做到 "severless"。

Maybe easy to blocked. Once dooh.cloudflare-dns.com (OHTTP config server) be clocked, OHTTP will not able to use, no matter change any relay, unless get config via other servers or change DNS server (note: NOT relay) and OHTTP config server, because must to get OHTTP config first, then executing DNS query. In this situation, "severless" is impossible.

0x391F avatar Mar 14 '25 08:03 0x391F

我看懂了,你要表达的是这个 OHTTP config 是需要程序通过一个 URL 自动获取的,那当然可以成为另一个封锁点,就像 GFW 为了封锁 ECH 就先封锁了不受 GFW 控制的境外 DoH,~~然后可能为了封锁境外 DoH 中继又去封锁 OHTTP config server,什么俄罗斯套娃~~

~~封 ECH 的 SNI,封境外 DoH,封境外 DoH 中继,封 OHTTP config server。。。封得差不多了~~

Anyway,如我所说,domain fronting + padding 目前看来是最优解,即使把配置贴在国内平台上,GFW 能做的也就只是删帖

然而这种过于 anti-censorship 的功能,主流软件比如 Chrome 可能并没有内置它的计划,只能 https://github.com/net4people/bbs/issues/454


I see. What you're trying to say is that the OHTTP config needs to be automatically obtained by the program through a URL, which of course can become another blocking point. Just like GFW blocked ECH by first blocking overseas DoH, which is not under GFW's control, ~~and then, perhaps, blocked the OHTTP config server in order to block overseas DoH relays, it's like a Russian nesting doll.~~

~~Block ECH's SNI, block overseas DoH, block overseas DoH relay, block OHTTP config server... It's almost done.~~

Anyway, as I said, domain fronting + padding seems to be the best solution for now. Even if you post the configuration on a domestic platform, all the GFW can do is delete the post.

However, mainstream software such as Chrome may not have plans to build this kind of overly anti-censorship functionality into it, so the only option is https://github.com/net4people/bbs/issues/454

RPRX avatar Mar 14 '25 11:03 RPRX