DnsDist · Nginx · DoH · DoT · UDP
SniDust proxies your DNS requests and spoofs your origin IP, so geo-restricted services (Zattoo, Netflix, SRF.ch, Yallo, Hulu, Amazon Prime, …) see the IP of your server instead of yours.
10.111.123.7 → 10.111.123.8DNS question for hulu.com10.111.123.8 → 10.111.123.7answer: hulu.com ⇒ 10.111.123.810.111.123.7 → 10.111.123.8HTTPS request to hulu.com10.111.123.8 → 104.98.130.197proxied request to the CDN edge104.98.130.197 → 10.111.123.8video stream back10.111.123.8 → 10.111.123.7stream on to the clientOnly clients on the ACL may use the proxy. IPs and DynDNS
domains from ALLOWED_CLIENTS are resolved to IPs and written to
/etc/dnsdist/allowedClients.acl; a cron re-resolves DynDNS names every 15 min.
Queries whose suffix matches one of the 11 lists in
/etc/snidust/domains.d (55 entries) are tagged; everything else is passed through untouched.
Tagged queries never reach the real CDN.
SpoofAction(EXTERNAL_IP) rewrites the record itself, so the client is told that
hulu.com resolves to the server — and opens its video connection there.
nginx proxies that connection to the real host
(proxy_pass http://$host$request_uri), resolving the name from the server's own
view — the geo-correct CDN edge. The stream is piped back to the client.
Optimised for these services; the shipped lists cover their CDN and API domains.
ch + wemfbox + akamai variants
nflx* + netflix.de
srgssr.ch, cdn.rts.ch
yallo.tv, zahs.tv
hulu.com, huluim.com
amazonvideo.com, amazon.co.uk
hbogo.com, hbonow.com
molotov.tv, y3o.tv
youtubei, googlevideo, youtu.be
10 akamai domains
| Blocklist file | Entries |
|---|---|
00-debug.lst | 1 |
01-cdn_akamai.lst | 11 |
02-amazon.lst | 3 |
03-hbo.lst | 3 |
04-hulu.lst | 2 |
05-netflix.lst | 11 |
06-molotov_tv.lst | 2 |
07-srf_ch.lst | 4 |
09-zattoo.lst | 9 |
10-yallo.lst | 2 |
11-youtube.lst | 7 |
| Total | 55 |
curl https://ifconfig.co
Run this on the device that will use the proxy. DynDNS domains work as well.
curl https://ifconfig.co
Run this on the VPS that hosts SniDust. This is the IP that gets spoofed.
docker run -d \ --name snidust \ -e ALLOWED_CLIENTS="127.0.0.1, 10.111.123.7, myDynDNSDomain.no-ip.com" \ -e EXTERNAL_IP=10.111.123.8 \ -p 443:8443 -p 80:8080 -p 53:5300/udp \ ghcr.io/seji64/snidust:latest
Prebuilt for linux/amd64, linux/arm64 and linux/arm/v7 — no local build needed.
docker logs snidust
You should see the upstreams (dns.google, cloudflare-dns) marked up and the ACL loaded.
sudo resolvctl set nameservers 10.111.123.8 # macOS # or set DoH/DoT manually: https://10.111.123.8/dns-query
Set the DNS server of the device (or the whole network) to the public IP of your server. Geo-location hidden.
version: '3.3'
services:
snidust:
container_name: snidust
image: 'ghcr.io/seji64/snidust:latest'
environment:
- TZ=Europe/Berlin
- 'ALLOWED_CLIENTS=127.0.0.1, 10.111.123.7, myDynDNSDomain.no-ip.com'
- 'EXTERNAL_IP=10.111.123.8'
- SPOOF_ALL_DOMAINS=false
# - 'DYNDNS_CRON_SCHEDULE=*/1 * * * *'
ports:
- 443:8443
- 80:8080
- 53:5300/udp
| Port | Protocol | Purpose |
|---|---|---|
5300/udp | DNS | Classic DNS endpoint — map to 53:5300/udp. |
8080/tcp | DoH (plain) | Nginx reverse proxy for DNS-over-HTTPS, map to 80:8080. |
8443/tcp | DoH / DoT (TLS) | Nginx stream module with ssl_preread, map to 443:8443. |
8530/tcp | DoH / DoT (TLS) | Native dnsdist TLS endpoint, only with DNSDIST_ENABLE_DOT=true. |
8083/tcp | HTTP | dnsdist web interface, bound to 127.0.0.1; needs DNSDIST_ENABLE_WEBSERVER=true and -p 8083:8083. |
| Variable | Default | Description |
|---|---|---|
ALLOWED_CLIENTS | 127.0.0.1 | Comma-separated IPs or DynDNS domains allowed to use the proxy. |
ALLOWED_CLIENTS_FILE | (empty) | Path to an ACL file; allows reloading without a restart. |
EXTERNAL_IP | (empty) | Public server IP used for spoofing. |
SPOOF_ALL_DOMAINS | false | Spoof every query, regardless of the blocklists (not recommended). |
INSTALL_DEFAULT_DOMAINS | true | Install the domain lists shipped in the repo. |
DYNDNS_CRON_SCHEDULE | */15 * * * * | Cron schedule for re-resolving DynDNS domains. |
| Variable | Default | Description |
|---|---|---|
DNSDIST_RATE_LIMIT_DISABLE | false | Disable rate limiting entirely. |
DNSDIST_RATE_LIMIT_WARN | 800 | Warn above this many queries per second. |
DNSDIST_RATE_LIMIT_BLOCK | 1000 | Block above this many queries per second. |
DNSDIST_RATE_LIMIT_BLOCK_DURATION | 360 | Seconds a client stays blocked. |
DNSDIST_RATE_LIMIT_EVAL_WINDOW | 60 | Evaluation window in seconds. |
DNSDIST_PACKAGE_CACHE_ENABLED | false | Enable packet cache to cut latency. |
DNSDIST_PACKAGE_CACHE_SIZE | 50000 | Maximum entries in the packet cache. |
DNSDIST_UPSTREAM_POOL_NAME | upstream | Pool name; change when using custom upstreams. |
DNSDIST_UPSTREAM_CHECK_INTERVAL | 10 | Seconds between upstream health checks. |
DNSDIST_ENABLE_DOT | false | Enable native DoT/DoH on port 8530. |
DNSDIST_DOT_CERT_TYPE | self-signed | Certificate type for DoT (self-signed / ACME). |
DNSDIST_ENABLE_WEBSERVER | false | Enable the dnsdist web UI on 127.0.0.1:8083. |
DNSDIST_DEBUG | false | Log every query to /tmp/dnsdist.log. |
See docker-compose.dot.yml and
docker-compose.acme.sh-dot.yml in the repo for a self-signed or an ACME (real certificate) setup.
Create 99-customUpstream.conf with
newServer({address="…", pool="customUpstream"}), mount it into
/etc/dnsdist/conf.d/ and set DNSDIST_UPSTREAM_POOL_NAME=customUpstream.
Add 99-custom.lst and mount it into
/etc/snidust/domains.d/99-custom.lst:ro — one domain per line.
Mount your own file at /etc/nginx/nginx.conf:ro
for reverse-proxy or performance tuning.
SniDust answers specific magic queries and re-reads its configuration in place — no restart, no downtime.
dig @10.111.123.8 reload.acl.snidust.local # re-read the ACL dig @10.111.123.8 reload.domainlist.snidust.local # re-read the blocklists dig @10.111.123.8 reload.certs.snidust.local # re-read the DoT certificates
Port 53 already in use. On Linux, systemd-resolved (or Pi-hole)
usually occupies port 53. Free it before mapping 53:5300/udp — see the guide linked from the README.
Nothing is spoofed? Check the domain is really covered by a list
(docker exec snidust cat /etc/snidust/domains.d/*.lst), that your client IP is in the ACL
(docker exec snidust cat /etc/dnsdist/allowedClients.acl), and set DNSDIST_DEBUG=true
to watch queries in /tmp/dnsdist.log.
Requirements: a VPS or root server with Docker, a public IP that is not itself geo-blocked,
and a client whose DNS you can change. The image is Alpine-based, runs as snidust and is supervised by tini.
Built on dnsdist.org, nginx.org, wilmaa-proxy, unblock-proxy.sh and netflix-proxy.
Source: github.com/Seji64/SniDust · Image: ghcr.io/seji64/snidust:latest