Commit d27844d4 authored by Ondrej Sury's avatar Ondrej Sury Committed by Robert Edmonds

Import Debian changes 0.6.4-1

dnsviz (0.6.4-1) unstable; urgency=medium

  * Imported upstream version 0.6.4

dnsviz (0.6.3-1) unstable; urgency=low

  * Imported upstream version 0.6.3
parents 5af563c5 1230534d
Metadata-Version: 1.1
Name: dnsviz
Version: 0.6.0
Version: 0.6.4
Summary: DNS analysis and visualization tool suite
Home-page: https://github.com/dnsviz/dnsviz/
Author: Casey Deccio
......@@ -19,6 +19,7 @@ Classifier: License :: OSI Approved :: GNU General Public License v2 or later (G
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet :: Name Service (DNS)
......
......@@ -12,10 +12,12 @@ powers the Web-based analysis available at http://dnsviz.net/
### Dependencies
* python (2.7.x) - http://www.python.org/
* python (2.6/2.7/3.4) - http://www.python.org/
python 2.7.x is required. python 3.4.x has also been successfully tested and
should work, as long as the other third-party dependencies support python 3.
python 2.6, 2.7, or 3.4 is required. For python 3.4 the other third-party
dependencies must also support python 3.4. Note that for python 2.6 the
importlib (https://pypi.python.org/pypi/importlib) and ordereddict
(https://pypi.python.org/pypi/ordereddict) packages are also required.
* dnspython (1.11.0 or later) - http://www.dnspython.org/
......@@ -35,14 +37,14 @@ powers the Web-based analysis available at http://dnsviz.net/
desired (and thus is highly recommended). The current code will display
warnings if the cryptographic elements cannot be verified.
Note that M2Crypto version 0.21.1 or later can be used to validate some
Note that M2Crypto version 0.21.1 or later can be used to validate some
DNSSEC algorithms, but support for the following DNSSEC algorithms is not
available in releases of M2Crypto prior to 0.24.0 without a patch:
3 (DSA-SHA1), 6 (DSA-NSEC3-SHA1), 12 (GOST R 34.10-2001),
available in releases of M2Crypto prior to 0.24.0 without a patch:
3 (DSA-SHA1), 6 (DSA-NSEC3-SHA1), 12 (GOST R 34.10-2001),
13 (ECDSA Curve P-256 with SHA-256), 14 (ECDSA Curve P-384 with SHA-384).
There are two patches included in the `contrib` directory that can be
applied to pre-0.24.0 versions to get this functionality:
`contrib/m2crypto-pre0.23.patch` or `contrib/m2crypto-0.23.patch`. For
`contrib/m2crypto-pre0.23.patch` or `contrib/m2crypto-0.23.patch`. For
example:
```
......@@ -57,9 +59,9 @@ powers the Web-based analysis available at http://dnsviz.net/
case, and `named(8)` does not need to be running.
### Build and Install
### Generic Build and Install
A typical build and install is performed with the following commands:
A generic build and install is performed with the following commands:
```
$ python setup.py build
......@@ -73,6 +75,47 @@ $ python setup.py --help
```
### RPM Build and Install (RHEL6 or RHEL7)
Install pygraphviz and M2Crypto, after installing their build dependencies.
```
$ sudo yum install python-setuptools gcc python-devel graphviz-devel openssl-devel
$ sudo easy_install pbr
$ sudo easy_install m2crypto pygraphviz
```
(RHEL6 only) Install the EPEL repository, and the necessary python libraries
from that repository.
```
$ sudo yum install epel-release
$ sudo yum install python-importlib python-ordereddict
```
Install dnspython.
```
$ sudo yum install python-dns
```
Install rpm-build tools to build the RPM.
```
$ sudo yum install rpm-build
```
Download the latest DNSViz release (denoted ${VERS}), extract the files, and
build using custom install script (to handle man pages).
```
$ curl -L -O https://github.com/dnsviz/dnsviz/archive/v${VERS}.tar.gz
$ tar -zxvf v${VERS}.tar.gz
$ cd dnsviz-${VERS}/
$ python setup.py bdist_rpm --install-script contrib/rpm-install.sh --distribution-name el${RHEL_VERS}
```
Install the newly created RPM file.
```
$ sudo rpm -iv dist/dnsviz-${VERS}-1.noarch.rpm
```
## Usage
DNSViz is invoked using the `dnsviz` command-line utility. `dnsviz` itself
......@@ -113,8 +156,8 @@ authoritative servers, rather than learning the servers through referrals from
the IANA root servers:
```
$ dnsviz probe -A \
-x example.com:a.iana-servers.org=199.43.132.53,a.iana-servers.org=2001:500:8c::53 \
-x example.com:b.iana-servers.org=199.43.133.53,b.iana-servers.org=2001:500:8d::53 \
-x example.com:a.iana-servers.org=199.43.132.53,a.iana-servers.org=[2001:500:8c::53] \
-x example.com:b.iana-servers.org=199.43.133.53,b.iana-servers.org=[2001:500:8d::53] \
-o example.com.json example.com
```
......@@ -135,7 +178,7 @@ Analyze multiple names in parallel (four threads) using explicit recursive
resolvers (replace *192.0.1.2* and *2001:db8::1* with legitimate resolver
addresses):
```
$ dnsviz probe -s 192.0.2.1,2001:db8::1 -t 4 -o multiple.json \
$ dnsviz probe -s 192.0.2.1,[2001:db8::1] -t 4 -o multiple.json \
example.com sandia.gov verisignlabs.com dnsviz.net
```
......
/*
* This file is a part of DNSViz, a tool suite for DNS/DNSSEC monitoring,
* analysis, and visualization.
* Created by Casey Deccio (casey@deccio.net)
*
* Copyright 2016 VeriSign, Inc.
*
* DNSViz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DNSViz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with DNSViz. If not, see <http://www.gnu.org/licenses/>.
*/
package net.dnsviz.applet;
import java.applet.Applet;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import net.dnsviz.transport.DNSQueryTransportHandler;
import net.dnsviz.util.DNSSettings;
import net.dnsviz.lookingglass.DNSLookingGlass;
public class DNSLookingGlassApplet extends Applet {
static final long serialVersionUID = 0;
private Exception err = null;
private DNSLookingGlass lg = null;
public DNSLookingGlassApplet() {
lg = new DNSLookingGlass();
}
public DNSQueryTransportHandler getDNSQueryTransportHandler(String req, String dst, int dport, String src, int sport, long timeout, boolean tcp) {
err = null;
try {
return lg.getDNSQueryTransportHandler(req, dst, dport, src, sport, timeout, tcp);
} catch (Exception ex) {
err = ex;
return null;
}
}
public void executeQueries(DNSQueryTransportHandler [] qths) {
err = null;
try {
lg.executeQueries(qths);
} catch (Exception ex) {
err = ex;
}
}
public InetAddress [] getDNSServers() {
return new DNSSettings().getDNSServers();
}
public boolean hasError() {
return err != null;
}
public Exception getError() {
return err;
}
public String getErrorTrace() {
if (err == null) {
return null;
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
err.printStackTrace(pw);
return sw.toString();
}
}
/*
* This file is a part of DNSViz, a tool suite for DNS/DNSSEC monitoring,
* analysis, and visualization.
* Created by Casey Deccio (casey@deccio.net)
*
* Copyright 2016 VeriSign, Inc.
*
* DNSViz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DNSViz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with DNSViz. If not, see <http://www.gnu.org/licenses/>.
*/
package net.dnsviz.lookingglass;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
import net.dnsviz.transport.DNSQueryTransportHandler;
import net.dnsviz.transport.DNSQueryTransportHandlerTCP;
import net.dnsviz.transport.DNSQueryTransportHandlerUDP;
import net.dnsviz.transport.DNSQueryTransportManager;
import net.dnsviz.util.Base64Decoder;
import net.dnsviz.util.Base64Encoder;
import net.dnsviz.websocket.WebSocketClient;
public class DNSLookingGlass {
public DNSLookingGlass() {
}
protected DNSQueryTransportHandler [] getDNSQueryTransportHandlers(JSONObject obj) throws JSONException, UnknownHostException {
DNSQueryTransportHandler [] ret;
JSONArray requests;
String [] vers;
String src;
int sport;
JSONObject reqObj;
vers = Double.toString(obj.getDouble("version")).split("\\.");
if (Integer.parseInt(vers[0]) != 1 || Integer.parseInt(vers[1]) > 0) {
throw new JSONException("Version of JSON input is invalid");
}
requests = obj.getJSONArray("requests");
ret = new DNSQueryTransportHandler [requests.length()];
for (int i = 0; i < requests.length(); i++) {
reqObj = requests.getJSONObject(i);
if (reqObj.has("src")) {
src = reqObj.getString("src");
} else {
src = null;
}
if (reqObj.has("sport")) {
sport = reqObj.getInt("sport");
} else {
sport = 0;
}
ret[i] = getDNSQueryTransportHandler(reqObj.getString("req"), reqObj.getString("dst"), reqObj.getInt("dport"), src, sport, reqObj.getLong("timeout"), reqObj.getBoolean("tcp"));
}
return ret;
}
protected JSONObject getEncodedResponses(DNSQueryTransportHandler [] qths) {
JSONObject ret;
JSONObject response;
JSONArray responses = new JSONArray();
for (int i = 0; i < qths.length; i++) {
response = new JSONObject();
response.put("res", qths[i].getEncodedResponse());
if (qths[i].getError() != null) {
response.put("err", qths[i].getError());
if (qths[i].getErrno() != null) {
response.put("errno", qths[i].getErrno());
}
}
if (qths[i].getSource() != null) {
response.put("src", qths[i].getSource().getHostAddress());
} else {
response.put("src", (String)null);
}
if (qths[i].getSPort() != 0) {
response.put("sport", qths[i].getSPort());
} else {
response.put("sport", (String)null);
}
response.put("time_elapsed", qths[i].timeElapsed());
responses.put(response);
}
ret = new JSONObject();
ret.put("version", "1.0");
ret.put("responses", responses);
return ret;
}
public DNSQueryTransportHandler getDNSQueryTransportHandler(String req, String dst, int dport, String src, int sport, long timeout, boolean tcp) throws UnknownHostException {
Base64Decoder d = new Base64Decoder();
byte [] byteReq = d.decode(req.getBytes());
InetAddress srcAddr = null;
InetAddress dstAddr = null;
if (dst != null) {
dstAddr = InetAddress.getByName(dst);
}
if (src != null) {
srcAddr = InetAddress.getByName(src);
}
if (tcp) {
return new DNSQueryTransportHandlerTCP(byteReq, dstAddr, dport, srcAddr, sport, timeout);
} else {
return new DNSQueryTransportHandlerUDP(byteReq, dstAddr, dport, srcAddr, sport, timeout);
}
}
public void executeQueries(DNSQueryTransportHandler [] qths) throws IOException {
int i;
DNSQueryTransportManager qtm = new DNSQueryTransportManager();
qtm.query(qths);
for (i = 0; i < qths.length; i++) {
qths[i].finalize();
}
}
protected void interact(WebSocketClient ws) throws IOException {
byte [] input;
while ((input = ws.read()).length > 0) {
ws.write(run(new String(input)).getBytes());
}
}
public String run(String json) {
JSONObject ret;
try {
DNSQueryTransportHandler [] qths = getDNSQueryTransportHandlers(new JSONObject(json));
executeQueries(qths);
return getEncodedResponses(qths).toString();
} catch (Exception ex) {
ret = new JSONObject();
ret.put("version", "1.0");
ret.put("error", getErrorTrace(ex));
return ret.toString();
}
}
protected String getErrorTrace(Exception err) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
err.printStackTrace(pw);
return sw.toString();
}
public static void main(String [] args) throws IOException {
WebSocketClient ws = new WebSocketClient(args[0], Integer.parseInt(args[1]), args[2], args[3]);
DNSLookingGlass lg = new DNSLookingGlass();
lg.interact(ws);
}
}
/*
* This file is a part of DNSViz, a tool suite for DNS/DNSSEC monitoring,
* analysis, and visualization.
* Created by Casey Deccio (casey@deccio.net)
*
* Copyright 2016 VeriSign, Inc.
*
* DNSViz is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DNSViz is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with DNSViz. If not, see <http://www.gnu.org/licenses/>.
*/
package net.dnsviz.transport;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.PortUnreachableException;
import java.net.BindException;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.NetworkChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Date;
import java.util.Random;
import java.net.UnknownHostException;
import net.dnsviz.util.Base64Encoder;
import net.dnsviz.util.Base64Decoder;
public abstract class DNSQueryTransportHandler {
private final static int MAX_PORT_BIND_ATTEMPTS = 10;
protected ByteBuffer req = null;
protected ByteBuffer res = null;
protected String err = null;
protected String errno = null;
protected InetAddress dst = null;
protected int dport = 0;
protected InetAddress src = null;
protected int sport = 0;
protected NetworkChannel channel = null;
protected long timeout = 0;
protected long expiration = 0;
protected long startTime = 0;
protected long endTime = 0;
protected DNSQueryTransportHandler(byte [] req, InetAddress dst, int dport, InetAddress src, int sport, long timeout) {
this.dst = dst;
this.dport = dport;
this.src = src;
this.sport = sport;
this.timeout = timeout;
initRequestBuffer(req);
}
public abstract int getInitialSelectionOp();
public abstract int getStartOfReqPayload();
public NetworkChannel getChannel() {
return channel;
}
public long getExpiration() {
return expiration;
}
public boolean hasError() {
return err != null;
}
public void setError(IOException ex) throws IOException {
if (ex instanceof SocketException) {
String m = ex.getMessage();
if (ex instanceof ConnectException) {
if (m.contains("timed out")) {
err = "TIMEOUT";
} else if (m.contains("refused")) {
err = "NETWORK_ERROR";
errno = Errno.getName(Errno.ECONNREFUSED);
}
} else if (ex instanceof BindException) {
if (m.contains("an't assign requested address")) {
err = "NETWORK_ERROR";
errno = Errno.getName(Errno.EADDRNOTAVAIL);
} else if (m.contains("ddress already in use")) {
err = "NETWORK_ERROR";
errno = Errno.getName(Errno.EADDRINUSE);
}
} else if (ex instanceof NoRouteToHostException) {
err = "NETWORK_ERROR";
errno = Errno.getName(Errno.EHOSTUNREACH);
} else if (ex instanceof PortUnreachableException) {
err = "NETWORK_ERROR";
errno = Errno.getName(Errno.ECONNREFUSED);
} else if (m.contains("ermission denied")) {
err = "NETWORK_ERROR";
errno = Errno.getName(Errno.EACCES);
}
}
/* if we weren't able to identify the error, then throw it */
if (err == null) {
throw ex;
}
}
public void setError(int code) {
err = "NETWORK_ERROR";
errno = Errno.getName(code);
}
public void setError(String name) {
err = name;
}
public String getError() {
return err;
}
public String getErrno() {
return errno;
}
public long timeElapsed() {
return endTime - startTime;
}
public long getSPort() {
return sport;
}
public InetAddress getSource() {
return src;
}
protected abstract void initRequestBuffer(byte [] req);
protected void initResponseBuffer() {
//TODO start more conservative and dynamically grow if more buffer space is
//needed
res = ByteBuffer.allocate(65536);
}
protected abstract void createSocket() throws IOException;
protected void configureSocket() throws IOException {
((SelectableChannel)channel).configureBlocking(false);
}
protected void bindSocket() throws IOException {
class bindAction implements PrivilegedExceptionAction<Object> {
private int port = 0;
public Object run() throws IOException {
channel.bind(new InetSocketAddress(src, port));
return null;
}
public void setPort(int port) {
this.port = port;
}
}
bindAction a = new bindAction();
if (sport > 0) {
a.setPort(sport);
try {
AccessController.doPrivileged(a);
} catch (PrivilegedActionException pae) {
Exception ex = pae.getException();
if (ex instanceof IOException) {
throw (IOException)ex;
} else {
throw (RuntimeException)ex;
}
}
} else {
Random r = new Random();
int i = 0;
while (true) {
// 65536 - 1024 = 64512
a.setPort(r.nextInt(64512) + 1024);
try {
AccessController.doPrivileged(a);
break;
} catch (PrivilegedActionException pae) {
Exception ex = pae.getException();
if (ex instanceof BindException) {
if (++i > MAX_PORT_BIND_ATTEMPTS || !ex.getMessage().contains("ddress already in use")) {
throw (BindException)ex;
}
} else if (ex instanceof IOException) {
throw (IOException)ex;
} else {
throw (RuntimeException)ex;
}
}
}
}
}
public void prepare() throws IOException {
initResponseBuffer();
try {
createSocket();
configureSocket();
bindSocket();
setStart();
connect();
} catch (IOException ex) {
setError(ex);
cleanup();
}
}
protected void setSocketInfo() {
InetSocketAddress addr;
class getAddrAction implements PrivilegedExceptionAction<InetSocketAddress> {
public InetSocketAddress run() throws IOException {
return (InetSocketAddress)channel.getLocalAddress();
}
}
getAddrAction a = new getAddrAction();
try {
addr = AccessController.doPrivileged(a);
} catch (PrivilegedActionException pae) {
Exception ex = pae.getException();
if (ex instanceof IOException) {
return;
} else {
throw (RuntimeException)ex;
}
}
src = addr.getAddress();
sport = addr.getPort();
}
protected void setStart() {
Date d = new Date();
expiration = d.getTime() + timeout;
startTime = d.getTime();
}
protected abstract void connect() throws IOException;
protected abstract boolean finishConnect() throws IOException;
public boolean doWrite() throws IOException {
class writeAction implements PrivilegedExceptionAction<Object> {
public Object run() throws IOException {
((WritableByteChannel)channel).write(req);
return null;
}
}
writeAction a = new writeAction();
try {
AccessController.doPrivileged(a);
} catch (PrivilegedActionException pae) {
Exception ex = pae.getException();
if (ex instanceof IOException) {
setError((IOException)ex);
cleanup();
return true;
} else {
throw (RuntimeException)ex;
}
}
if (!req.hasRemaining()) {
return true;
}
return false;