Git Product home page Git Product logo

sniproxy's Introduction

sniproxy

Proxies incoming HTTP and TLS connections based on the hostname that is parsed from either HTTP Host header (for plain HTTP connections) or TLS ClientHello.

This allows transparent proxying of the network traffic by simply rerouting connections to the sniproxy. There are many ways to re-route traffic, but most often it is done either on the DNS level or by using iptables.

Features

  • Embedded DNS server that can be used to redirect traffic to the proxy.
  • Supports both TLS and plain HTTP.
  • Supports forwarding connections to an upstream SOCKS proxy.
  • Flexible rules for redirecting, forwarding, blocking or throttling connections.
  • Cross-platform and simple.

How to install

  • Using homebrew:
    brew install ameshkov/tap/sniproxy
    
  • From source:
    go install github.com/ameshkov/sniproxy
    
  • You can get a binary for your platform from the releases page.

Using sniproxy

Redirect all traffic to a SNI proxy

  • Run sniproxy and rewrite DNS responses to point to 1.2.3.4:

    sudo sniproxy --dns-redirect-ipv4-to=1.2.3.4
  • You can test locally it with the following commands:

    curl "https://example.org/" --dns-servers 127.0.0.1
    curl "http://example.org/" --dns-servers 127.0.0.1

    Not every curl version supports --dns-servers. Alternatively, use these commands:

    curl "https://example.org/" --connect-to example.org:443:127.0.0.1:443
    curl "http://example.org/" --connect-to example.org:80:127.0.0.1:80
  • Now you should just point your device to the DNS server that is running on your computer.

Forward all traffic to a proxy

Run sniproxy, rewrite DNS responses to point to 1.2.3.4, :

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --forward-proxy="socks5://127.0.0.1:1080"

Now every connection will be re-routed to the SOCKS5 proxy on 127.0.0.1:1080.

You can choose which domains are re-routed. For instance, here only example. org and example.com will be re-routed through the SOCKS5 proxy:

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --forward-proxy="socks5://127.0.0.1:1080" \
    --forward-rule=example.org \
    --forward-rule=example.com

It also supports HTTP and HTTPS proxies. Here's an example:

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --forward-proxy="http://127.0.0.1:8080" \
    --forward-rule=example.org \
    --forward-rule=example.com

Block domains

You may want to block access to some domains. There are two options of how it can be done: --block-rule or --drop-rule. If the connection matches a --block-rule, the connection will be closed immediately. If the connection matches a --drop-rule, the connection will "hang" for a hard-coded limit of 3 minutes before it will be closed.

Here's how block or drop connections to domains:

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --block-rule=example.org \
    --block-rule=example.com \
    --drop-rule=example.net

Drop DNS queries

You may want to emulate the situation when DNS queries to specific domains are dropped. Use --dns-drop-rule option to do this:

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --dns-drop-rule=example.net \
    --dns-drop-rule=example.com

Throttle connections

If you need to emulate slow network, use bandwidth-rate to set the desired bytes-per-sec rate.

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --bandwidth-rate=1000

You can also throttle connections to individual domains using bandwidth-rule.

sudo sniproxy \
    --dns-redirect-ipv4-to=1.2.3.4 \
    --bandwidth-rule="example.*:5000"

Command-line arguments

Usage:
  sniproxy [OPTIONS]

