1 /* 2 * This file is a part of DNSViz, a tool suite for DNS/DNSSEC monitoring, 3 * analysis, and visualization. 4 * Created by Casey Deccio (casey@deccio.net) 5 * 6 * Copyright 2016 VeriSign, Inc. 7 * 8 * DNSViz is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * DNSViz is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with DNSViz. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 package net.dnsviz.lookingglass; 23 24 import java.io.IOException; 25 import java.io.PrintWriter; 26 import java.io.StringWriter; 27 import java.net.InetAddress; 28 import java.net.UnknownHostException; 29 30 import org.json.JSONArray; 31 import org.json.JSONObject; 32 import org.json.JSONException; 33 34 import net.dnsviz.transport.DNSQueryTransportHandler; 35 import net.dnsviz.transport.DNSQueryTransportHandlerTCP; 36 import net.dnsviz.transport.DNSQueryTransportHandlerUDP; 37 import net.dnsviz.transport.DNSQueryTransportManager; 38 import net.dnsviz.util.Base64Decoder; 39 import net.dnsviz.util.Base64Encoder; 40 import net.dnsviz.websocket.WebSocketClient; 41 42 public class DNSLookingGlass { DNSLookingGlass()43 public DNSLookingGlass() { 44 } 45 getDNSQueryTransportHandlers(JSONObject obj)46 protected DNSQueryTransportHandler [] getDNSQueryTransportHandlers(JSONObject obj) throws JSONException, UnknownHostException { 47 DNSQueryTransportHandler [] ret; 48 JSONArray requests; 49 String [] vers; 50 String src; 51 int sport; 52 JSONObject reqObj; 53 54 vers = Double.toString(obj.getDouble("version")).split("\\."); 55 if (Integer.parseInt(vers[0]) != 1 || Integer.parseInt(vers[1]) > 0) { 56 throw new JSONException("Version of JSON input is invalid"); 57 } 58 59 requests = obj.getJSONArray("requests"); 60 ret = new DNSQueryTransportHandler [requests.length()]; 61 for (int i = 0; i < requests.length(); i++) { 62 reqObj = requests.getJSONObject(i); 63 if (reqObj.has("src")) { 64 src = reqObj.getString("src"); 65 } else { 66 src = null; 67 } 68 if (reqObj.has("sport")) { 69 sport = reqObj.getInt("sport"); 70 } else { 71 sport = 0; 72 } 73 ret[i] = getDNSQueryTransportHandler(reqObj.getString("req"), reqObj.getString("dst"), reqObj.getInt("dport"), src, sport, reqObj.getLong("timeout"), reqObj.getBoolean("tcp")); 74 } 75 return ret; 76 } 77 getEncodedResponses(DNSQueryTransportHandler [] qths)78 protected JSONObject getEncodedResponses(DNSQueryTransportHandler [] qths) { 79 JSONObject ret; 80 JSONObject response; 81 82 JSONArray responses = new JSONArray(); 83 for (int i = 0; i < qths.length; i++) { 84 response = new JSONObject(); 85 response.put("res", qths[i].getEncodedResponse()); 86 if (qths[i].getError() != null) { 87 response.put("err", qths[i].getError()); 88 if (qths[i].getErrno() != null) { 89 response.put("errno", qths[i].getErrno()); 90 } 91 } 92 if (qths[i].getSource() != null) { 93 response.put("src", qths[i].getSource().getHostAddress()); 94 } else { 95 response.put("src", (String)null); 96 } 97 if (qths[i].getSPort() != 0) { 98 response.put("sport", qths[i].getSPort()); 99 } else { 100 response.put("sport", (String)null); 101 } 102 response.put("time_elapsed", qths[i].timeElapsed()); 103 responses.put(response); 104 } 105 106 ret = new JSONObject(); 107 ret.put("version", "1.0"); 108 ret.put("responses", responses); 109 return ret; 110 } 111 getDNSQueryTransportHandler(String req, String dst, int dport, String src, int sport, long timeout, boolean tcp)112 public DNSQueryTransportHandler getDNSQueryTransportHandler(String req, String dst, int dport, String src, int sport, long timeout, boolean tcp) throws UnknownHostException { 113 Base64Decoder d = new Base64Decoder(); 114 byte [] byteReq = d.decode(req.getBytes()); 115 InetAddress srcAddr = null; 116 InetAddress dstAddr = null; 117 if (dst != null) { 118 dstAddr = InetAddress.getByName(dst); 119 } 120 if (src != null) { 121 srcAddr = InetAddress.getByName(src); 122 } 123 if (tcp) { 124 return new DNSQueryTransportHandlerTCP(byteReq, dstAddr, dport, srcAddr, sport, timeout); 125 } else { 126 return new DNSQueryTransportHandlerUDP(byteReq, dstAddr, dport, srcAddr, sport, timeout); 127 } 128 } 129 executeQueries(DNSQueryTransportHandler [] qths)130 public void executeQueries(DNSQueryTransportHandler [] qths) throws IOException { 131 int i; 132 DNSQueryTransportManager qtm = new DNSQueryTransportManager(); 133 qtm.query(qths); 134 for (i = 0; i < qths.length; i++) { 135 qths[i].finalize(); 136 } 137 } 138 interact(WebSocketClient ws)139 protected void interact(WebSocketClient ws) throws IOException { 140 byte [] input; 141 while ((input = ws.read()).length > 0) { 142 ws.write(run(new String(input)).getBytes()); 143 } 144 } 145 run(String json)146 public String run(String json) { 147 JSONObject ret; 148 try { 149 DNSQueryTransportHandler [] qths = getDNSQueryTransportHandlers(new JSONObject(json)); 150 executeQueries(qths); 151 return getEncodedResponses(qths).toString(); 152 } catch (Exception ex) { 153 ret = new JSONObject(); 154 ret.put("version", "1.0"); 155 ret.put("error", getErrorTrace(ex)); 156 return ret.toString(); 157 } 158 } 159 getErrorTrace(Exception err)160 protected String getErrorTrace(Exception err) { 161 StringWriter sw = new StringWriter(); 162 PrintWriter pw = new PrintWriter(sw); 163 err.printStackTrace(pw); 164 return sw.toString(); 165 } 166 main(String [] args)167 public static void main(String [] args) throws IOException { 168 WebSocketClient ws = new WebSocketClient(args[0], Integer.parseInt(args[1]), args[2], args[3]); 169 DNSLookingGlass lg = new DNSLookingGlass(); 170 lg.interact(ws); 171 } 172 } 173