11 KiB
AdGuard DNS Development Setup
Contents
Initial setup
Development is supported on Linux and macOS (aka Darwin) systems.
-
Install Go 1.23 or later.
-
Call
make init
to set up the Git pre-commit hook. -
Call
make go-tools
to install analyzers and other tools into thebin
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 to1
to enable the race detector. The race detector is always enabled formake go-test
. -
VERBOSE
: Set to1
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 theOUT
andRACE
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
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 asmake 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.
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
:
mkdir test
cd test
Generate the TLS certificate and the key:
openssl req -nodes -new -x509 -keyout cert.key -out cert.crt
Also, generate TLS session tickets:
openssl rand 32 > ./tls_key_1
openssl rand 32 > ./tls_key_2
Step 2: prepare the DNSCrypt configuration
Install the dnscrypt
tool:
-
On macOS, install from Brew:
brew install ameshkov/tap/dnscrypt
-
On other unixes, such as Linux, download and install the latest release manually.
Then, generate the configuration:
dnscrypt generate -p testdns -o ./dnscrypt.yml
Step 3: prepare the configuration file
cd ../
cp -f config.dist.yaml config.yaml
Step 4: prepare the test data
echo '<html><body>General content ahead</body></html>' > ./test/block_page_general.html
echo '<html><body>Dangerous content ahead</body></html>' > ./test/block_page_sb.html
echo '<html><body>Adult content ahead</body></html>' > ./test/block_page_adult.html
echo '<html><body>Error 404</body></html>' > ./test/error_404.html
echo '<html><body>Error 500</body></html>' > ./test/error_500.html
Step 5: compile AdGuard DNS
make build
Step 6: prepare cache data and GeoIP
We'll use the test versions of the GeoIP databases here.
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
BILLSTAT_URL
CONSUL_ALLOWLIST_URL
GENERAL_SAFE_SEARCH_URL
LINKED_IP_TARGET_URL
NEW_REG_DOMAINS_URL
PROFILES_URL
SAFE_BROWSING_URL
YOUTUBE_SAFE_SEARCH_URL
See the external HTTP API documentation.
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 thedefault_dns
server configuration and replace it withbind_addresses
.
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
Step 8: test your instance
Plain DNS:
dnslookup example.org 127.0.0.1:5354
DoT:
VERIFY=0 dnslookup example.org tls://127.0.0.1:8853
DoH:
VERIFY=0 dnslookup example.org https://127.0.0.1:8443/dns-query
DoQ:
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 https://dnscrypt.info/stamps.
Note
The example below is for a test configuration that won't work for you.
dnslookup example.org sdns://AQcAAAAAAAAADjEyNy4wLjAuMTo1NDQzIAbKgP3dmXybr1DaKIFgKjsc8zSFX4rgT_hFgymSq6w1FzIuZG5zY3J5cHQtY2VydC50ZXN0ZG5z
Testing
The go-bench
and go-test
targets described earlier should generally be enough, but there are cases where additional testing setup is required. One such case is package bindtodevice
.
Testing SO_BINDTODEVICE
features
The SO_BINDTODEVICE
features require a Linux machine with a particular IP routing set up. In order to test these features on architectures other than Linux, this repository has a Dockerfile and a convenient script to use it, see scripts/test/bindtodevice.sh
.
A simple example:
-
If your Docker is installed in a way that doesn't require
sudo
to use it:sh ./scripts/test/bindtodevice.sh
-
Otherwise:
env USE_SUDO=1 sh ./scripts/test/bindtodevice.sh
This will build the image and open a shell within the container. The container environment is defined by scripts/test/bindtodevice.docker
, and has all utilities required to build the AdGuardDNS
binary and test it. The working directory is also shared with the container through the /test
directory inside it. The container also routes all IP connections to any address in the 172.17.0.0/16
subnet to the eth0
network interface. So, calling make go-test
or a similar command from within the container will actually test the SO_BINDTODEVICE
features:
go test --cover -v ./internal/bindtodevice/
If you want to open an additional terminal (for example to launch AdGuardDNS
in one and dig
it in the other), use docker exec
like this (you may need sudo
for that):
docker exec -i -t agdns_bindtodevice_test /bin/sh