Skip to content

uTLS for DOH #4313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
patterniha opened this issue Jan 20, 2025 · 157 comments
Closed

uTLS for DOH #4313

patterniha opened this issue Jan 20, 2025 · 157 comments

Comments

@patterniha
Copy link
Contributor

patterniha commented Jan 20, 2025

please add these features to built-in DOH:

///

  1. DOMAIN FRONTING:

the iran-great-firewall block most DOHs by sni(tls client hello hostname) but their IPs is not blocked.
one way to access DOH is using fragment, but fragment doesn't work sometimes and even if it works, it will increase the dns round-trip time.

the best way is using domain fronting,
I implemented domain fronting in python and it's working great for DOH.
all popular DOHs allow domain fronting.

Its implementation is also very easy:

    1. add "fake-sni" option in dns DOH settings.
    2. start tls with fake-sni(replace sni with fake-sni in tls client hello)
    3. disable ssl verification(allowInsecure)
    4. request http with host-header=true-host

///

  1. TLS FINGERPRINT:

tls fingerprint is currently only available for proxy-outbounds, please add this feature for DOH, so it will no longer be recognizable.

///

  1. HTTP/3:

some DOH support http/3. please add doh over http/3.

///

  1. CUSTOM HEADERS:

add this feature to add/edit/remove doh http headers.

///

so the final dns configuration would be something like:

"dns": {
  "hosts": {
    "dns.google": ["8.8.8.8","8.8.4.4"]
  },
  "servers": [
    {
      "address": "https://dns.google/dns-query",
      "sni": "www.google.com",
      "allowInsecure": true,
      "check-hostname-for": "dns.google",
      "fingerprint": "chrome",
      "alpn": ["h2","http/1.1"],   // "h3" for http/3
      "headers": {
        "User-Agent": "Mozila/5.0 ..."
      }
    }
  ]
}
@patterniha patterniha changed the title add domain fronting, tls fingerprint, http/3 to built-in DOH add domain fronting, tls fingerprint and http/3 to built-in DOH Jan 20, 2025
@patterniha patterniha changed the title add domain fronting, tls fingerprint and http/3 to built-in DOH add domain fronting, tls fingerprint, http/3 and custom headers to built-in DOH Jan 21, 2025
@Fangliding
Copy link
Member

暂不考虑
PR is welcome

@Fangliding Fangliding closed this as not planned Won't fix, can't repro, duplicate, stale Jan 21, 2025
@patterniha
Copy link
Contributor Author

Don't consider it yet PR is welcome

the built-in dns hasn't changed in a long time and is outdated.

I'm a python developer, otherwise I would have PR a long time ago.
I implemented most of these with python, but unfortunately Xray-core is based on go.

domain fronting implementation is easy, It can be used in other cases as well, at least you can consider this.

Anyway, it's better to leave this issue open because sooner or later the built-in dns will have to be updated.

@Fangliding
Copy link
Member

我不是那种喜欢堆很多 open issues 的人 我对issue的态度很明确 保持打开的都是确认无误的BUG和有人take的feature request 留太多陈旧的open issues不会让哪天有好心人从天而降从里面随机pick一个实现 只会堆的越来越多最后让open失去的意义 变成垃圾堆

@RPRX
Copy link
Member

RPRX commented Jan 21, 2025

对于 1 和 2,我可以把 DoH 改成 uTLS Chrome 并实际应用 refraction-networking/utls#161

只是看起来无人维护 uTLS 了,可能以后 Xray 不得不维护一个 Chrome 指纹

@patterniha
Copy link
Contributor Author

patterniha commented Jan 21, 2025

For 1 and 2, I can change DoH to uTLS Chrome and actually apply refraction-networking/utls#161

It just seems like no one is maintaining uTLS. Maybe Xray will have to maintain a Chrome fingerprint in the future.

