init
This commit is contained in:
86
README.md
Normal file
86
README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
## DNSMasq divergence testbed
|
||||
|
||||
This project spins up one `dnsmasq` in front of four backend DNS servers (CoreDNS). Each backend returns a different A record for the same name so you can observe how `dnsmasq` behaves when upstreams disagree.
|
||||
|
||||
### Topology
|
||||
|
||||
- **dnsmasq**: listens on host UDP/TCP `5353`, forwards to backends at `192.168.243.11-14`
|
||||
- **backend1..backend4 (CoreDNS)**: each serves a different answer for `test.local`:
|
||||
- backend1 → `10.0.0.1`
|
||||
- backend2 → `10.0.0.2`
|
||||
- backend3 → `10.0.0.3`
|
||||
- backend4 → `10.0.0.4`
|
||||
|
||||
Custom bridge network: `192.168.243.0/24` with static IPs for reproducibility.
|
||||
|
||||
### Files
|
||||
|
||||
- `docker-compose.yaml`: services and fixed IP networking
|
||||
- `dnsmasq/dnsmasq.conf`: forwards to all four backends, logging enabled, caching enabled
|
||||
- `backends/backend*/Corefile`: CoreDNS configs returning distinct answers
|
||||
|
||||
### Run
|
||||
|
||||
```bash
|
||||
docker compose -f /home/akos/docker/dnsmasq/docker-compose.yaml up -d
|
||||
```
|
||||
|
||||
Wait a few seconds until all containers are healthy.
|
||||
|
||||
### Test from the host
|
||||
|
||||
Query via `dnsmasq` on port 5353:
|
||||
|
||||
```bash
|
||||
dig @127.0.0.1 -p 5353 test.local A +short
|
||||
```
|
||||
|
||||
Run several times to observe responses and `dnsmasq` caching behavior. You should see one of: `10.0.0.1`, `10.0.0.2`, `10.0.0.3`, `10.0.0.4`.
|
||||
|
||||
### Test from within the dnsmasq container (optional)
|
||||
|
||||
The `andyshinn/dnsmasq` image is Alpine-based; install `dig` temporarily:
|
||||
|
||||
```bash
|
||||
docker exec -it dnsmasq sh -c "apk add --no-cache bind-tools >/dev/null && dig @127.0.0.1 test.local A +short"
|
||||
```
|
||||
|
||||
### Inspect logs
|
||||
|
||||
`dnsmasq` query logging is enabled:
|
||||
|
||||
```bash
|
||||
docker logs -f dnsmasq
|
||||
```
|
||||
|
||||
### Adjusting behavior
|
||||
|
||||
To explore how `dnsmasq` handles disagreement:
|
||||
|
||||
- **Disable cache** (no stored answers): set `cache-size=0` in `dnsmasq/dnsmasq.conf`, then recreate the service.
|
||||
- **Force first-server order**: add `strict-order` to `dnsmasq/dnsmasq.conf` so servers are queried in listed order.
|
||||
- **Query all upstreams**: add `all-servers` so `dnsmasq` queries every upstream in parallel and picks the first reply.
|
||||
|
||||
Apply changes by recreating the service:
|
||||
|
||||
```bash
|
||||
docker compose -f /home/akos/docker/dnsmasq/docker-compose.yaml up -d --force-recreate dnsmasq
|
||||
```
|
||||
|
||||
### Resetting the cache
|
||||
|
||||
```bash
|
||||
docker restart dnsmasq
|
||||
```
|
||||
|
||||
### Clean up
|
||||
|
||||
```bash
|
||||
docker compose -f /home/akos/docker/dnsmasq/docker-compose.yaml down -v
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
- The backends are simple CoreDNS instances using the `hosts` plugin for `test.local`; unknown names forward to public resolvers.
|
||||
- The compose file exposes `53/udp` and `53/tcp` on host port `5353` to avoid clashing with any local resolver.
|
||||
|
||||
15
backends/backend1/Corefile
Normal file
15
backends/backend1/Corefile
Normal file
@@ -0,0 +1,15 @@
|
||||
. {
|
||||
errors
|
||||
log
|
||||
health
|
||||
ready
|
||||
hosts {
|
||||
10.0.0.1 test.local
|
||||
10.0.0.11 test
|
||||
10.0.0.2 test2.local
|
||||
10.0.0.22 test2
|
||||
fallthrough
|
||||
}
|
||||
forward . 8.8.8.8
|
||||
}
|
||||
|
||||
12
backends/backend2/Corefile
Normal file
12
backends/backend2/Corefile
Normal file
@@ -0,0 +1,12 @@
|
||||
. {
|
||||
errors
|
||||
log
|
||||
health
|
||||
ready
|
||||
hosts {
|
||||
10.0.0.2 test.local
|
||||
fallthrough
|
||||
}
|
||||
forward . 8.8.4.4
|
||||
}
|
||||
|
||||
12
backends/backend3/Corefile
Normal file
12
backends/backend3/Corefile
Normal file
@@ -0,0 +1,12 @@
|
||||
. {
|
||||
errors
|
||||
log
|
||||
health
|
||||
ready
|
||||
hosts {
|
||||
10.0.0.3 test.local
|
||||
fallthrough
|
||||
}
|
||||
forward . 1.1.1.1
|
||||
}
|
||||
|
||||
13
backends/backend4/Corefile
Normal file
13
backends/backend4/Corefile
Normal file
@@ -0,0 +1,13 @@
|
||||
. {
|
||||
errors
|
||||
log
|
||||
health
|
||||
ready
|
||||
hosts {
|
||||
10.0.0.4 test.local
|
||||
10.0.0.99 test9.frequentis.frq
|
||||
fallthrough
|
||||
}
|
||||
forward . 9.9.9.9
|
||||
}
|
||||
|
||||
37
dnsmasq/dnsmasq.conf
Normal file
37
dnsmasq/dnsmasq.conf
Normal file
@@ -0,0 +1,37 @@
|
||||
# Log queries for visibility
|
||||
log-queries
|
||||
log-facility=/var/log/dnsmasq.log
|
||||
|
||||
# Do not read /etc/resolv.conf
|
||||
no-resolv
|
||||
|
||||
# Upstream DNS servers (CoreDNS backends)
|
||||
server=192.168.243.11
|
||||
server=192.168.243.12
|
||||
server=192.168.243.13
|
||||
server=192.168.243.14
|
||||
|
||||
# Never forward plain names
|
||||
domain-needed
|
||||
|
||||
# Never forward reverse lookups for private ranges
|
||||
bogus-priv
|
||||
|
||||
# Listen on all interfaces
|
||||
interface=eth0
|
||||
bind-interfaces
|
||||
|
||||
# Set cache size (optional)
|
||||
cache-size=1000
|
||||
|
||||
|
||||
# Upstream selection behavior (uncomment one or both as needed)
|
||||
# Query upstreams strictly in the listed order (no randomization)
|
||||
#strict-order
|
||||
|
||||
# Query all upstream servers in parallel; use the first reply
|
||||
#all-servers
|
||||
|
||||
# Disable cache entirely (for testing)
|
||||
#cache-size=0
|
||||
|
||||
66
docker-compose.yaml
Normal file
66
docker-compose.yaml
Normal file
@@ -0,0 +1,66 @@
|
||||
services:
|
||||
dnsmasq:
|
||||
image: 4km3/dnsmasq:2.86-r0
|
||||
container_name: dnsmasq
|
||||
command: ["-k"]
|
||||
volumes:
|
||||
- ./dnsmasq/dnsmasq.conf:/etc/dnsmasq.conf:ro
|
||||
ports:
|
||||
- "5353:53/udp"
|
||||
- "5353:53/tcp"
|
||||
networks:
|
||||
dnsnet:
|
||||
ipv4_address: 192.168.243.10
|
||||
depends_on:
|
||||
- backend1
|
||||
- backend2
|
||||
- backend3
|
||||
- backend4
|
||||
|
||||
backend1:
|
||||
image: coredns/coredns:latest
|
||||
container_name: backend1
|
||||
command: ["-conf", "/etc/coredns/Corefile"]
|
||||
volumes:
|
||||
- ./backends/backend1/Corefile:/etc/coredns/Corefile:ro
|
||||
networks:
|
||||
dnsnet:
|
||||
ipv4_address: 192.168.243.11
|
||||
|
||||
backend2:
|
||||
image: coredns/coredns:latest
|
||||
container_name: backend2
|
||||
command: ["-conf", "/etc/coredns/Corefile"]
|
||||
volumes:
|
||||
- ./backends/backend2/Corefile:/etc/coredns/Corefile:ro
|
||||
networks:
|
||||
dnsnet:
|
||||
ipv4_address: 192.168.243.12
|
||||
|
||||
backend3:
|
||||
image: coredns/coredns:latest
|
||||
container_name: backend3
|
||||
command: ["-conf", "/etc/coredns/Corefile"]
|
||||
volumes:
|
||||
- ./backends/backend3/Corefile:/etc/coredns/Corefile:ro
|
||||
networks:
|
||||
dnsnet:
|
||||
ipv4_address: 192.168.243.13
|
||||
|
||||
backend4:
|
||||
image: coredns/coredns:latest
|
||||
container_name: backend4
|
||||
command: ["-conf", "/etc/coredns/Corefile"]
|
||||
volumes:
|
||||
- ./backends/backend4/Corefile:/etc/coredns/Corefile:ro
|
||||
networks:
|
||||
dnsnet:
|
||||
ipv4_address: 192.168.243.14
|
||||
|
||||
networks:
|
||||
dnsnet:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.243.0/24
|
||||
|
||||
Reference in New Issue
Block a user