Files
darkproxy/README.md
T
auto-ci 958947b334
Configuration validation / lint (push) Has been cancelled
Configuration validation / smoke (push) Has been cancelled
feat(dns): add local namecoindns service and route .bit locally
2026-03-01 22:15:30 -05:00

9.4 KiB
Raw Blame History

Welcome to darkproxy...

Production hardening defaults

The stack now uses safer defaults for production:

  • Sensitive passwords are loaded from Docker secrets instead of inline values.
  • Admin/monitoring ports are bound to 127.0.0.1 on the host.
  • 3proxy now requires authentication (auth strong).

Before starting in production, set these secret files:

printf 'proxyuser:CL:YOUR_STRONG_PROXY_PASSWORD\n' > secrets/3proxy_users.txt
printf 'YOUR_STRONG_PIHOLE_PASSWORD\n' > secrets/pihole_webpassword.txt
printf 'YOUR_STRONG_GRAFANA_PASSWORD\n' > secrets/grafana_admin_password.txt

SOCKS clients must now authenticate to 3proxy with credentials from secrets/3proxy_users.txt.

This container runs the following vontainers in the stack.

3proxy-eagle - Socks5/http proxy

  • DNS
    • pihole - ad blocking and metrics
    • PopuraDNS - non-recursive DNS forwards requests to the following: Alfis - Blockchain based yggdrasil resolver EmerCoin - Resolves EMC domains UnBound - Recursive DNS for Clearnet domains
    • .onion and .i2p domain names are now resolved via the stack (see DNS section below)
  • I2PD over Yggdrasil container (container_name: darki2p)
    • Yggdrasil IP network stack
    • Socks5 server for I2P
  • Tor container

The system offers a DNS that resolves many darknet and clearnet IP's. The stack now handles:

  • *.onion forwarded to Tor's DNSPort running in the darktor container at 10.5.0.7:9053.
  • *.i2p served by the built-in DNS server inside the darki2p container (10.5.0.2:53) which is enabled via the [dns] section in i2pd.conf.

You can query these directly from any container on the darkproxy network, for example:

# Tor .onion domains
docker run --rm --network darkproxy infoblox/dig dig @10.5.0.4 facebookcorewwwi.onion

# I2P .i2p domains
docker run --rm --network darkproxy infoblox/dig dig @10.5.0.4 stats.i2p

# Ethereum Name Service (.eth) via local ensdns service
docker run --rm --network darkproxy infoblox/dig dig @10.5.0.4 vitalik.eth

# ENS address/content hash records (TXT)
docker run --rm --network darkproxy infoblox/dig dig @10.5.0.4 TXT vitalik.eth

# Other supported TLDs: .bit, .alt, .loki, .zil, .web3, .exit, .onion4, .onion6
docker run --rm --network darkproxy infoblox/dig dig @10.5.0.4 example.bit

Note: the CoreDNS service at 10.5.0.4 no longer enforces an ACL for the root zone it will happily perform recursive lookups for any client. Queries from your host should now work without the “refused to do a recursive query” error. If you later reintroduce an ACL, update this note accordingly.

Host-side quick tests (no extra images)

Run DNS queries from your host by executing dig in the existing darkpihole container:

docker exec darkpihole dig @10.5.0.4 TXT vitalik.eth +short
docker exec darkpihole dig @10.5.0.4 A vitalik.eth +short

Expected behavior:

  • TXT includes address= and (if present) contenthash=.
  • A returns a CNAME fallback like <name>.eth.limo..

Supported TLDs and resolvers

The stack now provides DNS resolution for a comprehensive set of alternative TLDs:

TLD Resolver Purpose
.onion, .exit, .onion4, .onion6 Tor DNSPort (10.5.0.7:9053) Tor hidden services
.i2p i2pd DNS (10.5.0.2:53) I2P eepsite names
.eth ensdns (10.5.0.11) via CoreDNS Ethereum Name Service (local resolver)
.bit namecoindns (10.5.0.12) via CoreDNS Namecoin names (local resolver service)
.alt alt-root 185.121.177.177 Alternative DNS root
.loki Cloudflare 1.1.1.1 Lokinet privacy network
.zil Cloudflare 1.1.1.1 Zilliqa blockchain
.web3 Cloudflare 1.1.1.1 General blockchain namespace
Alfis TLDs Alfis (10.5.0.3) .anon, .btn, .conf, .index, .merch, .mirror, .mob, .screen, .srv, .ygg
EmerCoin TLDs EmerCoin (10.5.0.9) .emc, .coin, .lib, .bazar, .enum
OpenNIC TLDs OpenNIC public resolvers .bbs, .chan, .cyb, .dyn, .epic, .geek, .gopher, .indy, .libre, .neo, .null, .o, .oss, .oz, .parody, .pirate, .fur, .ku, .rm, .te, .ti, .uu, .ko
Clearnet Unbound (10.5.0.5) All other domains via recursive resolution

