DNS over TLS - 套接字已关闭

时间:2018-04-20 23:15:18

标签: java android ssl dns

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

  

[...]这份文件      规定TLS的成功谈判表明了      双方愿意保持闲置的DNS连接开放,      独立于DNS over TCP的超时或其他建议      没有TLS

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

B

这里的问题是,当没有短时间请求时,服务器似乎关闭连接(在尝试发送请求[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实现有关)?显然,只是通过虚拟请求每隔一秒左右向服务器发送垃圾邮件就可以了,但这将是一个非常糟糕的解决方法。

1 个答案:

答案 0 :(得分:0)

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

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