【问题标题】:DNS over TLS - socket closedDNS over TLS - 套接字关闭
【发布时间】:2018-04-20 23:15:17
【问题描述】:

所以我的情况是,我正在代理 Android 设备上的所有用户 DNS 请求,并使用本地数据库解析它们或将它们转发到某个上游 DNS 服务器。最近我对基于 TLS 的 DNS 产生了更大的兴趣,我尝试在 rfc 之后实现它。
由于所有这些都是在移动设备上完成的,我不想为每个代理请求(总计约 6.7 kB)建立新的 TLS 连接,因为用户可能正在使用移动连接。
长话短说,RFC 声明如下:

[...] 这份文件 规定 TLS 的成功协商表明 双方保持空闲 DNS 连接打开的意愿, 独立于 TCP 上的 DNS 超时或其他建议 没有 TLS

我使用以下代码发送测试请求并评估结果(为了便于阅读而进行了删减)。:

private void tlsTest(){
    Socket s = establishConnection("1.1.1.1"); //Cloudflare in this example, reproducible for Quad9 as well
    DataInputStream in; //Created from the Socket
    DataOutputStream out; //Created from the Socket
    for (int i = 0; i < 20; i++) {
        byte[] data = dnsRequestTypeA("google.com");
        data = new DatagramPacket(data, 0, data.length, destination, 853).getData();
        out.writeShort(data.length);
        out.write(data);
        out.flush();
        int times = 0;
        while((message = readDNSMessage(in)) == null && ++times <= 10){
            Thread.sleep(200);
        }
        System.out.println("Response: " + message);
        Thread.sleep(2500);
    }
}

private DNSMessage readDNSMessage(DataInputStream in) throws IOException {
    byte[] lengthBytes = new byte[2];
    if(in.read(lengthBytes) < 0)return null;
    // Each DNS answer is preceded with an unsigned short giving the length of the packet
    int length = (lengthBytes[0]&0xFF) + ((lengthBytes[1] &0xFF) << 8);
    byte[] data = new byte[length];
    in.read(data);
    return new DNSMessage(data);
}

@NonNull
private Socket establishConnection(String host) throws IOException {
    Socket socket = getSocketFactory().createSocket(host, 853);
    socket.setKeepAlive(true);
    return socket;
}

这里的问题是,当短时间内没有请求(大约 1-2 秒我的测试)。
有没有人有这方面的经验?我做错了什么(也许它与 Android 用于 TLS 的 OpenSSL 实现有关)?显然,每隔一秒左右向服务器发送一次虚假请求是可行的,但这是一个非常棘手的解决方法。

【问题讨论】:

  • 你不能对已经被对端关闭的连接做任何事情。
  • 是的,我知道,我最初问是否有人有同样的经历,或者我是否做错了什么。但后来我了解到 dns-over-tls 服务器不符合关于 tls 会话保持活动状态的 RFC,并且在一次查询后简单地结束它。

标签: java android ssl dns


【解决方案1】:

经过一段时间的调试,我找不到任何直接的解决方案。在撰写本文时,我还没有使用过像 Wireshark 这样的工具来确定任何错误的实现,但我现在采用了不同的方式来处理这个问题;

我只是尽可能长时间地保持套接字处于活动状态(如果发送数据包失败,则在抛出异常之前最多重试 5 次)。此外,我缓存了所有查询,但由于这会严重影响性能/资源使用,我再次将其删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 2017-10-24
    相关资源
    最近更新 更多