/tlswrapper

Wrap your TCP-based service with multiplexing mTLS tunnels.

Primary LanguageGoMIT LicenseMIT

tlswrapper

MIT License Build Go Report Card Downloads Release

Wrap any TCP-based service with multiplexed mutual TLS tunnels.

Status: Stable

Features

  • Multiplexed: All traffic goes over one TCP connection.
  • Mutual Forwarded: Each peer can listen from and connect to the other peer simultaneously over the same underlying connection.
  • Secured: All traffic is optionally protected by mutual authenticated TLS.
  • Incompatible: Always enforce the latest TLS version.

In terms of performance, creating multiplexed TCP tunnels is generally not a good idea, see Head-of-line blocking. Make sure you have a good reason to do so.

       Trusted      |     Untrusted    |     Trusted
+--------+    +------------+    +------------+    +--------+
| Client |-n->|            |    |            |-n->| Server |
+--------+    |            |    |            |    +--------+
              | tlswrapper |-1->| tlswrapper |
+--------+    |            |    |            |    +--------+
| Server |<-n-|            |    |            |<-n-| Client |
+--------+    +------------+    +------------+    +--------+

Protocol Stack

+-------------------------------+
|          TCP traffic          |
+-------------------------------+
|   yamux stream multiplexing   |
+-------------------------------+
|   mutual TLS 1.3 (optional)   |
+-------------------------------+
|  TCP/IP (untrusted network)   |
+-------------------------------+

Authentication Model

Like SSH, each peer should have a key pair (certificate + private key) and an authorized list. Only certificates in the authorized list can communicate with the peer.

This behavior is based on TLS 1.3 implemented by "crypto/tls" library in Go.

By default, all certificates are self-signed. This will not reduce security.

Quick Start

Generate key pair with OpenSSL

See gencerts.sh.

./gencerts.sh client server

Create "config.json"

Server

{
  "tunnel": [
    {
      "muxlisten": "0.0.0.0:12345",
      "dial": "127.0.0.1:8080"
    }
  ],
  "cert": "server-cert.pem",
  "key": "server-key.pem",
  "authcerts": [
    "client-cert.pem"
  ]
}

Client

{
  "tunnel": [
    {
      "listen": "127.0.0.1:8080",
      "muxdial": "example.com:12345"
    }
  ],
  "cert": "client-cert.pem",
  "key": "client-key.pem",
  "authcerts": [
    "server-cert.pem"
  ]
}

Options

  • "tunnel": TLS tunnel configs
  • "tunnel[*].muxlisten": Server bind address for TLS connections
  • "tunnel[*].muxdial": Client dial address for TLS connections
  • "tunnel[*].listen": Listen for port forwarding
  • "tunnel[*].dial": The address we forward incoming connections to
  • "cert": peer certificate
  • "key": peer private key
  • "authcerts": peer authorized certificates list, bundles are supported

See source code for a complete list of all available options.

See config.json for example config file.

Start

./tlswrapper -c config.json

You may also found the systemd user unit tlswrapper.service is useful.

Build/Install

# get source code
git clone https://github.com/hexian000/tlswrapper.git
cd tlswrapper
# build an executable for local system
./make.sh r

Credits