Skip to content
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

[Bug?] 客户端配置中服务器地址若为域名,且 DNS 配置为使用加密服务器,就无法建立到服务器的连接 #455

Closed
IceCodeNew opened this issue Mar 14, 2021 · 20 comments

Comments

@IceCodeNew
Copy link

大概是从 68d315e 这个 commit 起,之前介绍的 隐藏配置 失效了。
我想要解决的问题是,当客户端配置里服务器地址写成域名的时候,dns 部分不能设置加密 DNS 服务器,否则会导致无法连接。
我想这个问题多半是因为预定义的加密 DNS 服务器有一个 bootstrap 的过程(拿到加密 DNS 服务器本身域名指向的 IP 地址),然后这个解析请求是要经过代理的,导致死循环。
为了解决这个问题,可以改为使用支持以 IP 作域名的加密 DNS 服务,或者设法预先把加密 DNS 服务器对应的 IP 写进配置。这两种办法都需要用到上述的隐藏配置。

在基于目前最新的 commit 46a51c8 编译的客户端上,使用隐藏配置的错误日志如下:

thread 'main' panicked at 'loading config ".\error.json", json parse error, Message { msg: "  --> 21:53\n   |\n21 |             { \"socket_addr\": \"1.0.0.2\", \"protocol\": \"tls\" }␊\n   |                                                     ^---\n   |\n   = expected boolean or null", location: Some(Location { line: 21, column: 53 }) }', bin/sslocal.rs:197:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

配置文件如下:

{
    "local_address": "127.0.0.1",
    "local_port": 888888888,

    "servers": [
        {
            "address": "example.com",
            "port": 66666666,
            "method": "chacha20-ietf-poly1305",
            "password": "example password",
            "plugin": "",
            "plugin_opts": ""
        }
    ],

    // https://security.cloudflare-dns.com/dns-query
    "dns": {
        "domain": "security.cloudflare-dns.com",
        "name_servers": [
            { "socket_addr": "1.1.1.2", "protocol": "https" },
            { "socket_addr": "1.0.0.2", "protocol": "tls" }
        ]
    }

    "mode": "tcp_only",

    "ipv6_first": false
}
@IceCodeNew
Copy link
Author

IceCodeNew commented Mar 14, 2021

最为简单的修复建议是扩展预定义的加密 DNS 服务,希望能考虑增加以下服务:

# Quad9-pri Secure w/ECS
https://9.9.9.11/dns-query
# Quad9-alt Secure w/ECS
https://149.112.112.11/dns-query
# Cloudflare-pri w/secure-filter
https://1.1.1.2/dns-query
# Cloudflare-alt w/secure-filter
https://1.0.0.2/dns-query

不过我个人是希望能恢复支持 dns 的隐藏配置啦。支持拿 IP 作 CN 的 TLS 证书很贵,所以会大大限制可用的加密 DNS 服务范围。而国内前段时间才对 Quad9, NextDNS 之类的加密 DNS 服务做过封锁,所以我担心这些扩展的预定义服务未来都会失效。
只有让 dns 配置支持 bootstrap 才是一劳永逸。

@zonyitoo
Copy link
Collaborator

zonyitoo commented Mar 15, 2021

The Quad9 and Cloudflare DNS servers that you mentioned could be set by cloudflare_tls, cloudflare_https, quad9_tls, right?

Did you realize that you have missed a , after dns:

    "dns": {
        "domain": "security.cloudflare-dns.com",
        "name_servers": [
            { "socket_addr": "1.1.1.2", "protocol": "https" },
            { "socket_addr": "1.0.0.2", "protocol": "tls" }
        ]
    },

@zonyitoo
Copy link
Collaborator

zonyitoo commented Mar 15, 2021

ref hickory-dns/hickory-dns#1413

Oh, you want EDNS support. Hmm. I think trust-dns haven't supported it yet.

@IceCodeNew
Copy link
Author

IceCodeNew commented Mar 15, 2021

The Quad9 and Cloudflare DNS servers that you mentioned could be set by cloudflare_tls, cloudflare_https, quad9_tls, right?

我以为这些预定义的加密 DNS 服务都是请求的 https://domain.name 而不是 https://ip_addr。所以造成了我所说的原始问题:

