Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/atenart/sniproxy

TLS proxy routing TCP connections to backends based on the TLS SNI in the TLS handshake
https://github.com/atenart/sniproxy

Last synced: 3 months ago
JSON representation

TLS proxy routing TCP connections to backends based on the TLS SNI in the TLS handshake

Awesome Lists containing this project

README

        

# SNIProxy

_SNIProxy_ is a TLS proxy, based on the TLS
[Server Name Indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication).
The SNI is contained in TLS handshakes and _SNIProxy_ uses it to route
connections to backends. _SNIProxy_ does not need the TLS encryption keys and
cannot decrypt the TLS traffic that goes through.

_SNIProxy_ is meant to be simple to use and configure, with sane defaults and
few parameters.

A first version was written in [Go](https://go.dev) and can be found in the
[archive/go](https://github.com/atenart/sniproxy/tree/archive/go) branch. It was
latter rewritten in [Rust](https://www.rust-lang.org).

## Container image

```shell
$ podman run --name sniproxy -p 80:80/tcp -p 443:443/tcp \
-v $(pwd)/sniproxy.yaml:/sniproxy.yaml:ro \
atenart/sniproxy:latest
```

The above works with Docker too, just replace `podman` with `docker`.

_SNIProxy_ handles HTTP connections and redirects those to their HTTPS
counterparts. If this is not needed, the above `-p 80:80/tcp` can be omitted.

## Parameters

The log level can be controlled using the `--log-level` CLI parameter. By
default `INFO` and above levels are reported. The configuration file can be
selected by the `--config` CLI parameter, and defaults to `sniproxy.yaml`.

See `sniproxy --help` for a list of available parameters.

## Configuration file

_SNIProxy_'s configuration file is written in the
[YAML](https://en.wikipedia.org/wiki/YAML) format.

```text
---
bind_https:
bind_http:
routes:
- domains:
-
-
backend:
address:
proxy_protocol:
alpn_challenge_backend:
address:
proxy_protocol:
alpn_challenge_bypass_acl:
denied_ranges:
-
-
allowed_ranges:
-
- domains:
...
```

A configuration for a single route can be as simple as:

```yaml
---
routes:
- domains:
- "example.net"
backend:
address: "1.2.3.4:443"
```

Domain names can be a regular expression:

```yaml
---
routes:
- domains:
# Matches example.net and all its subdomains.
- "example.net"
- "*.example.net"
backend:
address: "1.2.3.4:443"
```

### Optional parameters

_SNIProxy_ has a built-in ACL logic and can block and allow connections based on
the client IP address. When at least one range is explicitly allowed, all other
ranges are automatically denied (0.0.0.0/0 & ::/0). When an address can be found
in two ranges, the most specific wins. If the exact same range is both allowed
and denied, the deny rule wins.

```yaml
---
routes:
- domains:
- "example.net"
backend:
address: "1.2.3.4:8080"
denied_ranges:
- "10.0.0.42/32"
- domains:
- "foo.example.com"
backend:
address: "5.6.7.8:443"
denied_ranges:
- "10.0.0.42/32"
- "10.0.0.43/32"
- "192.168.0.0/24"
allowed_ranges:
- "192.168.0.42/32"
```

_SNIProxy_ can use a different backend for ALPN requests:

```yaml
---
routes:
- domains:
- "example.net"
backend:
address: "[1111::1]:8080"
alpn_challenge_backend:
address: "alpn-backend:8080"
```

The ACL rules can be bypassed for ALPN challenge requests:

```yaml
---
routes:
- domains:
- "example.net"
backend:
address: "[1111::1]:8080"
alpn_challenge_backend:
address: "alpn-backend:8080"
alpn_challenge_bypass_acl: true
allowed_ranges:
- "192.168.0.0/24"
```

[HAProxy PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt)
v1 and v2 are supported for backend connections:

```yaml
---
routes:
- domains:
- "example.net"
backend:
address: "[1111::1]:8080"
proxy_protocol: 2
alpn_challenge_backend:
address: "alpn-backend:8080"
proxy_protocol: 1
```