Application Options:
      --dns-address=          IP address that the DNS proxy server will be listening to. (default: 0.0.0.0)
      --dns-port=             Port the DNS proxy server will be listening to. (default: 53)
      --dns-upstream=         The address of the DNS server the proxy will forward queries that are not
                              rewritten by sniproxy. (default: 8.8.8.8)
      --dns-redirect-ipv4-to= IPv4 address that will be used for redirecting type A DNS queries.
      --dns-redirect-ipv6-to= IPv6 address that will be used for redirecting type AAAA DNS queries.
      --dns-redirect-rule=    Wildcard that defines which domains should be redirected to the SNI proxy. Can
                              be specified multiple times. (default: *)
      --dns-drop-rule=        Wildcard that defines DNS queries to which domains should be dropped. Can be
                              specified multiple times.
      --http-address=         IP address the SNI proxy server will be listening for plain HTTP connections.
                              (default: 0.0.0.0)
      --http-port=            Port the SNI proxy server will be listening for plain HTTP connections.
                              (default: 80)
      --tls-address=          IP address the SNI proxy server will be listening for TLS connections.
                              (default: 0.0.0.0)
      --tls-port=             Port the SNI proxy server will be listening for TLS connections. (default: 443)
      --bandwidth-rate=       Bytes per second the connections speed will be limited to. If not set, there
                              is no limit. (default: 0)
      --bandwidth-rule=       Allows to define connection speed in bytes/sec for domains that match the
                              wildcard. Example: example.*:1024. Can be specified multiple times.
      --forward-proxy=        Address of a SOCKS/HTTP/HTTPS proxy that the connections will be forwarded to
                              according to forward-rule.
      --forward-rule=         Wildcard that defines what connections will be forwarded to forward-proxy. Can
                              be specified multiple times. If no rules are specified, all connections will
                              be forwarded to the proxy.
      --block-rule=           Wildcard that defines connections to which domains should be blocked. Can be
                              specified multiple times.
      --drop-rule=            Wildcard that defines connections to which domains should be dropped (i.e.
                              delayed for a hard-coded period of 3 minutes. Can be specified multiple times.
      --verbose               Verbose output (optional)
      --output=               Path to the log file. If not set, write to stdout.

Help Options:
  -h, --help                  Show this help message

Debugging locally

If you want to contribute to sniproxy, here are some tips on how to debug it locally.

First, you rarely want to run with sudo and instead you'd prefer to use high ports. sniproxy provides command-line arguments for that.

./sniproxy \
    --dns-address=127.0.0.1 \
    --dns-port=5354 \
    --dns-upstream=8.8.8.8 \
    --dns-redirect-ipv4-to=127.0.0.1 \
    --dns-redirect-rule=example.org \
    --dns-redirect-rule=example.com \
    --tls-address=127.0.0.1 \
    --tls-port=8443 \
    --http-address=127.0.0.1 \
    --http-port=8080 \
    --forward-proxy="socks5://127.0.0.1:1080" \
    --verbose

It is easy to use curl to debug sniproxy:

# HTTPS request
curl "https://example.org/" --connect-to example.org:443:127.0.0.1:8443

# Plain HTTP request
curl "http://example.org/" --connect-to example.org:80:127.0.0.1:8080

Use mitmproxy to debug sniproxy with forwarding rules:

# Run mitmproxy in SOCKS mode
mitmweb --mode=socks5

# Forward connections to mitmproxy
./sniproxy \
    --dns-address=127.0.0.1 \
    --dns-port=5354 \
    --dns-upstream=8.8.8.8 \
    --dns-redirect-ipv4-to=127.0.0.1 \
    --dns-redirect-rule=example.org \
    --dns-redirect-rule=example.com \
    --tls-address=127.0.0.1 \
    --tls-port=8443 \
    --http-address=127.0.0.1 \
    --http-port=8080 \
    --forward-proxy="socks5://127.0.0.1:1080" \
    --verbose

# Check that the connections were properly forwarded
curl "https://example.org/" --connect-to example.org:443:127.0.0.1:8443 --insecure
curl "http://example.org/" --connect-to example.org:80:127.0.0.1:8080

sniproxy's People

Contributors

ameshkov avatar snawoot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sniproxy's Issues

Allow running sniproxy as a gateway

root@dev4-20-tunapi:/usr/local/bin# ./sniproxy --dns-redirect-ipv4-to=127.0.0.1 --tls-port=3133 --http-port=3134 --forward-proxy=http://192.168.118.21:3128
2023/10/10 11:04:19 [info] cmd: run sniproxy with the following configuration:
{
"DNSListenAddress": "0.0.0.0",
"DNSPort": 53,
"DNSUpstream": "8.8.8.8",
"DNSRedirectIPV4To": "127.0.0.1",
"DNSRedirectIPV6To": "",
"DNSRedirectRules": [
"*"
],
"DNSDropRules": null,
"HTTPListenAddress": "0.0.0.0",
"HTTPPort": 3134,
"TLSListenAddress": "0.0.0.0",
"TLSPort": 3133,
"BandwidthRate": 0,
"BandwidthRules": {},
"ForwardProxy": "http://192.168.118.21:3128",
"ForwardRules": null,
"BlockRules": null,
"DropRules": null,
"Verbose": false,
"LogOutput": ""
}

grk@dev4-20-tunapi:~$ curl -Iv https://193.109.212.15 -k

  • Trying 193.109.212.15:443...
  • Connected to 193.109.212.15 (193.109.212.15) port 443 (#0)
  • ALPN, offering h2
  • ALPN, offering http/1.1
  • successfully set certificate verify locations:
  • CAfile: /etc/ssl/certs/ca-certificates.crt
  • CApath: /etc/ssl/certs
  • TLSv1.3 (OUT), TLS handshake, Client hello (1):
  • OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 193.109.212.15:443
  • Closing connection 0
    curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 193.109.212.15:443

in sniproxy terminal output
...
2023/10/10 11:07:41 [info] sniproxy: [4] start tunneling to :443
2023/10/10 11:08:05 [info] sniproxy: [5] start tunneling to mail.google.com:443
...

in upstream squid access.log
...
1696928862.134 1 192.168.118.11 NONE/400 3861 CONNECT :443 - HIER_NONE/- text/html
1696928899.311 240197 192.168.118.11 TCP_TUNNEL/200 2748 CONNECT mail.google.com:443 - HIER_DIRECT/216.58.215.69 -
...

looks like fallback to TCP destination IP doesn't work properly, when in https connection there is no SNI field
when SNI field is present (https://mail.google.com) sniproxy works properly

Add an option to disable HTTP/2

Fastly error: unknown domain: github.com

This prompt often appears as if it is not for the reason that http2 is not supported.

Using Proxy

I just saw this project, was looking for something like this.
I use a socks proxy on my phone (made using proxidize-android
Was wondering if I use sniproxy and forward selected domians to socks, it will be working very similar to commercially available DNS proxies.
How can I add username & password for sniproxy to forward requests to socks ? because socks proxy on phone needs username and password to allow connection.
Please advice.
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.