npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tls-router

v2.0.3

Published

Route incoming TLS clients to backend plaintext TCP servers based on the ALPN (protocol) and SNI (servername).

Downloads

5

Readme

tls-router 🛂

Route incoming TLS clients to backend plaintext TCP servers based on the ALPN (protocol) and SNI (servername) of the TLS handshake.

Tls Router can serve both encrypted (TLS) and plaintext (TCP) traffic on the same port. It detects whether a client is using TLS based on the first three bytes of the first data packet, also known as the TLS "ClientHello" handshake. Plaintext TCP clients are directed to an optional fallback backend.

Performance impact on network throughput should be minimal since all the data processing is handled by the internals of Node.js, specifically OpenSSL and libuv. No streaming data is processed at the JavaScript level.

This tool can be used with any TLS/TCP based connections. Its initial purpose is to allow legacy Gopher servers to transparently support Gopher over TLS (using ALPN) and virtual hosting multiple domains on the same IP address (using SNI).

Usage

Node.js must be available on the system, exposing the global node, npm, and npx commands.

Global Installation

System-wide installation makes the tls-router command globally available. The trade-off is that only a single version can be installed.

npm install --global tls-router

tls-router [options]

Local Installation

To include tls-router in a package for Node.js, use local installation to allow dependency versioning.

npm install --development tls-router

... or:

npm install --production tls-router

Then use tls-router via its API in your application code, or run the local command as npx tls-router, or use it within an npm-run script inside your package.json file.

npx tls-router [options]

... or:

{
  "name": "my-app",
  "scripts": {
    "my-script": "tls-router"
  },
  "devDepencencies": {
    "tls-router": "*"
  }
}
npm run my-script --  [options]

On-demand Installation

To run tls-router as a one-off command, without permanent global installation nor requiring a package.json project file, use the handy npx command that comes with Node.js. This downloads and installs into a temporary location, then cleans up after the command terminates. Downloads are cached so subsequent runs should be faster.

npx tls-router [options]

CLI

Example: Gopher over TLS with various ways to configure routing rules.

npx tls-router
  # Accept both TLS and TCP clients on port 70
  --listen 70

  # Offered ALPN names
  --alpn gopher

  # TLS crypto files
  --public-certificate cert.pem
  --private-key key.pem
  --certificate-authority ca.pem

  # TCP connections are piped to a local backend server on port 7777
  --plaintext localhost:7777

  # ALPN=gopher SNI=example.net to localhost:7000 (DNS lookup)
  --route gopher:example.net:localhost:7000

  # ALPN=gopher SNI=example.net to 127.0.0.1:7000 (IPv4)
  --route gopher:example.net:127.0.0.1:7000

  # ALPN=gopher SNI=example.net to [::1]:7000 (IPv6)
  --route gopher:example.net:[::1]:7000

  # ALPN=* SNI=example.net to 127.0.0.1:7000
  --route :example.net:127.0.0.1:7000

  # ALPN=gopher SNI=* to 127.0.0.1:7000
  --route gopher::127.0.0.1:7000

  # all trafic as plaintext to localhost:7000
  --route 7000

  # all traffic as plaintext to 127.0.0.1:7000 (IPv4)
  --route 127.0.0.1:7000

  # all traffic as plaintext to [::1]:7000 (IPv6)
  --route '[::1]:7000'

  # ALPN=* SNI=example.net to 127.0.0.1:7000
  --route :example.net:127.0.0.1:7000

CLI options can also be specified using:

  • Environment variables with the TLS_ROUTER_ prefix. E.g. TLS_ROUTER_LISTEN=70
  • JSON configuration file whose path is specified with the --config option. E.g. --config options.json

For more information run with the options:

  • --help to see a list of all available options.
  • --version to show the current application version.

API

Example: Accept Gopher over TLS on port 70. All TLS clients are routed to a regular (plaintext, non-TLS) Gopher server on port 7000. Plaintext TCP clients are routed to a fallback server on port 7777.

const { TlsRouter } = require('tls-router')

const router = new TlsRouter((rule, client, backend) => {
  console.log(`Client proxied to ${backend.port}`)
})

const [key, cert, ca] = await Promise.all([
  readFile('./private-key.pem'),
  readFile('./public-certificate.pem'),
  readFile('./certificate-authority.pem')
])
router.setSecureContext({
  key, cert, ca,
  ALPNProtocols: ['gopher']
})

router.route({ port: 7000 })
router.plaintext = { port: 7777 }

router.listen(70)

Class: new TlsRouter([options][, routedConnectionListener])

Extends: net.Server

Also implements several methods of, but does not inherit from, tls.TLSServer.

options - Passed to the net.Server constructor. See: https://nodejs.org/api/net.html#net_new_net_server_options_connectionlistener

  • ttfbTimeout - The maximum time-to-first-byte before a client is disconnected. Default: 10000

routedConnectionListener - Optional handler for the routedConnection event.

Event: routedConnection

Emitted when an incoming TLS connection is routed to a backend.

Arguments:

  • rule - The matching rule, if any. This is undefined if the client is a plaintext connection. See: router.route()
  • client - The incoming tls.TLSSocket (TLS) or net.Socket (TCP) connection.
  • backend - The forwarded net.Socket (TCP) connection.

Event: plaintextConnection

Emits once a socket is confirmed to be TCP and not TLS. Use this instead of the connection event.

See: https://nodejs.org/api/net.html#net_event_connection

Event: secureConnection

See: https://nodejs.org/api/tls.html#tls_event_secureconnection

Event: missingRoute

When a TLS client connects but no route matches its SNI and ALPN, thi event is emitted. The handler receives the incoming net.Socket (TCP) instance.

It is up to the event handler to deal with the connection. If this event is not listened for, the client connection is gracefully closed.

Event: clientError

Fires when either the client (TLS) or backend (TCP) socket throws an error.

Arguments:

  • error - Error instance
  • client or backend - net.Socket or tls.TLSSocket instance respectively

router.plaintext

Destination address for incoming plaintext TCP connections.

Set to an object with properties:

  • address
  • family
  • port

See: server.address()

Detault: undefined

router.route(...rule)

Each rule has the properties:

  • sni - Match the server domain name provided by the TLS client. Default: Any server name matches.
  • alpn - Match the negotiated protocol provided by the TLS client. Default: Any protocol name matches.
  • port - TCP port of the route destination. Required.
  • address - TCP IP address or DNS hostname of the route destination. Default: localhost
  • family - The IP type, either 4, 6, or 0. Default: 0 (auto).

router.getTicketKeys()

See: https://nodejs.org/api/tls.html#tls_server_getticketkeys

router.setTicketKeys(keys)

See: https://nodejs.org/api/tls.html#tls_server_setticketkeys_keys

router.setSecureContext(options)

See: https://nodejs.org/api/tls.html#tls_server_setsecurecontext_options