# AdGuard DNS Development Setup ## Contents - [Initial setup](#init) - [Common Makefile macros and targets](#makefile) - [How to run AdGuard DNS](#run) - [Testing](#testing) ## Initial setup Development is supported on Linux and macOS (aka Darwin) systems. 1. Install Go 1.23 or later. 2. Call `make init` to set up the Git pre-commit hook. 3. Call `make go-tools` to install analyzers and other tools into the `bin` directory. ## Common Makefile macros and targets Most development tasks are done through the use of our Makefile. Please keep the Makefile POSIX-compliant and portable. ### Macros This is not an extensive list. See `../Makefile` and the scripts in the `../scripts/make/` directory. - `OUT`: The name of the binary to build. Default: `./AdGuardDNS`. - `RACE`: Set to `1` to enable the race detector. The race detector is always enabled for `make go-test`. - `VERBOSE`: Set to `1` to enable verbose mode. Default: `0`. ### Targets This is not an extensive list. See `../Makefile`. - `make init`: Set up the pre-commit hook that runs checks, linters, and tests. - `make go-build`: Build the binary. See also the `OUT` and `RACE` macros. - `make go-gen`: Regenerate the automatically generated Go files that need to be periodically updated. Those generated files are: - `../internal/backendpb/dns.pb.go` - `../internal/backendpb/dns_grpc.pb.go` - `../internal/ecscache/ecsblockilist_generate.go` - `../internal/geoip/asntops_generate.go` - `../internal/geoip/country_generate.go` - `../internal/profiledb/internal/filecachepb/filecache.pb.go` You'll need to [install `protoc`][protoc] for the last one. - `make go-lint`: Run Go checkers and static analysis. - `make go-test`: Run Go tests. - `make go-bench`: Run Go benchmarks. - `make go-tools`: Install the Go static analysis tools locally. - `make test`: Currently does the same thing as `make go-test` but is defined both because it's a common target and also in case code in another language appears in the future. - `make txt-lint`: Run plain text checkers. [protoc]: https://protobuf.dev/getting-started/gotutorial/#compiling-protocol-buffers ## How to run AdGuard DNS This is an example on how to run AdGuard DNS locally. ### Step 1: prepare the TLS certificate and the key Keeping the test files in the `test` directory since it's added to `.gitignore`: ```sh mkdir test cd test ``` Generate the TLS certificate and the key: ```sh openssl req -nodes -new -x509 -keyout cert.key -out cert.crt ``` Also, generate TLS session tickets: ```sh openssl rand 32 > ./tls_key_1 openssl rand 32 > ./tls_key_2 ``` ### Step 2: prepare the DNSCrypt configuration Install the [`dnscrypt`][dnsc] tool: - On macOS, install from Brew: ```sh brew install ameshkov/tap/dnscrypt ``` - On other unixes, such as Linux, [download][dnscdl] and install the latest release manually. Then, generate the configuration: ```sh dnscrypt generate -p testdns -o ./dnscrypt.yml ``` ### Step 3: prepare the configuration file ```sh cd ../ cp -f config.dist.yaml config.yaml ``` ### Step 4: prepare the test data ```sh echo '
General content ahead' > ./test/block_page_general.html echo 'Dangerous content ahead' > ./test/block_page_sb.html echo 'Adult content ahead' > ./test/block_page_adult.html echo 'Error 404' > ./test/error_404.html echo 'Error 500' > ./test/error_500.html ``` ### Step 5: compile AdGuard DNS ```sh make build ``` ### Step 6: prepare cache data and GeoIP We'll use the test versions of the GeoIP databases here. ```sh rm -f -r ./test/cache/ mkdir ./test/cache curl 'https://raw.githubusercontent.com/maxmind/MaxMind-DB/main/test-data/GeoIP2-Country-Test.mmdb' -o ./test/GeoIP2-Country-Test.mmdb curl 'https://raw.githubusercontent.com/maxmind/MaxMind-DB/main/test-data/GeoIP2-City-Test.mmdb' -o ./test/GeoIP2-City-Test.mmdb curl 'https://raw.githubusercontent.com/maxmind/MaxMind-DB/main/test-data/GeoIP2-ISP-Test.mmdb' -o ./test/GeoIP2-ISP-Test.mmdb ``` ### Step 7: run AdGuard DNS You'll need to supply the following: - [`ADULT_BLOCKING_URL`][env-ADULT_BLOCKING_URL] - [`BILLSTAT_URL`][env-BILLSTAT_URL] - [`CONSUL_ALLOWLIST_URL`][env-CONSUL_ALLOWLIST_URL] - [`GENERAL_SAFE_SEARCH_URL`][env-GENERAL_SAFE_SEARCH_URL] - [`LINKED_IP_TARGET_URL`][env-LINKED_IP_TARGET_URL] - [`NEW_REG_DOMAINS_URL`][env-NEW_REG_DOMAINS_URL] - [`PROFILES_URL`][env-PROFILES_URL] - [`SAFE_BROWSING_URL`][env-SAFE_BROWSING_URL] - [`YOUTUBE_SAFE_SEARCH_URL`][env-YOUTUBE_SAFE_SEARCH_URL] See the [external HTTP API documentation][externalhttp]. You may use `go run ./scripts/backend` to start mock GRPC server for `BACKEND_PROFILES_URL`, `BILLSTAT_URL`, `DNSCHECK_REMOTEKV_URL`, and `PROFILES_URL` endpoints. You may need to change the listen ports in `config.yaml` which are less than 1024 to some other ports. Otherwise, `sudo` or `doas` is required to run `AdGuardDNS`. Examples below are for the configuration with the following changes: - Plain DNS: `53` → `5354` - DoT: `853` → `8853` - DoH: `443` → `8443` - DoQ: `853` → `8853` You may also need to remove `probe_ipv6` if your network does not support IPv6. If you're using an OS different from Linux, you also need to make these changes: - Remove the `interface_listeners` section. - Remove `bind_interfaces` from the `default_dns` server configuration and replace it with `bind_addresses`. ```sh env \ ADULT_BLOCKING_URL='https://raw.githubusercontent.com/ameshkov/stuff/master/DNS/adult_blocking.txt' \ BILLSTAT_URL='grpc://localhost:6062' \ BLOCKED_SERVICE_INDEX_URL='https://adguardteam.github.io/HostlistsRegistry/assets/services.json' \ CONSUL_ALLOWLIST_URL='https://raw.githubusercontent.com/ameshkov/stuff/master/DNS/consul_allowlist.json' \ CONFIG_PATH='./config.yaml' \ FILTER_INDEX_URL='https://adguardteam.github.io/HostlistsRegistry/assets/filters.json' \ FILTER_CACHE_PATH='./test/cache' \ NEW_REG_DOMAINS_URL='https://raw.githubusercontent.com/ameshkov/stuff/master/DNS/nrd.txt' \ PROFILES_CACHE_PATH='./test/profilecache.pb' \ PROFILES_URL='grpc://localhost:6062' \ SAFE_BROWSING_URL='https://raw.githubusercontent.com/ameshkov/stuff/master/DNS/safe_browsing.txt' \ GENERAL_SAFE_SEARCH_URL='https://adguardteam.github.io/HostlistsRegistry/assets/engines_safe_search.txt' \ GEOIP_ASN_PATH='./test/GeoIP2-ISP-Test.mmdb' \ GEOIP_COUNTRY_PATH='./test/GeoIP2-City-Test.mmdb' \ QUERYLOG_PATH='./test/cache/querylog.jsonl' \ LINKED_IP_TARGET_URL='https://httpbin.agrd.workers.dev/anything' \ LISTEN_ADDR='127.0.0.1' \ LISTEN_PORT='8081' \ RULESTAT_URL='https://httpbin.agrd.workers.dev/post' \ SENTRY_DSN='https://1:1@localhost/1' \ VERBOSE='1' \ YOUTUBE_SAFE_SEARCH_URL='https://adguardteam.github.io/HostlistsRegistry/assets/youtube_safe_search.txt' \ ./AdGuardDNS ``` [env-ADULT_BLOCKING_URL]: environment.md#ADULT_BLOCKING_URL [env-BILLSTAT_URL]: environment.md#BILLSTAT_URL [env-CONSUL_ALLOWLIST_URL]: environment.md#CONSUL_ALLOWLIST_URL [env-GENERAL_SAFE_SEARCH_URL]: environment.md#GENERAL_SAFE_SEARCH_URL [env-LINKED_IP_TARGET_URL]: environment.md#LINKED_IP_TARGET_URL [env-NEW_REG_DOMAINS_URL]: environment.md#NEW_REG_DOMAINS_URL [env-PROFILES_URL]: environment.md#PROFILES_URL [env-SAFE_BROWSING_URL]: environment.md#SAFE_BROWSING_URL [env-YOUTUBE_SAFE_SEARCH_URL]: environment.md#YOUTUBE_SAFE_SEARCH_URL [externalhttp]: externalhttp.md ### Step 8: test your instance Plain DNS: ```sh dnslookup example.org 127.0.0.1:5354 ``` DoT: ```sh VERIFY=0 dnslookup example.org tls://127.0.0.1:8853 ``` DoH: ```sh VERIFY=0 dnslookup example.org https://127.0.0.1:8443/dns-query ``` DoQ: ```sh VERIFY=0 dnslookup example.org quic://127.0.0.1:8853 ``` Open `http://127.0.0.1:8081/metrics` to see the server's metrics. DNSCrypt is a bit trickier. You need to open `dnscrypt.yml` and use values from there to generate an SDNS stamp on