Skip to main content

Agent TLS Termination

Agent TLS termination enables you to secure your traffic with end-to-end encryption without needing to reconfigure your server.

tip

If your service doesn't support TLS termination, you can still use Agent TLS termination with Zero-Knowledge TLS.

Quickstart

The following instructions will guide you through setting up Agent TLS termination with ngrok.

Prerequisites

Step 1 – Generate a cert and key pair

The following command:

  1. Generates a new certificate signing request (CSR) for a 4096-bit RSA key pair.
    • The key is saved to your-key.key.
  2. Creates a self-signed certificate which:
    • Is in x509 format and uses the SHA-256 hash algorithm.
    • Is valid for 365 days.
    • Is saved to your-cert.crt.
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -noenc -out your-cert.crt -keyout your-key.key

Step 2 – Configure your endpoint

You can configure your endpoint with an agent configuration file. To create a new configuration file with your generated cert and key pair, run the following command:

ngrok config add-authtoken you-authtoken

Your generated configuration file should resemble the following:

version: 3
agent:
authtoken: your-authtoken
endpoints:
- name: demo-tls
url: "tls://your-domain.ngrok.app"
upstream:
url: 12345
agent_tls_termination:
server_certificate: /path/to/your-cert.crt
server_private_key: /path/to/your-key.key
tip

You can run ngrok config edit to open the configuration file in your default text editor. Learn more about the ngrok config command.

Step 3 – Start your endpoint

Next, use ngrok start endpoint_name_here in the terminal to start an endpoint using the settings in your agent configuration file, as shown below:

ngrok start demo-tls

Step 4 – Start your upstream server

Start an upstream server on the specified port (e.g., 12345) to handle incoming requests. The following example uses Python, but you can use any language or framework depending on your requirements.

import socket

host='127.0.0.1'
port=12345
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
print(f"Server started on {host}:{port}")
server.listen(1)

while True:
client, client_address = server.accept()
print(f"Connection established with {client_address}")
client.sendall(b"hello, world!")
client.close()
print(f"Connection with {client_address} closed")

Step 5 – Try connecting to your endpoint

The following example uses openssl s_client to initiate an SSL/TLS client connection to your upstream server without a certificate.

openssl s_client -quiet -connect your-domain.ngrok.app:443 -verify_return_error
Connecting to 2600:1f16:d83:1200::6e:0
depth=0 C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=your-domain.ngrok.app
verify error:num=18:self-signed certificate
408FB6F801000000:error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2093:

The following example uses openssl s_client to initiate an SSL/TLS client connection to your upstream server with a certificate.

openssl s_client -quiet -connect your-domain.ngrok.app:443 -verify_return_error -CAfile your-cert.crt
Connecting to 2600:1f16:d83:1200::6e:0
depth=0 C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=your-domain.ngrok.app
verify return:1
hello, world!%
note

The extra arguments added to the command suppress most of the output so that only the data exchanged with the server will be displayed.

Mutual TLS example

The following instructions will guide you through setting up Agent TLS termination using Mutual TLS (mTLS) with ngrok.

Step 1 – Generate a root CA private key and certificate

openssl genpkey -algorithm RSA -out your-ca.key -pkeyopt rsa_keygen_bits:2048
openssl req -x509 -new -nodes -key your-ca.key -sha256 -days 365 -out your-ca.crt -subj "/CN=YourDemoCA"

Step 2 – Generate server credentials

The following terminal commands will generate these server credentials:

  • A server private key
  • A CSR
  • A signed certificate
openssl genpkey -algorithm RSA -out your-server.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -key your-server.key -out your-server.csr -subj "/CN=your-domain.ngrok.app"
openssl x509 -req -in your-server.csr -CA your-ca.crt -CAkey your-ca.key -CAcreateserial -out your-server.crt -days 365 -sha256

Step 3 – Generate client credentials

The following terminal command will generate these client credentials:

  • A private key
  • A CSR
  • A signed certificate
openssl genpkey -algorithm RSA -out your-client.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -key your-client.key -out your-client.csr -subj "/CN=YourDemoCA"
openssl x509 -req -in your-client.csr -CA your-ca.crt -CAkey your-ca.key -CAcreateserial -out your-client.crt -days 365 -sha256

Step 4 – Configure your mTLS endpoint

Use the following command to create an agent configuration file with your generated certificates:

ngrok config add-authtoken you-authtoken

Your generated configuration file should resemble the following:

version: 3
agent:
authtoken: your-token
endpoints:
- name: demo-mtls
url: "tls:/your-domain.ngrok.app"
upstream:
url: 8080
agent_tls_termination:
server_certificate: /path/to/your-cert.crt
server_private_key: /path/to/your-key.key
mutual_tls_certificate_authorities:
- /path/to/your-ca.crt

Step 5 – Start your mTLS endpoint

Next, use ngrok start endpoint_name_here in the terminal to start an endpoint using the settings in your agent configuration file, as shown below:

ngrok start demo-mtls

Step 6 – Start your upstream server

Start an upstream server on the specified port (e.g., 12345) to handle incoming requests. The following example uses Python, but you can use any language or framework depending on your requirements.

import socket

host='127.0.0.1'
port=12345
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
print(f"Server started on {host}:{port}")
server.listen(1)

while True:
client, client_address = server.accept()
print(f"Connection established with {client_address}")
client.sendall(b"hello, world!")
client.close()
print(f"Connection with {client_address} closed")

Step 7 – Try connecting to your mTLS endpoint

The following example uses openssl s_client to initiate an SSL/TLS client connection to your upstream server without a certificate.

openssl s_client -quiet -connect your-domain.ngrok.app:443 -verify_return_error
Connecting to 2600:1f16:d83:1200::6e:3
depth=0 CN=your-domain.ngrok.app
verify error:num=20:unable to get local issuer certificate
408FB6F801000000:error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2093

The following example uses openssl s_client to initiate an SSL/TLS client connection to your upstream server with a certificate.

openssl s_client -quiet -connect your-domain.ngrok.app:443 -verify_return_error -CAfile your-ca.crt
Connecting to 2600:1f16:d83:1200::6e:3
depth=1 CN=YourDemoCA
verify return:1
depth=0 CN=your-domain.ngrok.app
verify return:1
hello, world!%