2,3,4 are not very important right now.(but it's important in the future)

but It would be great if number 1 was done.

1 practically solves the DNS problem in Iran.

Fragment is not suitable for DNS at all.

@patterniha
Copy link
Contributor Author

patterniha commented Jan 21, 2025

我可以把 DoH 改成 uTLS Chrome 并实际应用

so I'm waiting for 1 and 2, I hope you don't forget, THANK YOU

@patterniha patterniha changed the title add domain fronting, tls fingerprint, http/3 and custom headers to built-in DOH uTLS for DOH Jan 21, 2025
@intmain0
Copy link

intmain0 commented Jan 22, 2025

#4185
上个月提过uTLS for DOH,其实DOH可以强制使用Chrome指纹的
https://github.com/XTLS/Xray-core/blob/main/app/dns/nameserver_doh.go#L286DOH的代码在这,急用的话可以直接在这改完之后自己编译

@patterniha
Copy link
Contributor Author

#4185 Last month I mentioned uTLS for DOH. In fact, DOH can force the use of Chrome fingerprints. The code of https://github.com/XTLS/Xray-core/blob/main/app/dns/nameserver_doh.go#L286DOH is here. If you need it urgently, you can compile it yourself after making the changes here.

My emphasis is on the "domain fronting" rather than the "fingerprint".

@patterniha
Copy link
Contributor Author

patterniha commented Jan 22, 2025

对于 1 和 2,我可以把 DoH 改成 uTLS Chrome 并实际应用 refraction-networking/utls#161

只是看起来无人维护 uTLS 了,可能以后 Xray 不得不维护一个 Chrome 指纹

@RPRX

if we use "fake-sni", servers give us the "default-certificate":

  1. It's not hard for MitM to get valid certificate for an irrelevant domain and give it to us as a default-certificate.

    --> "validate certificate without check hostname" is no different with "not validating at all".

  2. our "main-host" may not be in "default-certificate-san-list".

    --> "enable validation and check hostname for main-host" may cause our connection to the server to fail.

  3. Suppose we are sure that "x.com" is in the "default-certificate-san-list" (x.com is not necessarily the same as "main-host").

    --> we should "validate certificate and check hostname for x.com"

  4. Suppose that the server supports(hosts) x1.com, x2.com,... and the server sometimes returns x1.com certificate as a default-certificate and sometimes x2.com (and certificates are distinct).

    --> we should "validate certificate and check hostname for [x1.com or x2.com or ...](until the first one is verified)".

///
as a result, we need these options for domain fronting:

1. "sni" : String  // default: main-host, can be any fake-sni
2. "check-hostname-for": String | List  //It makes sense if allowInsecure is false, default: main-host, "": disable check hostname, list is a "or list"
3. ip: String | List



@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

只给 https+local 加了 Chrome's fingerprint with fakeSNI,一是非 local 不需要,二是绕过服务端路由就抽象了,试试 ee55203

我看它这里用的是 http.Transport,我查了下 DoH 都支持 H2,似乎改成直接 http2 更合适?@Fangliding @yuhan6665
已经改了

@RPRX RPRX reopened this Jan 22, 2025
@Fangliding
Copy link
Member

Fangliding commented Jan 22, 2025

没必要动吧 这样又不影响 本来就是强制尝试h2的 http2是个low level的包 分开处理h1 h2的时候才会用

@Fangliding
Copy link
Member

其实甚至不用单独写 直接用核心里的tcp dialer带conf传出去就行了 config里可以嵌入包括fingerprint在内的整个tlsSetting

@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

没必要动吧 这样又不影响 本来就是强制尝试h2的 http2是个low level的包 分开处理h1 h2的时候才会用

报错 net/http: HTTP/1.x transport connection broken: malformed HTTP response,它可能是走 upgrade,我给它改成直接 http2 吧

其实甚至不用单独写 直接用核心里的tcp dialer带conf传出去就行了 config里可以嵌入包括fingerprint在内的整个tlsSetting

配置加哪是个问题,而且我们有 REALITY,似乎不太有必要给 tlsSettings 加 fakeSNI

@Fangliding
Copy link
Member

报错 net/http: HTTP/1.x transport connection broken: malformed HTTP response,它可能是走 upgrade,我给它改成直接 http2 吧

给utls加alpn看看 它默认是不执行alpn协商的(虽然会发) 向上层返回协商结果为空 可能默认h1了

配置加哪是个问题,而且我们有 REALITY,似乎不太有必要给 tlsSettings 加 fakeSNI

我之前觉得是改servername开insecure的 我知道utls有更高级的选项 那算了就这样吧

@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

给utls加alpn看看 它默认是不执行alpn协商的(虽然会发) 向上层返回协商结果为空 可能默认h1了

Chrome 指纹默认 h2, http/1.1 的,我感觉 Go 这个 http 包可能默认 h1 再 upgrade 到 h2,让它控制 TLS 的话 ALPN 会是仅 http/1.1

我之前觉得是改servername开insecure的 我知道utls有更高级的选项 那算了就这样吧

这个更高级的选项是我加的,终于用上了

@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

@Fangliding 试试 ee55203 的 fakeSNI 有没有效,用 WireShark 看一下

@patterniha
Copy link
Contributor Author

patterniha commented Jan 22, 2025

@RPRX
sorry is my fault, everything is fine even hosts.

@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

@patterniha 我本来还想说,你可以直接用 https+local://8.8.8.8/dns-query,fakeSNI 设为 www.google.com

@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

我感觉 DoH 应该都有 IP 证书吧,不然如果无法直接通过 IP 访问,这 DNS 也是抽象

@RPRX RPRX closed this as completed in 3ff11c5 Jan 22, 2025
@patterniha
Copy link
Contributor Author

patterniha commented Jan 22, 2025

I feel that DoH should all have IP certificates, otherwise if it cannot be accessed directly through IP, the DNS is also abstract.

yes, but not for DOH behind the cdn and don't want their IP to be revealed.
and even doh.cleanbrowsing.org is not behind the cdn but doesn't have IP certificate

@RPRX
Copy link
Member

RPRX commented Jan 22, 2025

@patterniha 我不确定 Xray 内置 DNS 里的 hosts 设置项是否对 https+local 的 host 有效,感觉没有

@patterniha
Copy link
Contributor Author

I feel that DoH should all have IP certificates, otherwise if it cannot be accessed directly through IP, the DNS is also abstract.

close???
where is fingerprint???

where is options in #4313 (comment) ???

@patterniha
Copy link
Contributor Author

@patternihaI'm not sure about Xray's built-in DNS hostsIs the setting item valid for https+local hosts? I don’t think so.

it works correctly, I had a typo.

@patterniha
Copy link
Contributor Author

patterniha commented Jan 22, 2025

@RPRX
please read #4313 (comment) carefully, thx

@patterniha
Copy link
Contributor Author

patterniha commented Feb 8, 2025

@RPRX

first, not work.
second i confused mitmAlpn11 ??? h2c is h2 ???
third do you set "fromMitM" for alpn too?

@RPRX
Copy link
Member

RPRX commented Feb 8, 2025

h2c 加上 tls 不就是 h2 吗?所以 mitmAlpn11 应当置为 false,ALPN 的 fromMitm 应当被忽略

你不会又搞出 http/1.1 吧

@RPRX
Copy link
Member

RPRX commented Feb 8, 2025

first, not work.

你再测测,确定不行的话我让 mitmServerName 从别处取值

@patterniha
Copy link
Contributor Author

dns -> routing -> tls-repack correct?
what is mitmAlpn11 ???

@patterniha
Copy link
Contributor Author

mitmAlpn11 == dokomo with mitm with h11 alpn ?

@RPRX
Copy link
Member

RPRX commented Feb 8, 2025

what is mitmAlpn11 ???

内部变量名

@patterniha
Copy link
Contributor Author

aha internal

@patterniha
Copy link
Contributor Author

my tls-repack outbound:

{
            "tag": "tls-repack",
            "protocol": "freedom",
            "settings": {
                "redirect": ":443","domainStrategy": "ForceIP"
            },                               
            "streamSettings": {
                "security": "tls",
                "tlsSettings": {
          "fingerprint": "chrome",
                    "allowInsecure": false,
                    "serverName": "www.google.com",
                    "verifyPeerCertInNames": ["fromMitM"],              
                    "alpn": [
                        "fromMitM"
                    ]
                }
            }
        },

for "h2c://8.8.8.8/dns-query"

but not work

@patterniha
Copy link
Contributor Author

@RPRX
noooo

@patterniha
Copy link
Contributor Author

patterniha commented Feb 8, 2025

its my fault, i run the certificate command and certificate is overriden

wait for test again

@RPRX
Copy link
Member

RPRX commented Feb 8, 2025

@patterniha 不过我确实也发现了问题,测新的 613c63b

@patterniha

This comment has been minimized.

@patterniha
Copy link
Contributor Author

patterniha commented Feb 8, 2025

@RPRX

it works

we have only one tls-repack outbound, GREAT.

@patterniha
Copy link
Contributor Author

patterniha commented Feb 8, 2025

@RPRX

but all request send with one sni.

@RPRX
Copy link
Member

RPRX commented Feb 8, 2025

but all request send with one sni.

这东西我现在不是很想弄成一个数组,或许以后支持 geosite

@patterniha
Copy link
Contributor Author

thx again

@RPRX
Copy link
Member

RPRX commented Feb 8, 2025

@patterniha 测试 925a985

@patterniha
Copy link
Contributor Author

its ok, now easier to import

@RPRX
Copy link
Member

RPRX commented Feb 9, 2025

@patterniha 模板搞快点

@RPRX
Copy link
Member

RPRX commented Feb 9, 2025

还有个问题是浏览器 OCSP 不会把自签证书发出去吧,听说还是明文 HTTP

@patterniha
Copy link
Contributor Author

uploaded h2c + mitm template.

@intmain0
Copy link

@patterniha 现在 https+local 默认使用 Chrome 指纹,且你可以设置 fakeSNI 以改变 SNI,但验证证书仍用 url 中的 host

使用25.1.30测试,发现https+local的指纹是t13d1311h2_f57a46bbacb6_e7c285222651,搜索之后(https://github.com/hashicorp/terraform-provider-aws/issues/39311)有提到该指纹是go1.23的指纹

@RPRX
Copy link
Member

RPRX commented Feb 10, 2025

@intmain0 这项修改已被撤回,你需要使用 DoH h2c + freedom TLS 实现 Chrome 指纹

@patterniha
Copy link
Contributor Author

patterniha commented Feb 13, 2025

@RPRX

BUG

DNS(h2c) sometimes only return ipv6 !!! so if my network doesn't support ipv6 connection fails.

DOH//8.8.8.8 cache HIT: instagram.fevn6-4.fna.fbcdn.net -> [2a00:f38:0:111d:face:b00c:3333:a3f]

after restart xray-core(and deleted the dns cache) The problem is usually solved.

@patterniha
Copy link
Contributor Author

patterniha commented Feb 13, 2025

@RPRX
i think the problem is related to "IPOnDemand" it doesn't wait enough for both ipv4 and ipv6.
and if one of them arrived, it ignore the other if it arrive with delay.
so in dns cache we only have one type of ip.
///

this log show that even in doh we send two request for ipv4 and ipv6:

2025/02/13 08:36:48.896938 [Info] app/dns: DOH//8.8.8.8 got answer: edge-chat-fallback.facebook.com. TypeA -> [31.13.72.8] 439.9293ms
2025/02/13 08:36:48.899692 [Info] app/dns: DOH//8.8.8.8 got answer: edge-chat-fallback.facebook.com. TypeAAAA -> [[2a03:2880:f00a:8:face:b00c:0:2]] 441.0922ms

i think in doh we can send both ipv4 and ipv6 queries in one request, right?
so if we send both queries in only one request the problem is solved

///
as a result:

  1. We have to wait for both queries to arrive
  2. As much as possible, we should send both queries in a single request.

@RPRX
Copy link
Member

RPRX commented Feb 13, 2025

i think in doh we can send both ipv4 and ipv6 queries in one request, right?

我不确定

你要设置 DNS 的 queryStrategy,让它只解析出 IPv4

@patterniha
Copy link
Contributor Author

i think in doh we can send both ipv4 and ipv6 queries in one request, right?

I'm not sure

You need to set the DNS queryStrategy so that it only resolves IPv4

@RPRX
but i need one config.
my wifi doesn't support ipv6 and mobile data support.
I can't change the config all the time.

and for serverless-for-iran Which one should I choose?
if ipv4 -> only ipv4 works even in ipv6 capable networks and we miss ipv6
if both -> this problem

so this problem should be solved

@RPRX
Copy link
Member

RPRX commented Mar 3, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants