mosdns icon indicating copy to clipboard operation
mosdns copied to clipboard

[BUG] 安卓系统 DoT 无法使用 lets encrypt 的证书

Open linusxiong opened this issue 2 years ago • 10 comments

出现了什么问题

启用安卓手机自带的安全dns使用mosdns的dot地址无法使用,使用chrome和edge的的内置doh填入mosdns的doh地址无法使用,已排除证书问题,换了两张不同ca的证书,已知coredns使用第三方插件同样可复现。


9月 13 19:13:16 localhost.localdomain mosdns[211888]: 2021/09/13 19:13:16 http: TLS handshake error from 124.64.xxx.xxx:2205: read tcp 192.168.xxx.xxx:443->124.64.xxx.xxx:2205: read: connection reset by peer
9月 13 19:13:17 localhost.localdomain mosdns[211888]: 2021/09/13 19:13:17 http: TLS handshake error from 120.239.xxx.xxx:43138: EOF
9月 13 19:24:26 localhost.localdomain mosdns[211888]: 2021/09/13 19:24:26 http2: server connection error from 120.37.xxx.xxx:55989: connection error: PROTOCOL_ERROR




2021-09-13T19:42:21.040+0800	warn	inbound_server	dns_handler/server_handler.go:88	entry returned an err	{"query": "msg.qy.net. IN AAAA 0 23", "error": "plugin tag ecs not defined"}
2021-09-13T19:42:25.313+0800	warn	inbound_server	dns_handler/server_handler.go:88	entry returned an err	{"query": "weather-data.apple.com. IN HTTPS 0 347", "error": "main_sequence: exec command failed: forward_domestic: context canceled"}
2021-09-13T19:42:26.059+0800	warn	forward_domestic	utils/utils.go:316	upstream failed	{"query": "i.vip.iqiyi.com. IN A 0 82", "from": "119.28.28.28", "error": "read timeout"}
2021-09-13T19:46:00.151+0800	warn	inbound_server	dns_handler/server_handler.go:104	write response	{"query": "c.passcloud.xyz. IN A 64870 28540", "error": "use of closed network connection"}


如何重现

描述一下如何重现该问题。请尽可能的包含:

mosdns 的版本号(mosdns -v):1.8.6

使用的启动参数或启动方式:systemctl启动

操作系统和平台:centos 8 rocky linux 已经关闭防火墙和selinux

使用的配置文件:


log:
  level: info
  file: "./log.log"
plugin:
  - tag: inbound_server
    type: server
    args:
      entry:
        - ecs
        - cache
        - main_sequence
      server:
        - protocol: doh
          addr: :443
          timeout: 5
          idle_timeout: 30
          cert: '/root/.acme.sh/脱敏/fullchain.cer'
          key: '/root/.acme.sh/脱敏.key'
          url_path: '/dns-query'
          get_user_ip_from_header: 'X-Forwarded-For'
        - protocol: udp
          addr: :8053
        - protocol: dot
          addr: :853
          timeout: 5
          idle_timeout: 30
          cert: '/root/.acme.sh/脱敏/fullchain.cer'
          key: '/root/.acme.sh/脱敏.key'
  - tag: main_sequence
    type: sequence
    args:
      exec:
        - if:
            - query_is_local_domain   # 已知的cn域名
            - '!_query_is_common'     # 和不常见的请求类型
          exec:
            - forward_dnspod           # 用dnspod服务器
            - _end

        - if:
            - query_is_non_local_domain  # 已知的非cn域名
          exec:
            - forward_google             # 用google服务器
            - _end

        - forward_dnspod               # 先请求转发至本地服务器
        - if:
            - response_has_local_ip   # 如果应答包含cn IP
          exec:
            - _end                    # 就直接采用结果
        - forward_google             # 否则去请求google服务器的结果
