diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..33eff0f --- /dev/null +++ b/install.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# Function to check system requirements +check_requirements() { + # Check OS + if [[ "$(uname)" != "Linux" ]]; then + echo "Error: sanicdns is only compatible with Linux systems." + exit 1 + fi + + # Check architecture + if [[ "$(uname -m)" != "x86_64" ]]; then + echo "Error: sanicdns requires x86_64 architecture." + exit 1 + fi + + # Check kernel version + kernel_version=$(uname -r | cut -d. -f1,2) + if ! awk -v ver="$kernel_version" 'BEGIN{if (ver < 5.11) exit 1; exit 0}'; then + echo "Error: sanicdns requires kernel version 5.11 or higher." + exit 1 + fi + + # Check number of logical cores + cores=$(nproc) + if [[ $cores -lt 2 ]]; then + echo "Error: sanicdns requires at least 2 logical cores." + exit 1 + fi +} + +# Function to find and download the latest compatible release +find_and_download_release() { + echo "Searching for the latest compatible sanicdns release..." + local releases_url="https://api.github.com/repos/hadriansecurity/sanicdns/releases" + local releases=$(curl -s "$releases_url") + + local version + local url + + version=$(echo "$releases" | jq -r '.[] | select(.assets[].name == "sanicdns_af_xdp.tar.gz") | .tag_name' | head -n 1) + + if [ -z "$version" ]; then + echo "Error: Could not find a compatible release with sanicdns_af_xdp.tar.gz" + return 1 + fi + + url=$(echo "$releases" | jq -r ".[] | select(.tag_name == \"$version\") | .assets[].browser_download_url") + + echo "Attempting to download sanicdns version $version..." + if curl -s -L -o sanicdns_af_xdp.tar.gz "$url"; then + echo "Successfully downloaded sanicdns version $version" + echo "Installing sanicdns version $version" + return 0 + else + echo "Failed to download sanicdns version $version" + return 1 + fi +} + +# Function to install sanicdns +install_sanicdns() { + echo "Installing sanicdns..." + tar xzf sanicdns_af_xdp.tar.gz + sudo install sanicdns_af_xdp/sanicdns sanicdns_af_xdp/sanicdns_xdp.c.o /usr/local/bin + rm -rf sanicdns_af_xdp.tar.gz sanicdns_af_xdp +} + +# Function to install dpdk-hugepages +install_dpdk_hugepages() { + echo "Installing dpdk-hugepages..." + wget -q https://raw.githubusercontent.com/DPDK/dpdk/main/usertools/dpdk-hugepages.py + sudo install dpdk-hugepages.py /usr/local/bin + rm dpdk-hugepages.py +} + +# Main installation function +install() { + if find_and_download_release; then + install_sanicdns + install_dpdk_hugepages + echo "sanicdns installation complete!" + else + echo "Installation failed." + exit 1 + fi +} + +# Run checks +check_requirements + +# If all checks pass, run installation +install diff --git a/readme.md b/readme.md index c7cb008..27164eb 100644 --- a/readme.md +++ b/readme.md @@ -29,35 +29,60 @@ To use SanicDNS you'll need: ## Installing -TODO: Add link to docs -This section provides instructions for installing precompiled AF_XDP binaries to get started quickly. For instructions on compiling from source, see the docs. +This section provides instructions for installing precompiled AF_XDP binaries to get started quickly. -1. Download the latest `sanicdns_af_xdp.tar.gz` release -2. Unpack the archive - ```bash - tar xzf sanicdns_af_xdp.tar.gz - ```` -3. Install binaries - ```bash - sudo install sanicdns_af_xdp/sanicdns sanicdns_af_xdp/sanicdns_xdp.c.o /usr/local/bin - ```` -4. Install dpdk-hugepages - ```bash - wget https://raw.githubusercontent.com/DPDK/dpdk/main/usertools/dpdk-hugepages.py - sudo install dpdk-hugepages.py /usr/local/bin - ```` +```bash +curl -sSL https://raw.githubusercontent.com/hadriansecurity/sanicdns/main/install.sh | sudo bash +``` ## Getting started -TODO: Add link to docs -1. Setup 1Gb of hugepages (see the docs for how many hugepages are necessary) +1. Setup 1Gb of hugepages (Allocate more when out of memory) ```bash - dpdk-hugepages.py --setup 1G + sudo dpdk-hugepages.py --setup 1G ```` 2. Get a wordlist to use - For getting started you can use the `majestic_million.txt` file in the SanicDNS Repo TODO: add link + For getting started you can use the `majestic_million.txt` file in the SanicDNS Repo + ```bash + wget https://raw.githubusercontent.com/hadriansecurity/sanicdns/main/majestic_million.txt + ``` 3. Run the tool ```bash - sudo sanicdns -i majestic_million.txt -l log.txt -r 2000 --resolvers 1.1.1.1,1.0.0.1 + sudo sanicdns -i majestic_million.txt -l log.txt -r 2000 -c 10000 --resolvers 1.1.1.1,1.0.0.1 ```` +## Command line flags +``` + -h, --help print this help screen + --version print the version and exit + --headless run in headless mode (no terminal UI) + -w, --cores number of cores to use (default: 2) + -r, --rate scan rate in [packets per second] (default: 1000) + -c, --num-concurrent max number of concurrent DNS requests + (default: rate/5) + -t, --timeout timeout [ms] (default: 15'000) + --num-retries number of retries (default: 10) + -g, --gateway-ip IP address of gateway + -s, --static-ip own (static) IP address + -m, --gateway-mac gateway mac, ARP will be used if no MAC is specified + -d, --device-name Device name (example: 0000:2e:00:0) + -i, --input-file Path of input file with domains + -x, --xdp-path Path to XDP program + --resolvers Resolvers (default 1.1.1.1,1.0.0.1), either: + 1. Comma-seperated list of IP's + 2. File with a resolver specified on each line + --rcodes Only output results with these DNS return codes + Example: --rcodes R_NOERROR,R_SERVFAIL + --prefix Prefix to add to each line of the input + --postfix Postfix to add to each line of the input + -l, --log-path Log file path, logging will be enabled when a log path + is set + -o, --output-path output path (default: output.txt) + --output-raw output raw DNS packets in hex (from DNS header to end + of packet) + --no-huge Don't use huge pages + --debug Print debug information + -q, --q-type Question type + (T_A, T_NS, T_CNAME, T_DNAME, T_SOA, T_PTR, T_MX, T_- + TXT, T_AAAA, T_OPT) +``` diff --git a/src/main.cpp b/src/main.cpp index 943e4d1..dfb30fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -180,10 +180,9 @@ std::optional InitConfigFromArgs(int argc, char** argv) { auto& resolvers = parser["resolvers"] - .description("Resolvers (default 1.1.1.1,1.0.0.1), either:\n 1. Comma-seperated " + .description("Resolvers, either:\n 1. Comma-seperated " "list of IP's\n 2. File with a resolver specified on each line") - .type(po::string) - .fallback("1.1.1.1,1.0.0.1"); + .type(po::string); auto& rcodes_filters = parser["rcodes"] .description("Only output results with these DNS return codes\n" @@ -304,6 +303,10 @@ std::optional InitConfigFromArgs(int argc, char** argv) { config.xdp_path = xdp_path.get().string; #endif + if (!resolvers.was_set()) { + fmt::print("{} provide resolvers\n", error_str); + return std::nullopt; + } config.resolvers = ({ tl::expected res = ParseResolvers(resolvers.get().string); if (!res) {