GRoot is a static verification tool for DNS. GRoot consumes a collection of zone files along with a collection of user-defined properties and systematically checks if any input to DNS can lead to violation of the properties.
Installation | Property Verification · Available Properties | Citing GRoot · License (MIT)
📃 SIGCOMM 2020 -- GRoot: Proactive Verification of DNS Configurations
We have updated the paper to handle empty non-terminals as per the RFCs properly. The updated paper is available here. For more details, please check the GitHub issue #11.
Note: The docker image may consume ~ 1.2 GB of disk space.
We recommend running GRoot within a docker container, since they have negligible performance overhead. (See this report)
- Get
docker
for your OS. - Pull our docker image#:
docker pull dnsgt/groot
. - Run a container over the image:
docker run -it dnsgt/groot
.
This would give you abash
shell within groot directory.
# Alternatively, you could also build the Docker image locally:
docker build -t dnsgt/groot github.com/dns-groot/groot
Docker containers are isolated from the host system. Therefore, to run GRoot on zones files residing on the host system, you must first bind mount them while running the container:
docker run -v ~/data:/home/groot/groot/shared -it dnsgt/groot
The ~/data
on the host system would then be accessible within the container at ~/groot/shared
(with read+write permissions). The executable would be located at ~/groot/build/bin/
.
CLICK to reveal instructions
- Install
vcpkg
package manager to install dependecies. - Install the C++ libraries (64 bit versions) using:
- .\vcpkg.exe install boost-serialization:x64-windows boost-flyweight:x64-windows boost-dynamic-bitset:x64-windows boost-graph:x64-windows boost-accumulators:x64-windows docopt:x64-windows nlohmann-json:x64-windows spdlog:x64-windows
- .\vcpkg.exe integrate install
- Clone the repository (with
--recurse-submodules
) and open the solution (groot.sln) using Visual studio. Set the platform to x64 and mode to Release. - Configure the project properties to use ISO C++17 Standard (std:c++17) for C++ language standard.
- Set
groot
asSet as Startup Project
using the solution explorer in the Visual Studio. Build the project using visual studio to generate the executable. The executable would be located at~\groot\x64\Release\
.
- Follow the instructions mentioned in the
DockerFile
to natively install in Ubuntu 18.04 or later. - The executable would be located at
~/groot/build/bin/
.
Check for any violations of the input properties by invoking GRoot as:
For docker (Ubuntu):
~/groot$ ./build/bin/groot test/TestFiles/cc.il.us/zone_files --jobs=test/TestFiles/cc.il.us/jobs.json --output=output.json
For Windows:
~\groot> .\x64\Release\groot.exe test\TestFiles\cc.il.us\zone_files --jobs=test\TestFiles\cc.il.us\jobs.json --output=output.json
GRoot outputs any violations to the output.json
file.
User can log debugging messages to log.txt
using -l
and use -v
flag to log more detailed information. Use -s
flag to display the statistics of the zone files parsed and the execution time. To log zone file issues (missing glue records, multiple CNAME/DNAME records, duplicate records) separately in lint.json
, use the --lint
flag.
GRoot expects all the required zone files to be available in the input directory along with a special file metadata.json
. The metadata.json
file has to be created by the user and has to list the file name and the name server from which that zone file was obtained. If the zone files for a domain are obtained from multiple name servers, make sure to give the files a distinct name and fill the metadata accordingly. The user also has to provide the root (top) name servers for his domain in the metadata.json
.
CLICK to reveal an examplemetadata.json
{
"TopNameServers" : ["us.illinois.net."], //List of top name servers as strings
"ZoneFiles" : [
{
"FileName": "cc.il.us..txt", //cc.il.us. zone file from us.illinois.net. name server
"NameServer": "us.illinois.net."
},
{
"FileName": "richland.cc.il.us..txt", //richland.cc.il.us. zone file from ns1.richland.cc.il.us. name server
"NameServer": "ns1.richland.cc.il.us.",
"Origin": "richland.cc.il.us." // optional field to indicate the origin of the input zone file.
},
{
"FileName": "child.richland.cc.il.us..txt", //child.richland.cc.il.us. zone file from ns1.child.richland.cc.il.us. name server
"NameServer": "ns1.child.richland.cc.il.us."
},
{
"FileName": "child.richland.cc.il.us.-2.txt", //child.richland.cc.il.us. zone file from ns2.child.richland.cc.il.us. name server
"NameServer": "ns2.child.richland.cc.il.us." //for same domain (child.richland.cc.il.us.) as the last one but from a different name server
}
]
}
GRoot can currently verify properties shown below on the zone files and expects the input list in a json
file format. A job verifies properties on a domain and optionally on all its subdomains. The input json
file can have a list of jobs. GRoot verifies a default set of properties if no input file is provided.
CLICK to reveal an example job
[
{
"Domain": "cc.il.us." // Name of the domain to check
"SubDomain": true, //Whether to check the properties on all the subdomains also
"Properties":[
{
"PropertyName": "QueryRewrite",
"Value": ["illinois.net." , "cc.il.us."]
},
{
"PropertyName": "Rewrites",
"Value": 1
},
{
"PropertyName": "RewriteBlackholing"
}
]
}
]
Delegation Consistency
The parent and child zone files should have the same set of NS and glue A records for delegation.
Input json
format:
{
"PropertyName": "DelegationConsistency"
}
Finding all aliases
Lists all the input query names (aliases) that are eventually rewritten to one of the canonical names.Input json
format:
{
"PropertyName": "AllAliases",
"Value": ["gw1.richland.cc.il.us."] //List of canonical names
}
Lame Delegation
A name server that is authoritative for a zone should provide authoritative answers, otherwise it is a lame delegation.
Input json
format:
{
"PropertyName": "LameDelegation"
}
Nameserver Contact
The query should not contact any name server that is not a subdomain of the allowed set of domains for any execution in the DNS.
Input json
format:
{
"PropertyName": "NameserverContact",
"Value": ["edu.", "net.", "cc.il.us."] //List of allowed domain suffixes
}
Number of Hops
The query should not go through more than X number of hops for any execution in the DNS.
Input json
format:
{
"PropertyName": "Hops",
"Value": 2
}
Number of Rewrites
The query should not be rewritten more than X number of time for any execution in the DNS.
Input json
format:
{
"PropertyName": "Rewrites",
"Value": 3
}
Query Rewritting
The query should not be rewritten to any domain that is not a subdomain of the allowed set of domains for any execution in the DNS.
Input json
format:
{
"PropertyName": "QueryRewrite",
"Value": ["illinois.net." , "cc.il.us."] //List of allowed domain suffixes
}
Response Consistency
Different executions in DNS that might happen due to multiple name servers should result in the same answers.Input json
format:
{
"PropertyName": "ResponseConsistency",
"Types": ["A", "MX"] //Checks the consistency for only these types
}
Response Returned
Different executions in DNS that might happen due to multiple name servers should result in some non-empty response.Input json
format:
{
"PropertyName": "ResponseReturned",
"Types": ["CNAME", "A"] //Checks that some non-empty response is returned for these types
}
Response Value
Every execution in DNS should return an answer that matches the user input answer.Input json
format:
{
"PropertyName": "ResponseValue",
"Types": ["A"],
"Value": ["64.107.104.4"] //The expected response
}
Rewrite Blackholing
If the query is rewritten for any execution in the DNS, then the new query's domain name should have at least one resource record.
Input json
format:
{
"PropertyName": "RewriteBlackholing"
}
Structural Delegation Consistency
The parent and child zone files should have the same set of NS and glue A records for delegation irrespective of whether the name server hosting the child zone is reachable from the top name servers.
Input json
format:
{
"PropertyName": "StructuralDelegationConsistency"
}
Zero Time To Live
The query should not return a resource record with zero TTL for the given types.
Input json
format:
{
"PropertyName": "ZeroTTL",
"Types": ["A"]
}
DNAME Substitution Check
The query should not overflow the legal size for a domain name after DNAME rewrite. Records with CNAME target domain overflowing the legal size are ignored by the tool and are reported as issues during parsing itself.
Input json
format:
{
"PropertyName": "DNAMESubstitutionCheck"
}
GRoot, by default, checks for cyclic zone dependency and other loops while verifying any of the above properties.
@inproceedings{10.1145/3387514.3405871,
author = {Kakarla, Siva Kesava Reddy and Beckett, Ryan and Arzani, Behnaz and Millstein, Todd and Varghese, George},
title = {GRoot: Proactive Verification of DNS Configurations},
year = {2020},
isbn = {9781450379557},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/3387514.3405871},
doi = {10.1145/3387514.3405871},
booktitle = {Proceedings of the Annual Conference of the ACM Special Interest Group on Data Communication on the
Applications, Technologies, Architectures, and Protocols for Computer Communication},
pages = {310–328},
numpages = {19},
keywords = {Static Analysis, Verification, DNS, Formal Methods},
location = {Virtual Event, USA},
series = {SIGCOMM ’20}
}