# 匹配本地域名的插件
  - tag: query_is_local_domain
    type: query_matcher
    args:
      domain:
        - 'ext:./geosite.dat:cn'

  # 匹配非本地域名的插件
  - tag: query_is_non_local_domain
    type: query_matcher
    args:
      domain:
        - 'ext:./geosite.dat:geolocation-!cn'
  # 匹配本地 IP 的插件
  - tag: response_has_local_ip
    type: response_matcher
    args:
      ip:
        - 'ext:./geoip.dat:cn'
  # 添加ECS的插件
  - tag: ecs
    type: ecs
    args:
      auto: true
      force_overwrite: false
  # 缓存插件
  - tag: cache
    type: cache
    argus: 
      size: 10000
      cleaner_interval: 180
  # 转发插件
  - tag: forward_google
    type: fast_forward
    args:
      upstream:
        - addr: 1.1.1.1
          trusted: true 
      deduplicate: true
  - tag: forward_dnspod
    type: fast_forward
    args:
      upstream:
        - addr: 119.29.29.29
          trusted: true 
      deduplicate: true

linusxiong avatar Sep 14 '21 01:09 linusxiong

我现在没自建的 DNS 所以不好测试这个问题。

印象中 @rampageX 大佬用的服务器场景较多。 @rampageX 大佬顺手的话能核实一下安卓系统/ chrome 能正常使用 mosdns 的 DoH/T 服务器吗?

update:

本地用自签的证书测试了 chrome doh,没有问题。安卓dot不认自签证书,没测。但mosdns 的dot 其他dot客户端都能正常用。

IrineSistiana avatar Sep 14 '21 08:09 IrineSistiana

甲骨文, 腾讯上海 VPS, Let’s Encrypt 证书.

选国内,国外两个服务器原因: 国外 853 端口被无条件阻断,而 iOS 目前无法使用非标准端口的 DoT 描述文件(或者说我也不知道怎么写),所以必须用国内 VPS 测 DoT; 国内 443 可用必须备案,那就只有用国外 VPS 测 DoH。

DoH 和 DoT 服务器 iOS 描述文件通过 https://dns.notjakob.com/tool.html 生成。

没有安卓设备, 在 iOS 14, Edge(基于 Chrome 的) 以及 Firefox 上测了 DoH, 在 iOS 14 上测了 DoT, 没发现什么问题。Edge 和 Firefox 都可以使用非标准端口的 DoH,地址后直接加端口即可,例如: https://cl.1024.xyz:4433/dns-query

目前版本 mosdns 建立的 DoH 和 DoT, 作为 dnsproxy, AdguardHome, https_dns_proxy, studdy, smartdns 的上游都没有问题,之前有问题的我也提过 issue,作者修好了。

BTW: 用那个 doggo 测 DoH 的确会出错报 error from nameserver 400 Bad Request

还有,如果用 JSON 方式查询 mosdns 建立的 DoH,返回空:

curl -H 'accept: application/dns-json' 'https://cl.1024.xyz/dns-query?name=example.com&type=A'

https://github.com/m13253/dns-over-https 建立的 DoH 可以正常返回结果。

rampageX avatar Sep 14 '21 13:09 rampageX

BTW: 用那个 doggo 测 DoH 的确会出错报 error from nameserver 400 Bad Request

这个确实是 mosdns 的 bug。会修。

如果用 JSON 方式查询 mosdns 建立的 DoH,返回空:

