HTTPS Reverse Tunnel, now without the pain and cost

Mahdi Torabi·June 5, 2024

TL;DR

Built to enable the work of Unblocked’s engineering team, chiSSL is a new, lightweight version of chisel that allows you to expose any local server running on your development machine to the internet with a valid SSL certificate, all via a single command.

Jump to the Getting Started section for configuration and examples.


We all know https is a mandatory requirement for most applications, but running your local development server with a valid SSL certificate is no small matter. Even if you make it through all the set up steps, you’re still limited by whether or not you have control over the client.

Take Slack webhooks, for example. Enabling a local service on your development machine to receive webhooks from Slack requires that the service is reachable over the internet and can provide a valid SSL certificate. At Unblocked, this is a common part of our workflow as we build our product. However, we’ve found that the choices available to complete this connection are either cost prohibitive or too low-level (e.g., they mainly focus on TCP/UDP tunnels).

Enter chiSSL

chiSSL is a new, lightweight version of chisel that allows you to expose any local server running on your development machine to the internet with a valid SSL certificate, all via a single command. It comes with a number of benefits out of the box:

  • chiSSL Server
    • Can run on small machines and provide users with 64,511 usable ports
    • Automatically generates, applies, and renews "Let’s Encrypt" SSL certificates
    • No limits on the number of ports per user
    • Ability to restrict available port/address ranges for each user
    • User management REST API (beta)
    • User management CLI (beta)
    • Static domain
  • chiSSL Client
    • Unlimited number of connections and ports per user
    • Supports configuration files
    • Allows users to inspect the traffic sent over tunnels

chiSSL is inexpensive to run (~$10 a month) and fast to configure. You can run the command below, or put your configuration in a yaml file and simply run chissl client.

chissl client --auth Username:Password  https://your.custom-domain.com "PublicPort1->LocalPort1" "PublicPort2->LocalPort2"

# Test 
curl https://your.custom-domain.com:PublicPort1
curl https://your.custom-domain.com:PublicPort2

Getting Started with chiSSL

chiSSL Server Installation

Requirements
  1. Linux server with minimum 1vCPU and 0.5GB RAM
  2. Fully qualified domain name for your sever
    • For this example, let’s assume the server is your.domain.com
Installation
  1. Switch to a privileged user sudo su
  2. Run installation script
  3. # Usage: 
    # <domain_name> argument must be set to server fqdn 
    # [port] argument is optional (defaults to 443)
    # bash <(curl -s https://raw.githubusercontent.com/NextChapterSoftware/chissl/main/server_installer.sh) <domain_name> [port]
    # e.g 
    
    bash <(curl -s https://raw.githubusercontent.com/NextChapterSoftware/chissl/main/server_installer.sh) your.domain.com
  4. Default admin user credentials will be stored at /etc/chissl.json
  5. Verify the service is running sudo systemctl status chisel
  6. Verify HTTPS health endpoint
  7. ➜  ~ curl https://your.domain.com/health
    OK

chiSSL Client Installation

Installation
  1. Install the binary
  2. # Add brew tap 
    brew tap nextchaptersoftware/chissl https://github.com/NextChapterSoftware/chissl
    
    # Install chiSSL 
    brew install chissl
  3. Create configuration directory mkdir ~/.chissl/
  4. Retrieve the default admin password from /etc/chissl.json on the server
  5. Create your profile.yaml at ~/.chissl/profile.yaml
  6. auth: "admin:ADMIN_PASS"          
    server: "https://your.domain.com"
    remotes:
      - "9000->80:neverssl.com"      # Test endpoint to verify installation
      - "8999->8000"                 # Listening port for Webhook test service
                                     # which will receive events from Slack
    verbose: true
  7. Verify everything is working as expected
    1. Run chissl client
    2. Browse to https://your.domain.com:9000
    3. You should now see neverssl.com loading with a valid SSL certificate! 😄

Using chiSSL

Let’s again use Slack webhooks as an example to show how chiSSL works. In the last step we configured chiSSL to forward all traffic arriving at server port 8999 to 8000 on a local machine. Now we can use Netcat to simulate the Webhook server.

sudo nc -lk 8000

Once that’s completed, all we need now is to have Slack fire Webhooks athttps://your.domain.com:8999. For simplicity, let’s use the legacy Outgoing Webhook app on Slack and configure it as follows:

  • Select the channel we want to fire Webhooks and add the integration
  • Chose a trigger word (we chose Hey)
  • Finally, add the public url https://your.domain.com:8999 and save

To test, post the webhook trigger word to the Slack channel.

Netcat output (simulating a server receiving Webhooks):

➜  ~ nc -lk 8000
POST / HTTP/1.1
Host: REDACTED:8999
User-Agent: Slackbot 1.0 (+https://api.slack.com/robots)
Accept: */*
Accept-Encoding: gzip,deflate
Content-Length: 247
Content-Type: application/x-www-form-urlencoded

token=REDACTED&team_id=REDACTED&team_domain=REDACTED&service_id=REDACTED&channel_id=REDACTED&channel_name=mahdi-webhook-test&timestamp=1717101726.601749&user_id=REDACTED&user_name=mahdi&text=Hey&trigger_word=Hey

chiSSL client output with payload inspection enabled:

➜  ~ chissl client
2024/05/30 13:41:25 client: Connecting to wss://REDACTED:443
2024/05/30 13:41:25 client: tun: proxy#9000=>neverssl.com:80: Listening
2024/05/30 13:41:25 client: tun: proxy#8999=>8000: Listening
2024/05/30 13:41:25 client: tun: Bound proxies
2024/05/30 13:41:25 client: Handshaking...
2024/05/30 13:41:26 client: Sending config
2024/05/30 13:41:26 client: Connected (Latency 124.321334ms)
2024/05/30 13:41:26 client: tun: SSH connected
2024/05/30 13:42:07 client: tun: conn#1: Open [1/1]
2024/05/30 13:42:07 client: tun: conn#1:
================== Host: 127.0.0.1:8000 : Read ==================
POST / HTTP/1.1
Host: REDACTED:8999
User-Agent: Slackbot 1.0 (+https://api.slack.com/robots)
Accept: */*
Accept-Encoding: gzip,deflate
Content-Length: 247
Content-Type: application/x-www-form-urlencoded

token=REDACTED&team_id=REDACTED&team_domain=REDACTED&service_id=REDACTED&channel_id=REDACTED&channel_name=mahdi-webhook-test&timestamp=1717101726.601749&user_id=REDACTED&user_name=mahdi&text=Hey&trigger_word=Hey
2024/05/30 13:42:36 client: tun: conn#1: sent 481B received 0B
2024/05/30 13:42:36 client: tun: conn#1: Close [0/1]

chiSSL is now available on GitHub, where you can find more information about its features, get started using it, and share your feedback.