No description
Find a file
github-actions[bot] d9b3c56ba0
Merge pull request #180 from mosajjal/dependabot/github_actions/docker/build-push-action-7.1.0
Bump docker/build-push-action from 7.0.0 to 7.1.0
2026-04-13 07:24:49 +00:00
.github Bump docker/build-push-action from 7.0.0 to 7.1.0 2026-04-13 07:24:37 +00:00
cmd/sniproxy fix: add Stop() to ACL interface, fix goroutine leaks in refresh workers 2026-03-13 20:30:44 +13:00
pkg fix: add Stop() to ACL interface, fix goroutine leaks in refresh workers 2026-03-13 20:30:44 +13:00
.gitignore fix: add Stop() to ACL interface, fix goroutine leaks in refresh workers 2026-03-13 20:30:44 +13:00
.golangci.yml fix: resolve all golangci-lint issues, harden HTTP servers, rewrite docs 2026-03-13 17:09:51 +13:00
cidr.csv V2 (#48) 2023-05-13 16:29:38 +12:00
CONTRIBUTING.md fix: resolve all golangci-lint issues, harden HTTP servers, rewrite docs 2026-03-13 17:09:51 +13:00
Dockerfile refactor 2025-11-01 10:46:57 +13:00
domains.csv updated domains.csv from fod 2023-05-13 16:32:17 +12:00
go.mod chore: update all dependencies 2026-03-13 20:46:26 +13:00
go.sum chore: update all dependencies 2026-03-13 20:46:26 +13:00
install.sh install.sh rewrite 2025-07-23 10:38:27 +12:00
LICENSE Update LICENSE 2025-01-10 15:02:47 +13:00
README.md fix: resolve all golangci-lint issues, harden HTTP servers, rewrite docs 2026-03-13 17:09:51 +13:00

sniproxy

An SNI proxy with a built-in DNS server. It intercepts DNS queries, responds with its own IP address, then proxies the incoming TLS/HTTP connections to the real destination by reading the SNI (Server Name Indication) or Host header.

This is useful when you want to selectively proxy traffic for specific domains through a server, without needing to set up a full VPN. Point your DNS at sniproxy, and it handles the rest.

Continuation of byosh and SimpleSNIProxy.

How it works

  1. Client sends a DNS query for example.com
  2. sniproxy checks the domain against its ACL rules
  3. If the domain should be proxied, sniproxy responds with its own public IP
  4. Client connects to sniproxy on port 443 (or 80)
  5. sniproxy reads the SNI from the TLS ClientHello (or Host header for HTTP), connects to the real server, and pipes traffic both ways

For domains that shouldn't be proxied, sniproxy forwards the DNS query upstream and returns the real IP.

Features

DNS server supporting UDP, TCP, DNS-over-TLS, DNS-over-QUIC, and DNS-over-HTTPS. HTTP and HTTPS proxying with multi-port listeners. ACL system with domain lists, CIDR ranges, GeoIP filtering (MaxMind MMDB), and per-FQDN destination overrides. Optional SOCKS5 upstream proxy. Source IP rotation across multiple interface addresses. IPv4/IPv6 with configurable preference. Prometheus metrics endpoint.

Install

Grab a binary from the releases page, or:

go install github.com/mosajjal/sniproxy/v2@latest

Docker:

docker run -d --pull always \
  -p 80:80 -p 443:443 -p 53:53/udp \
  -v "$(pwd)/config.yaml:/tmp/config.yaml" \
  ghcr.io/mosajjal/sniproxy:latest --config /tmp/config.yaml

There's also an installer script that sets up systemd and everything:

bash <(curl -L https://raw.githubusercontent.com/mosajjal/sniproxy/master/install.sh)

Configuration

sniproxy uses a YAML config file. Dump the defaults with:

sniproxy --defaultconfig > config.yaml

Then edit to taste. The config covers upstream DNS, bind addresses, ACL rules, TLS certs, and SOCKS5 proxy settings. See config.defaults.yaml for the full reference with comments.

You can also override any setting with environment variables using the SNIPROXY_ prefix. Double underscores separate nested keys:

SNIPROXY_GENERAL__BIND_DNS_OVER_UDP=0.0.0.0:5555

Ports

sniproxy needs ports 80, 443, and 53 by default. On Ubuntu, systemd-resolved often squats on port 53. Either disable it or change its stub listener:

sed -i 's/#DNS=/DNS=9.9.9.9/; s/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf
systemctl restart systemd-resolved

Usage

sniproxy [flags]

Flags:
  -c, --config string   path to YAML configuration file
      --defaultconfig    write the default config yaml file to stdout
  -h, --help            help for sniproxy
  -v, --version         show version info and exit

API docs

pkg.go.dev/github.com/mosajjal/sniproxy/v2/pkg