当客户端配置里服务器地址写成域名的时候,dns 部分不能设置加密 DNS 服务器,否则会导致无法连接。
我想这个问题多半是因为预定义的加密 DNS 服务器有一个 bootstrap 的过程(拿到加密 DNS 服务器本身域名指向的 IP 地址),然后这个解析请求是要经过代理的,导致死循环。

因此我才会用到隐藏配置,因为我看它的结构里同时指明了加密 DNS 服务器的 IP 地址,我期待它能解决这个问题。

但是遗憾的是我可能真的漏掉了一个逗号才导致配置无法生效……我试过以后再来回报。
新的错误出现了,参见下一条评论:

@IceCodeNew
Copy link
Author

错误日志:

thread 'main' panicked at 'loading config ".\test.json", json parse error, Message { msg: "data did not match any variant of untagged enum SSDnsConfig", location: Some(Location { line: 17, column: 12 }) }', bin/sslocal.rs:197:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

配置文件:

{

    "local_address": "127.0.0.1",
    "local_port": 55555555,

    "servers": [
        {
            "address": "example.com",
            "port": 666666666,
            "method": "chacha20-ietf-poly1305",
            "password": "*****************************************",
            "plugin": "",
            "plugin_opts": ""
        }
    ],

    "dns": {
        "domain": "security.cloudflare-dns.com",
        "name_servers": [
            { "socket_addr": "1.1.1.2", "protocol": "https" },
            { "socket_addr": "1.1.1.2", "protocol": "tls" },
            { "socket_addr": "1.0.0.2", "protocol": "https" },
            { "socket_addr": "1.0.0.2", "protocol": "tls" }
        ]
    },

    "mode": "tcp_only",

    "ipv6_first": false
}

@zonyitoo

This comment has been minimized.

@zonyitoo
Copy link
Collaborator

zonyitoo commented Mar 15, 2021

The following config should work:

    "dns": {
        "name_servers": [
            {
                "socket_addr": "1.1.1.2:443",
                "protocol": "https",
                "tls_dns_name": "security.cloudflare-dns.com"
            },
            {
                "socket_addr": "1.1.1.2:853",
                "protocol": "tls",
                "tls_dns_name": "security.cloudflare-dns.com"
            },
            {
                "socket_addr": "1.0.0.2:443",
                "protocol": "https",
                "tls_dns_name": "security.cloudflare-dns.com"
            },
            {
                "socket_addr": "1.0.0.2:853",
                "protocol": "tls",
                "tls_dns_name": "security.cloudflare-dns.com"
            }
        ]
    }

This is exactly the same as the way how trust-dns-resolver sets its pre-defined DNS servers, like google, quad9, ...

@IceCodeNew
Copy link
Author

问题解决了,感谢耐心回答!
其实我怀疑之前用预定义的字段其实也是通的,这次测试的时候也是,程序启动以后有足足半分钟的时间里都没能和 ssserver 建立连接。
然后等到我已经在吭哧吭哧写问题反馈的时候突然发现已经通了……

@IceCodeNew
Copy link
Author

清除 DNS 缓存以后测试了一下配置里用预定义的 cloudflare_https 字段,发现不能连接到服务器。

@zonyitoo
Copy link
Collaborator

I haven't test any of it before. :P . Try to use -vvv to see what exactly was happening.

@IceCodeNew
Copy link
Author

嗯,确定了,即便是使用隐藏配置以后也没能解决问题。如果系统中不存在 ss 服务器的域名解析缓存,就一直无法建立连接。
我尝试用 ACL 规则确保 DNS 解析不走代理,无果:

{
  "local_address": "127.0.0.1",
  "local_port": 555555555,

  "servers": [
    {
      "address": "example.com",
      "port": 6666666,
      "method": "chacha20-ietf-poly1305",
      "password": "*****************************",
      "plugin": "",
      "plugin_opts": ""
    },
    {
      "address": "v6ddns.example.com",
      "port": 6666666,
      "method": "chacha20-ietf-poly1305",
      "password": "*****************************",
      "plugin": "",
      "plugin_opts": ""
    },
    {
      "disabled": true,
      "address": "666.666.666.666",
      "port": 77777777777,
      "method": "chacha20-ietf-poly1305",
      "password": "*****************************",
      "plugin": "",
      "plugin_opts": ""
    }
  ],

  "dns": {
    "name_servers": [
      {
        "socket_addr": "1.1.1.2:443",
        "protocol": "https",
        "tls_dns_name": "security.cloudflare-dns.com"
      },
      {
        "socket_addr": "1.1.1.2:853",
        "protocol": "tls",
        "tls_dns_name": "security.cloudflare-dns.com"
      },
      {
        "socket_addr": "1.0.0.2:443",
        "protocol": "https",
        "tls_dns_name": "security.cloudflare-dns.com"
      },
      {
        "socket_addr": "1.0.0.2:853",
        "protocol": "tls",
        "tls_dns_name": "security.cloudflare-dns.com"
      }
    ]
  },

  "mode": "tcp_only",

  "ipv6_first": false
}

