From b45ffed48ab59291f6e920c8ca670906bf740dc7 Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Fri, 9 Mar 2018 23:51:48 -0500 Subject: [PATCH] Set readTimeout for upstreams, cache no TTL for 5s --- .../java/com/moparisthebest/dns/DnsProxy.java | 29 ++++++++++++------- .../java/com/moparisthebest/dns/Util.java | 24 ++++++++++----- .../com/moparisthebest/dns/dto/Packet.java | 7 +++-- .../moparisthebest/dns/listen/TcpAsync.java | 11 +++++-- .../moparisthebest/dns/listen/UdpSync.java | 10 +++++-- .../dns/resolve/CacheResolver.java | 9 ++++++ .../dns/resolve/HttpResolver.java | 2 ++ .../dns/resolve/SocketResolver.java | 3 ++ 8 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/moparisthebest/dns/DnsProxy.java b/src/main/java/com/moparisthebest/dns/DnsProxy.java index 2ab7b77..72a84f2 100644 --- a/src/main/java/com/moparisthebest/dns/DnsProxy.java +++ b/src/main/java/com/moparisthebest/dns/DnsProxy.java @@ -5,11 +5,9 @@ import com.moparisthebest.dns.net.ParsedUrl; import com.moparisthebest.dns.resolve.CacheResolver; import com.moparisthebest.dns.resolve.QueueProcessingResolver; +import java.io.File; import java.io.FileInputStream; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; @@ -20,11 +18,20 @@ public class DnsProxy { public static void main(String[] args) throws Throwable { final Map config; - try (FileInputStream fis = new FileInputStream(args.length > 0 ? args[0] : "jdnsproxy.properties")) { - final Properties props = new Properties(); - props.load(fis); - @SuppressWarnings("unchecked") final Map configUnchecked = (Map) (Object) props; - config = configUnchecked; + final File propsFile = new File(args.length > 0 ? args[0] : "jdnsproxy.properties"); + if(propsFile.canRead()) { + try (FileInputStream fis = new FileInputStream(propsFile)) { + final Properties props = new Properties(); + props.load(fis); + @SuppressWarnings("unchecked") final Map configUnchecked = (Map) (Object) props; + config = configUnchecked; + } + } else { + if(args.length > 0) { + System.err.printf("Error: config file '%s' does not exist or can't be read%n", args[0]); + return; + } + config = Collections.emptyMap(); } System.out.println("config:" + config); @@ -44,8 +51,8 @@ public class DnsProxy { //queueProcessingResolvers.add(new SocketResolver(5, "socket1", SocketFactory.getDefault(), new InetSocketAddress("8.8.4.4", 53))); //queueProcessingResolvers.add(new HttpResolver(5, "http1", "https://dns.google.com/experimental?ct")); - final ExecutorService executor = ForkJoinPool.commonPool(); - final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(8); + final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(40); + final ExecutorService executor = scheduledExecutorService;//ForkJoinPool.commonPool(); final CacheResolver resolver = new CacheResolver(minTtl, staleResponseTtl, staleResponseTimeout, packetQueueLength, executor, scheduledExecutorService) .startQueueProcessingResolvers(queueProcessingResolvers); diff --git a/src/main/java/com/moparisthebest/dns/Util.java b/src/main/java/com/moparisthebest/dns/Util.java index 9e91554..eb5cd38 100644 --- a/src/main/java/com/moparisthebest/dns/Util.java +++ b/src/main/java/com/moparisthebest/dns/Util.java @@ -63,13 +63,19 @@ public class Util { /* // temp debug code - public static void debugPacket(final byte[] packet) { - System.out.println(Base64.getUrlEncoder().encodeToString(packet)); + public static void debugPacket(ByteBuffer packet) { + //if(true) return; + int position = packet.position(); + packet.position(0); + //System.out.println(Base64.getUrlEncoder().encodeToString(packet.array())); //System.out.println(new Packet(ByteBuffer.wrap(packet, 2, packet.length - 2).slice())); - System.out.println(new Packet(ByteBuffer.wrap(packet).slice())); - printPrettyHexBytes(ByteBuffer.wrap(packet)); - printPrettyChars(packet); - printPrettyDecimalUnsignedBytes(ByteBuffer.wrap(packet)); + //packet.mark(); + System.out.println(new Packet(packet.slice())); + //printPrettyHexBytes(packet); + //printPrettyChars(packet); + //printPrettyDecimalUnsignedBytes(packet); + packet.position(position); + //packet.reset(); } public static void printPrettyHexBytes(ByteBuffer bytes) { @@ -89,10 +95,12 @@ public class Util { System.out.println("+++++++++++++++++++++++++++++"); } - public static void printPrettyChars(final byte[] bytes) { + public static void printPrettyChars(ByteBuffer bytes) { + bytes = bytes.slice(); System.out.println("-----------------------------"); int count = 0; - for (final byte b : bytes) { + for (int x = 0; x < bytes.limit(); ++x) { + final byte b = bytes.get(x); System.out.printf("%02X(%c) ", b, (char) b); if (++count == 8) { System.out.println(); diff --git a/src/main/java/com/moparisthebest/dns/dto/Packet.java b/src/main/java/com/moparisthebest/dns/dto/Packet.java index b0f8ac8..454710d 100644 --- a/src/main/java/com/moparisthebest/dns/dto/Packet.java +++ b/src/main/java/com/moparisthebest/dns/dto/Packet.java @@ -212,6 +212,9 @@ public class Packet extends AbstractBufferWindow { lowestTtl = rrTtl; } } + if(lowestTtl == Integer.MAX_VALUE) + lowestTtl = 5; // todo: what is proper when no TTLs are available? + //System.out.println("lowestTtl: " + lowestTtl); return lowestTtl; } @@ -238,7 +241,7 @@ public class Packet extends AbstractBufferWindow { } public String getDohBase64() { - // todo: remove trailing equals + // todo: remove trailing equals, this goes outside limit... return Base64.getUrlEncoder().encodeToString(getBuf().array()); } @@ -269,7 +272,7 @@ public class Packet extends AbstractBufferWindow { ", start=" + getStart() + ", end=" + getEnd() + ", length=" + getLength() + - ", dohBase64=" + getDohBase64() + + //", dohBase64=" + getDohBase64() + '}'; } } diff --git a/src/main/java/com/moparisthebest/dns/listen/TcpAsync.java b/src/main/java/com/moparisthebest/dns/listen/TcpAsync.java index d5ed9aa..3f56ced 100644 --- a/src/main/java/com/moparisthebest/dns/listen/TcpAsync.java +++ b/src/main/java/com/moparisthebest/dns/listen/TcpAsync.java @@ -41,10 +41,15 @@ public class TcpAsync implements Listener { try { bufChan.buf.flip(); bufChan.setRequest(new Packet(bufChan.buf)); - //debugPacket(bufChan.getRequest().getBuf().array()); + //debugPacket(bufChan.getRequest().getBuf()); - resolver.resolveAsync(bufChan).thenAcceptAsync((bc) -> { - //debugPacket(bc.getResponse().getBuf().array()); + resolver.resolveAsync(bufChan).whenCompleteAsync((bc, t) -> { + //System.out.println("got completed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + if(t != null) { + t.printStackTrace(); + return; + } + //debugPacket(bc.getResponse().getBuf()); bc.tcpHead.clear(); bc.tcpHead.putShort((short) bc.getResponse().getBuf().capacity()); diff --git a/src/main/java/com/moparisthebest/dns/listen/UdpSync.java b/src/main/java/com/moparisthebest/dns/listen/UdpSync.java index b7a19e4..87c5f90 100644 --- a/src/main/java/com/moparisthebest/dns/listen/UdpSync.java +++ b/src/main/java/com/moparisthebest/dns/listen/UdpSync.java @@ -40,10 +40,14 @@ public class UdpSync implements Listener { final UdpRequestResponse requestResponse = new UdpRequestResponse(request.getSocketAddress(), new Packet(ByteBuffer.wrap(request.getData(), request.getOffset(), request.getLength()).slice())); //System.out.println(requestResponse); - //debugPacket(request.getData()); + //debugPacket(requestResponse.getRequest().getBuf()); - resolver.resolveAsync(requestResponse).thenAcceptAsync((urr) -> { - //debugPacket(bc.getResponse().getBuf().array()); + resolver.resolveAsync(requestResponse).whenCompleteAsync((urr, t) -> { + if(t != null) { + t.printStackTrace(); + return; + } + //debugPacket(urr.getResponse().getBuf()); //System.out.println("got response"); final byte[] response = urr.getResponse().getBuf().array(); diff --git a/src/main/java/com/moparisthebest/dns/resolve/CacheResolver.java b/src/main/java/com/moparisthebest/dns/resolve/CacheResolver.java index d42a94d..c96ad55 100644 --- a/src/main/java/com/moparisthebest/dns/resolve/CacheResolver.java +++ b/src/main/java/com/moparisthebest/dns/resolve/CacheResolver.java @@ -110,8 +110,17 @@ public class CacheResolver implements Resolver, AutoCloseable { return CompletableFuture.completedFuture(requestResponse); } } + //System.out.println("no cachedPacket, querying upstream!"); requestResponse.setRequestPacketKey(key); return requestAndCache(requestResponse); + /* + // todo: should not have to do this, some upstreams seem to eat stuff though, figure that out, I think readTimeout fixed this + final CompletableFuture request = requestAndCache(requestResponse); + final CompletableFuture abort = supplyAsyncOnTimeOut(scheduledExecutorService, 15000, TimeUnit.MILLISECONDS, () -> { + throw new RuntimeException("timed out cause upstream ate us"); + }); + return request.applyToEitherAsync(abort, s -> s); + */ } //boolean first = true; diff --git a/src/main/java/com/moparisthebest/dns/resolve/HttpResolver.java b/src/main/java/com/moparisthebest/dns/resolve/HttpResolver.java index cd6610b..15b0a30 100644 --- a/src/main/java/com/moparisthebest/dns/resolve/HttpResolver.java +++ b/src/main/java/com/moparisthebest/dns/resolve/HttpResolver.java @@ -12,6 +12,7 @@ import static com.moparisthebest.dns.Util.readPacket; public class HttpResolver extends AbstractQueueProcessingResolver { private final OpenConnection openConnection; private final int connectTimeout; + private final int readTimeout = 4000; interface OpenConnection { HttpURLConnection open() throws Exception; @@ -47,6 +48,7 @@ public class HttpResolver extends AbstractQueueProcessingResolver { final HttpURLConnection conn = openConnection.open(); conn.setConnectTimeout(connectTimeout); + conn.setReadTimeout(readTimeout); conn.setUseCaches(false); conn.setDoInput(true); conn.setDoOutput(true); diff --git a/src/main/java/com/moparisthebest/dns/resolve/SocketResolver.java b/src/main/java/com/moparisthebest/dns/resolve/SocketResolver.java index 5fdef92..4db1e1b 100644 --- a/src/main/java/com/moparisthebest/dns/resolve/SocketResolver.java +++ b/src/main/java/com/moparisthebest/dns/resolve/SocketResolver.java @@ -16,6 +16,7 @@ import static com.moparisthebest.dns.Util.writeTcpPacket; public class SocketResolver extends AbstractQueueProcessingResolver { private final OpenSocket openConnection; + private final int readTimeout = 4000; interface OpenSocket { Socket open() throws Exception; @@ -105,6 +106,8 @@ public class SocketResolver extends AbstractQueueProcessingResolver { OutputStream upOs = upstream.getOutputStream(); DataOutputStream upDos = new DataOutputStream(upOs)) { + upstream.setSoTimeout(readTimeout); + writeTcpPacket(request, upDos); upDos.flush();