Configuration validation and drift tests

A simple automation is included to help detect accidental changes to the compose and DNS configuration:

  1. Local check run scripts/validate-config.sh (or its PowerShell equivalent).

    • The script requires docker to be installed; it will generate a normalized manifest and compare it against docker-compose.lock.yml.
    • If the baseline file does not exist it will be created; commit the file after review.
    • CoreDNS syntax is also validated using either a local coredns binary or a container.
  2. CI workflow .github/workflows/config-validation.yml is triggered on pushes or pull requests affecting docker-compose.yml or PopuraDNS/. The job executes the same docker compose config comparison and runs the Corefile check inside a container.

  3. Updating the baseline when intentional changes are made to the compose file, regenerate the baseline:

    scripts/validate-config.sh  # fails with drift
    cp generated.yml docker-compose.lock.yml
    git add docker-compose.lock.yml
    

These steps ensure that configuration drift is caught early and reviewers can see what has changed.

Local ENS (.eth) client

If you want to resolve Ethereum ENS names locally from the host, use the standalone client script:

python3 -m venv .venv-ens
source .venv-ens/bin/activate
pip install -r scripts/requirements-ens.txt
python3 scripts/resolve_ens.py vitalik.eth --pretty

Options:

  • --rpc <url> to set a custom Ethereum JSON-RPC endpoint.
  • --include-text to include common ENS text records.

Example:

python3 scripts/resolve_ens.py ens.eth --include-text --pretty

Local Namecoin (.bit) resolver

.bit lookups are routed through a local namecoindns service in the stack:

  • CoreDNS forwards bit.:53 to 10.5.0.12:53.
  • namecoindns performs DNS-over-HTTPS upstream resolution.

Quick test:

docker exec darkpihole dig @10.5.0.4 A id.bit
docker exec darkpihole dig @10.5.0.4 TXT id.bit

If your environment returns NXDOMAIN for .bit, configure Namecoin-capable DoH upstreams in docker-compose.yml under namecoindns (NAMECOIN_DOH_UPSTREAMS).

Monitoring the proxy

A lightweight Prometheus/Grafana stack is included to expose 3proxy metrics and give you visibility into traffic volumes, connected sessions, etc.

how it works

  • 3proxy is configured with monitor -p6800, which sets up a plain-text status socket. Samples look like PROXY CONNS 12 or SOCKS IN 345.
  • monitor/exporter.py polls that socket every few seconds and exports the counters on HTTP port 9100 in Prometheus format.
  • The docker-compose.yml file now defines three new services: 3proxy_exporter, prometheus and grafana. Prometheus scrapes the exporter and Grafana points at Prometheus as a data source.

building & running

The exporter lives in monitor/; build the image and start the stack:

# build everything including the new services
docker-compose build 3proxy_exporter prometheus grafana

docker-compose up -d

Prometheus will be accessible on port 9090, Grafana on 3000 (admin password secret). Use Grafana to create or import dashboards a simple example JSON is provided in monitor/3proxy-dashboard.json. You can import that file directly or build your own panels using metrics such as proxy_conns and proxy_bytes_in.

tips

  • Alerts can be added in Prometheus rules, e.g. fire when proxy_conns exceeds a threshold for several minutes.
  • If you dont want the full stack, you can still query the monitor port directly with nc; nothing in the proxy depends on the exporter.
  • The scripts/validate-config.sh script warns if a 3proxy config lacks a monitor line.

Production readiness checklist

Make sure you never commit real secrets. The secrets/ directory is now included in .gitignore; both timezone and Yggdrasil key files live there and are mounted into containers at runtime.

Before deploying to a live environment, run the validation script and resolve any warnings or errors. The script covers:

  • YAML syntax and drift against the committed baseline
  • CoreDNS/PopuraDNS Corefile syntax
  • Unbound configuration syntax
  • Presence of required secret files
  • Simple 3proxy configuration sanity (presence of socks/proxy rules)
  • Detection of :latest image tags (pin to fixed versions)
  • Verification that restart policies exist

The GitHub Actions workflow also includes a smoke test job that spins up all services in docker-compose.yml using a DockerinDocker service and waits for each containers healthcheck to report healthy. This gives an additional layer of confidence that the stack can be built and started successfully.

You can also extend the script with additional service-specific checks such as running docker run ... commands to exercise the images, scanning the 3proxy config more deeply, or linting other mounted configuration files.

Run the script locally via ./scripts/validate-config.sh (or .scripts/validate-config.ps1 on Windows) and review the output carefully. CI will execute the same validations automatically on pull requests.