mosdns 只支持 rfc8484 还不支持 json。(因为 application/dns-json 没rfc标准,兼容性差的很.....一家可能一个样......


所以 @xsy2004,可能不是 mosdns 的问题。建议抓包看,或者盯 debug log

IrineSistiana avatar Sep 14 '21 14:09 IrineSistiana

甲骨文, 腾讯上海 VPS, Let’s Encrypt 证书.

选国内,国外两个服务器原因: 国外 853 端口被无条件阻断,而 iOS 目前无法使用非标准端口的 DoT 描述文件(或者说我也不知道怎么写),所以必须用国内 VPS 测 DoT; 国内 443 可用必须备案,那就只有用国外 VPS 测 DoH。

DoH 和 DoT 服务器 iOS 描述文件通过 https://dns.notjakob.com/tool.html 生成。

没有安卓设备, 在 iOS 14, Edge(基于 Chrome 的) 以及 Firefox 上测了 DoH, 在 iOS 14 上测了 DoT, 没发现什么问题。Edge 和 Firefox 都可以使用非标准端口的 DoH,地址后直接加端口即可,例如: https://cl.1024.xyz:4433/dns-query

目前版本 mosdns 建立的 DoH 和 DoT, 作为 dnsproxy, AdguardHome, https_dns_proxy, studdy, smartdns 的上游都没有问题,之前有问题的我也提过 issue,作者修好了。

BTW: 用那个 doggo 测 DoH 的确会出错报 error from nameserver 400 Bad Request

还有,如果用 JSON 方式查询 mosdns 建立的 DoH,返回空:

curl -H 'accept: application/dns-json' 'https://cl.1024.xyz/dns-query?name=example.com&type=A'

https://github.com/m13253/dns-over-https 建立的 DoH 可以正常返回结果。

安卓有不可描述的兼容性问题是肯定的,我昨天上生产环境试了,日800万请求扛得住,但是安卓的dot就是有问题,不知道为什么,很奇怪的是coredns的dot好像也有这种情况

linusxiong avatar Sep 14 '21 15:09 linusxiong

安卓有不可描述的兼容性问题是肯定的,我昨天上生产环境试了,日800万请求扛得住,但是安卓的dot就是有问题,不知道为什么,很奇怪的是coredns的dot好像也有这种情况

纯属瞎猜: 可以试试用 nginx stream proxy 套一层 tls 在 mosdns 的 tcp 服务器上。看看是不是 mosdns或者 go 的 tls 的问题。 听说安卓的证书验证玄学的很。如果套 nginx 还有问题,可能是证书。


IrineSistiana avatar Sep 15 '21 00:09 IrineSistiana

遇到类似问题来补充一下 在用安卓的adguard 默认是不能连上mosdns所建立的dot doh的 必须把相关中间证书导入系统之后才能连上

terrytw avatar Oct 03 '21 12:10 terrytw

遇到类似问题来补充一下 在用安卓的adguard 默认是不能连上mosdns所建立的dot doh的 必须把相关中间证书导入系统之后才能连上

貌似确实是证书的问题,mosdns的doh现在chrome可以用了,因为之前是不支持post请求来着,然后dot我换了其他的前置,暂时没使用自带的dot,如果是lets的证书,建议换掉,他们的根证书过期了,换了证书,有些系统不兼容,或者是使用了老版本的openssl,这些会导致不兼容。

linusxiong avatar Oct 03 '21 12:10 linusxiong

看来现在的情况是:

  • chrome 等浏览器能正常使用 mosdns 的DoH。
  • 但 Android 不能用 mosdns 的 DoT。
  • 应该不是 mosdns 的 DoT 实现方式的问题。其他软件都可以正常使用 mosdns 的 DoT 。
  • 可能和证书或者 Android 验证证书的方式有关。

IrineSistiana avatar Oct 04 '21 03:10 IrineSistiana

cat ~/.config/caddy/Caddyfile
{
        debug
        order webdav last
        preferred_chains {
                root_common_name "ISRG Root X1"
        }

}

caddy我配了个东西。 AdGuard当初DOT也用不了。 总之找到了这两个。 https://community.letsencrypt.org/t/android-devices-with-dot-configured-interaction-with-new-default-chain/161020 https://forum.xda-developers.com/t/all-devices-private-dns-broken-with-lets-encrypt-even-on-new-devices.4341355/ 报告安卓9有这问题,我自己用安卓10也有这问题。

daiaji avatar Feb 04 '22 16:02 daiaji

此文解释详细: https://ikarus.sg/lets-encrypt-dot-android/ 有一个解决办法是,在手机的证书里把DST 禁用

terrytw avatar Feb 05 '22 01:02 terrytw