Skip to content

c2FmZQ/tlsproxy

Repository files navigation

pr release CodeQL

TLS Termination Proxy

TLSPROXY is primarily a TLS termination proxy that uses Let's Encrypt to provide TLS encryption for any number of TCP or HTTP servers, and any number of server names concurrently on the same port.

Its functionality is similar to an stunnel server, but without the need to configure and run certbot separately.

TLSPROXY can also be used as a Reverse Proxy for HTTP(S) services, and optionally control access to these services with user authentication and authorization.

Overview of features:

  • Use Let's Encrypt automatically to get TLS certificates (http-01 & tls-alpn-01 challenges).
  • Terminate TLS connections, and forward the data to any TCP server in plaintext.
  • Terminate TLS connections, and forward the data to any TLS server. The data is encrypted in transit, but the proxy sees the plaintext.
  • Terminate TCP connections, and forward the TLS connection to any TLS server (passthrough). The proxy doesn't see the plaintext.
  • Terminate QUIC connections, and forward the data to any QUIC or TLS/TCP server.
  • Terminate HTTPS connections, and forward the requests to HTTP or HTTPS servers (http/1.1, http/2, http/3).
  • Support for the PROXY protocol defined by HAProxy. (not on QUIC or HTTP/3 backends)
  • TLS client authentication & authorization (when the proxy terminates the TLS connections).
  • Built-in Certificate Authority for managing client and backend server TLS certificates.
  • User authentication with OpenID Connect, SAML, and/or passkeys (for HTTP and HTTPS connections). Optionally issue JSON Web Tokens (JWT) to authenticated users to use with the backend services and/or run a local OpenID Connect server for backend services.
  • Access control by IP address.
  • Routing based on Server Name Indication (SNI), with optional default route when SNI isn't used.
  • Simple round-robin load balancing between servers.
  • Support any ALPN protocol in TLS, TLSPASSTHROUGH, QUIC, or TCP mode.
  • OCSP stapling and OCSP certificate verification.
  • Hardware-backed cryptographic keys for encryption and signing with a TPM.
  • Use the same address (IPAddr:port) for any number of server names, e.g. foo.example.com and bar.example.com on the same xxx.xxx.xxx.xxx:443.
flowchart LR
  subgraph Incoming TLS or QUIC Connections
    h1(www.example.com)
    h2(foo.example.com)
    h3(bar.example.com)
    h4(...)
  end
  prx(((TLSPROXY)))
  subgraph Backend Services
    be1(HTTP Server)
    be2(HTTPS Server)
    be3(IMAP, SMTP, SSH)
    be4(Any TCP, TLS, or QUIC Server)
  end
  h1-->prx
  h2-->prx
  h3-->prx
  h4-->prx
  prx-->be1
  prx-->be2
  prx-->be3
  prx-->be4

Example config:

# (Required) Indicate acceptance of the Let's Encrypt Terms of Service.
acceptTOS: true
# (Optional) The email address is used by Let's Encrypt to send important notifications.
email: <your email address>

# The HTTP address must be reachable from the internet via port 80 for the
# letsencrypt ACME http-01 challenge to work. If the httpAddr is empty, the
# proxy will only use tls-alpn-01 and tlsAddr must be reachable on port 443.
# See https://letsencrypt.org/docs/challenge-types/
# Normal HTTP requests received on this port are redirected to port 443.
httpAddr: ":10080"

# The proxy will receive TLS connections at this address and forward them to
# the backends.
tlsAddr: ":10443"

# Each backend has a list of server names (DNS names that clients connect to),
# and addresses (where to forward connections).
backends:

# In HTTP mode, HTTPS requests to example.com and www.example.com are forwarded
# to the listed addresses using round robin load balancing.
- serverNames:
  - example.com
  - www.example.com
  mode: http
  addresses:
  - 192.168.0.10:80
  - 192.168.0.11:80
  - 192.168.0.12:80

# In HTTPS mode, HTTPS requests to other.example.com are forwarded to the listed
# addresses just like in http mode. The connection between the proxy and the
# backend server(s) uses TLS. The identity of the server is verified with
# forwardServerName, forwardRootCAs, and/or insecureSkipVerify.
- serverNames:
  - other.example.com
  mode: https
  addresses:
  - 192.168.1.100:443
  insecureSkipVerify: true

# In TCP mode, incoming TLS connections are forwarded to the listed addresses
# using unencrypted TCP connections. The connections are distributed between
# backend servers using round robin load balancing.
- serverNames:
  - ssh.example.com
  mode: tcp
  addresses:
  - 192.168.2.200:22

# In TLS mode, incoming TLS connections are forwarded to the listed addresses
# using TLS. The connections are distributed between backend servers using round
# robin load balancing. The identity of the server is verified with
# forwardServerName, forwardRootCAs, and/or insecureSkipVerify.
- serverNames:
  - secure.example.com
  mode: tls
  addresses:
  - 192.168.3.123:8443
  forwardServerName: secure-internal.example.com

# In all modes (except tlspassthrough), the client identity can be verified by
# setting clientAuth, and optionally setting rootCAs and acl.
- serverNames:
  - restricted.example.com
  mode: https
  clientAuth:
    rootCAs:
    - |
      -----BEGIN CERTIFICATE-----
      .....
      -----END CERTIFICATE-----
    acl:
    - SUBJECT:CN=admin-user
  addresses:
  - 192.168.4.100:443
  forwardServerName: restricted-internal.example.com

# In TLSPASSTHROUGH mode, incoming TLS connections are forwarded directly to the
# backend servers. The proxy only sees the encrypted content transmitted between
# the client and the backend servers. The backend servers need to have their own
# TLS certificates and, if client authentication is required, they need to do it
# themselves.
- serverNames:
  - passthrough.example.com
  mode: tlspassthrough
  addresses:
  - 192.168.5.66:8443

See the godoc and the examples directory for more details.

How to download and run tlsproxy

From source

Install from the source code:

git clone https://github.com/c2FmZQ/tlsproxy.git
cd tlsproxy
go generate ./...
go build -o tlsproxy

Then, run it with:

<path>/tlsproxy --config=config.yaml

Docker image

Use the docker image, e.g.

docker run                                 \
  --name=tlsproxy                          \
  --user=1000:1000                         \
  --restart=always                         \
  --volume=${CONFIGDIR}:/config            \
  --volume=${CACHEDIR}:/.cache             \
  --publish=80:10080                       \
  --publish=443:10443                      \
  --env=TLSPROXY_PASSPHRASE="<passphrase>" \
  c2fmzq/tlsproxy:latest

The proxy reads the config from ${CONFIGDIR}/config.yaml.

⚠️ ${TLSPROXY_PASSPHRASE} is used to encrypt the TLS secrets.

Precompiled binaries

Download a precompiled binary from the release page.

Verify signatures

The release binaries and the container images are signed when they are published.

Container image

To verify the authenticity of a container image, use:

cosign verify \
  --certificate-identity-regexp='^https://github[.]com/c2FmZQ/tlsproxy/[.]github/workflows/release[.]yml' \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com                                   \
  c2fmzq/tlsproxy:latest

and/or:

cosign verify --key keys/cosign.pub c2fmzq/tlsproxy:latest

Release binary

To verify the authenticity of a release binary, first import c2FmZQ-bot.pub:

curl https://raw.githubusercontent.com/c2FmZQ/tlsproxy/main/keys/c2FmZQ-bot.pub | gpg --import

Then, verify the signature, e.g.

gpg --verify tlsproxy-linux-amd64.sig tlsproxy-linux-amd64