ACL:

[proxy_all]

[bypass_list]
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/24
192.0.2.0/24
192.88.99.0/24
192.168.0.0/16
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/4
240.0.0.0/4
255.255.255.255/32
::1/128
fc00::/7
fe80::/10

1.0.0.1/32
1.0.0.2/32
1.0.0.3/32
1.1.1.1/32
1.1.1.2/32
1.1.1.3/32
2606:4700:4700::1111/128
2606:4700:4700::1112/128
2606:4700:4700::1113/128
2606:4700:4700::1001/128
2606:4700:4700::1002/128
2606:4700:4700::1003/128

...(china_ip.list)

@IceCodeNew IceCodeNew reopened this Mar 15, 2021
@zonyitoo
Copy link
Collaborator

It doesn't related to ACL.

@IceCodeNew IceCodeNew changed the title [Feature Request] 关于 dns 模块的功能需求 [Bug?] 客户端配置中服务器地址若为域名,且 DNS 配置为使用加密服务器,就无法建立到服务器的连接 Mar 15, 2021
@zonyitoo
Copy link
Collaborator

It works perfectly with "dns": "cloudflare_https" on my laptop.

@IceCodeNew
Copy link
Author

IceCodeNew commented Mar 15, 2021

It works perfectly with "dns": "cloudflare_https" on my laptop.

感谢建议,我观察了 -vvv 后的程序输出,搞明白发生什么了。
1.1.1.2 在我的环境下不通,1.0.0.2 通。sslocal 一开始处理的几个请求都会超时和失败,因为 sslocal 在评估几个服务器的时候发现每个服务器地址都延迟测试超时。然后大概是第三第四个请求起,sslocal 改成向 1.0.0.2 建立连接了,之后对服务器的延迟测试就正常了。

我没有实际用 trust-dns 的经验,不知道有没有可能调整一下这里的逻辑,改成并发向配置的多个 DNS 服务器进行请求呢?

@zonyitoo
Copy link
Collaborator

Interesting.

@zonyitoo
Copy link
Collaborator

不知道有没有可能调整一下这里的逻辑,改成并发向配置的多个 DNS 服务器进行请求呢?

https://github.com/bluejekyll/trust-dns/blob/5f68b7d7b2af2a6c4dbb24895ea63e63c720dcde/crates/resolver/src/config.rs#L730-L734

Default to 2.

@IceCodeNew
Copy link
Author

不知道有没有可能调整一下这里的逻辑,改成并发向配置的多个 DNS 服务器进行请求呢?

bluejekyll/trust-dns@5f68b7d/crates/resolver/src/config.rs#L730-L734

Default to 2.

那说明我对错误日志的解读可能有些问题。但确实一开始我看到的消息都是说 TCP Connecting to 1.1.1.2:443,然后一堆延迟超时;接着是 TCP Connecting to 1.1.1.2:853,一堆延迟超时。最后才看到 TCP Connecting to 1.0.0.2:443 。

@IceCodeNew
Copy link
Author

总之从配置里删去 1.1.1.2 的条目后,客户端程序一上线就能和 ss 服务器建立连接了。
即使清除 DNS 缓存后再启动客户端程序,一开始的请求也不会出错。问题确认得到解决。

@zonyitoo
Copy link
Collaborator

That means it was trying to connect 1.1.1.2:443 and 1.1.1.2:853 simutaneously in the first batch.

@IceCodeNew
Copy link
Author

That means it was trying to connect 1.1.1.2:443 and 1.1.1.2:853 simutaneously in the first batch.

嗯,不过没有同时向 1.1.1.2 和 1.0.0.2 发起请求,在这个场景下就非常不好了。

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

2 participants