Aller au contenu

sslh

Overview

sslh is a protocol multiplexer that accepts incoming connections on a single port and routes them to appropriate backends based on protocol detection. This allows running multiple services (HTTPS, SSH, OpenVPN, etc.) on the same port 443.

Key Features

  • Multiplex multiple protocols on single port
  • Transparent protocol detection
  • Load balancing capabilities
  • IPv4 and IPv6 support
  • TLS/SSL certificate forwarding
  • HTTPS, SSH, OpenVPN, Xmpp support
  • Lightweight and efficient
  • Systemd integration
  • ACL-based routing

Use Cases

  • Unified port access for multiple services
  • Firewall policy compliance (single port)
  • Network security with limited open ports
  • Accessing services through restrictive firewalls
  • Server consolidation
  • Penetration testing from restricted networks

Installation

Linux/Debian-based

sudo apt-get update
sudo apt-get install sslh

macOS

brew install sslh

CentOS/RHEL

sudo yum install sslh

Build from Source

git clone https://github.com/yob/sslh.git
cd sslh
make
sudo make install

Configuration

Basic Configuration File

Default location: /etc/sslh/sslh.cfg

# sslh configuration file
verbose: false;
foreground: false;
inetd: false;
numeric: true;

# Listen on port 443 for all incoming connections
listen:
(
    { host: "0.0.0.0"; port: "443"; }
);

# Protocol-specific backends
protocols:
(
    # HTTPS traffic to Apache
    { name: "https"; host: "localhost"; port: "8443"; },
    
    # SSH traffic to SSH server
    { name: "ssh"; host: "localhost"; port: "22"; },
    
    # OpenVPN
    { name: "openvpn"; host: "localhost"; port: "1194"; },
    
    # XMPP
    { name: "xmpp"; host: "localhost"; port: "5222"; }
);

# Logging
logfile: "/var/log/sslh/sslh.log";
pidfile: "/var/run/sslh.pid";

Listen on Multiple Ports

listen:
(
    { host: "0.0.0.0"; port: "443"; },
    { host: "0.0.0.0"; port: "8443"; },
    { host: "::"; port: "443"; }  # IPv6
);

SSL/TLS Pass-through Configuration

protocols:
(
    {
        name: "https";
        host: "localhost";
        port: "8443";
        sni_hostnames: [ "example.com", "www.example.com" ];
    },
    { name: "ssh"; host: "localhost"; port: "22"; }
);

Basic Usage

Start sslh Service

sudo systemctl start sslh

Enable on Boot

sudo systemctl enable sslh

Check Service Status

sudo systemctl status sslh

View Service Logs

sudo journalctl -u sslh -f

Running sslh Manually

Foreground Mode (Debugging)

sudo sslh -f -v -c /etc/sslh/sslh.cfg

Flags:

  • -f: Foreground (don’t daemonize)
  • -v: Verbose output
  • -c: Configuration file path

Background Mode

sudo sslh -c /etc/sslh/sslh.cfg

Test Configuration

sudo sslh -t -c /etc/sslh/sslh.cfg

Validates configuration without starting service.

Routing Configurations

HTTPS + SSH on Port 443

protocols:
(
    { name: "https"; host: "localhost"; port: "8443"; },
    { name: "ssh"; host: "localhost"; port: "22"; }
);

Upstream services needed:

  • HTTPS web server on port 8443
  • SSH server on port 22

HTTPS + SSH + OpenVPN + XMPP

protocols:
(
    { name: "https"; host: "localhost"; port: "8443"; },
    { name: "ssh"; host: "localhost"; port: "22"; },
    { name: "openvpn"; host: "localhost"; port: "1194"; },
    { name: "xmpp"; host: "localhost"; port: "5222"; }
);

Remote Server Routing

protocols:
(
    { 
        name: "https"; 
        host: "10.0.0.5"; 
        port: "8443";
    },
    { 
        name: "ssh"; 
        host: "10.0.0.6"; 
        port: "22";
    }
);

Route to different backend servers by protocol.

Load Balanced HTTPS

protocols:
(
    {
        name: "https";
        host: "localhost";
        port: "8443";
    },
    {
        name: "https";
        host: "localhost";
        port: "8444";
    }
);

Round-robin between multiple web servers.

Client Connection Methods

Connect via SSH Through sslh

# Server running sslh on port 443
ssh -p 443 user@example.com

# Or with specific config
ssh -p 443 -o "StrictHostKeyChecking=no" user@example.com

Connect via HTTPS

curl https://example.com:443/

# Web browser: https://example.com:443

OpenVPN Through sslh

Configure OpenVPN client to connect to:

remote example.com 443
proto tcp

Stunnel Integration (for non-TLS Protocols)

Some protocols need encapsulation in TLS:

# stunnel wrapper for SSH through HTTPS port
[ssh-over-https]
client = yes
accept = localhost:2222
connect = example.com:443

Advanced Configurations

SNI-Based Routing

protocols:
(
    {
        name: "https";
        host: "localhost";
        port: "8443";
        sni_hostnames: [ "api.example.com" ];
    },
    {
        name: "https";
        host: "localhost";
        port: "8445";
        sni_hostnames: [ "www.example.com" ];
    }
);

Routes based on SNI hostname in TLS ClientHello.

Alpha Protocol (Fallback)

protocols:
(
    { name: "https"; host: "localhost"; port: "8443"; },
    { name: "ssh"; host: "localhost"; port: "22"; },
    { name: "tls"; host: "localhost"; port: "443"; }  # Catch-all
);

User-Based ACLs

protocols:
(
    {
        name: "https";
        host: "localhost";
        port: "8443";
        user_filter: [ "user1", "user2" ];
    },
    { name: "ssh"; host: "localhost"; port: "22"; }
);

Inetd Mode (xinetd Integration)

inetd: true;

protocols:
(
    { name: "https"; host: "localhost"; port: "8443"; },
    { name: "ssh"; host: "localhost"; port: "22"; }
);

Setting Up Backend Services

Configure HTTPS Listener

# Apache HTTPS on 8443
sudo a2enmod ssl
sudo a2enmod rewrite

# Create SSL config pointing to port 8443
# in /etc/apache2/sites-available/ssl.conf
<VirtualHost *:8443>
    ServerName example.com
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key
</VirtualHost>
sudo systemctl restart apache2

SSH Server Setup

# Ensure SSH runs on default port 22
sudo nano /etc/ssh/sshd_config
# Port 22

sudo systemctl restart ssh

OpenVPN Backend Configuration

# /etc/openvpn/server.conf
port 1194
proto tcp
ca ca.crt
cert server.crt
key server.key
dh dh.pem

# Point clients to port 443

Certificate Management

# Self-signed certificate for sslh
sudo openssl req -x509 -newkey rsa:2048 \
    -keyout /etc/ssl/private/sslh.key \
    -out /etc/ssl/certs/sslh.crt \
    -days 365 -nodes

Network Configuration

Firewall Rules (iptables)

# Allow incoming on port 443
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow SSH and HTTPS backends
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8443 -j ACCEPT

# Save rules
sudo iptables-save > /etc/iptables/rules.v4

UFW Rules

sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
sudo ufw allow 8443/tcp
sudo ufw enable

IPv6 Support

listen:
(
    { host: "0.0.0.0"; port: "443"; },  # IPv4
    { host: "::"; port: "443"; }         # IPv6
);

Monitoring and Logging

View Real-time Logs

sudo journalctl -u sslh -f

Check Process Status

ps aux | grep sslh

Monitor Connections

sudo netstat -antp | grep 443
# or
sudo ss -antp | grep 443

Enable Verbose Logging

# In /etc/sslh/sslh.cfg
verbose: true;
logfile: "/var/log/sslh/sslh.log";

Log Analysis

# Count connections by protocol
sudo grep "Accepted" /var/log/sslh/sslh.log | \
    awk '{print $NF}' | sort | uniq -c

# Monitor in real-time
sudo tail -f /var/log/sslh/sslh.log

Troubleshooting

Connection Refused

Issue: Clients can’t connect to multiplexed port.

Solution:

# 1. Check sslh is running
sudo systemctl status sslh

# 2. Verify configuration
sudo sslh -t -c /etc/sslh/sslh.cfg

# 3. Check backend services
sudo netstat -antp | grep 8443
sudo netstat -antp | grep 22

# 4. Verify port binding
sudo netstat -antp | grep 443

Protocol Detection Fails

Issue: Traffic routing to wrong backend.

Solution:

# Test with verbose logging
sudo systemctl stop sslh
sudo sslh -f -v -c /etc/sslh/sslh.cfg

# Attempt connection and watch output
# Modify protocol detection if needed

Backend Service Not Responding

Issue: Service exists but sslh can’t route to it.

Solution:

# Test backend connectivity
nc -zv localhost 8443  # HTTPS backend
ssh -p 22 localhost    # SSH backend

# Verify firewall allows traffic
sudo iptables -L -n | grep 8443

# Check backend service configuration
sudo lsof -i :8443

High CPU Usage

Issue: sslh consuming excessive CPU.

Solution:

# Check for connection storms
sudo netstat -antp | grep 443 | wc -l

# Implement rate limiting
sudo iptables -A INPUT -p tcp --dport 443 \
    -m limit --limit 100/second --limit-burst 200 -j ACCEPT

# Monitor process
top -p $(pidof sslh)

Performance Optimization

Connection Limits

# Increase file descriptor limit
sudo ulimit -n 65536

# Make permanent in /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536

TCP Tuning

# Optimize for connection multiplexing
sudo sysctl -w net.core.somaxconn=4096
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=4096

Multiple sslh Instances

# Run multiple multiplexers for load distribution
sudo sslh -l localhost:1443 &
sudo sslh -l localhost:1444 &

# Load balance with nginx upstream
upstream sslh {
    server localhost:1443;
    server localhost:1444;
}

Security Best Practices

PracticeReason
Use firewall rulesRestrict access to multiplexer
Monitor logsDetect suspicious patterns
Validate certificatesEnsure backend authenticity
Rate limit connectionsPrevent DoS attacks
Keep updatedSecurity patches and bug fixes

Restrict Backend Access

# Only allow sslh to connect to backends
sudo iptables -A INPUT -p tcp --dport 8443 \
    -s localhost -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8443 -j DROP

Integration Examples

With nginx

upstream http_backend {
    server localhost:8443;
}

server {
    listen 8443 ssl;
    ssl_certificate /etc/ssl/certs/server.crt;
    ssl_certificate_key /etc/ssl/private/server.key;
    
    location / {
        proxy_pass https://http_backend;
    }
}

With Docker

FROM ubuntu:22.04

RUN apt-get update && apt-get install -y sslh

COPY sslh.cfg /etc/sslh/sslh.cfg
EXPOSE 443

CMD ["sslh", "-f", "-c", "/etc/sslh/sslh.cfg"]

Docker Compose

version: '3'
services:
  sslh:
    image: sslh:latest
    ports:
      - "443:443"
    volumes:
      - ./sslh.cfg:/etc/sslh/sslh.cfg
    depends_on:
      - web
      - ssh
  
  web:
    image: nginx:latest
    expose:
      - "8443"
  
  ssh:
    image: linux:ssh
    expose:
      - "22"

References

Quick Reference

# Start service
sudo systemctl start sslh

# Test configuration
sudo sslh -t -c /etc/sslh/sslh.cfg

# Run in foreground with verbose output
sudo sslh -f -v -c /etc/sslh/sslh.cfg

# Connect via SSH (multiplexed)
ssh -p 443 user@server

# Connect via HTTPS
curl https://server:443/

# View logs
sudo journalctl -u sslh -f

# Monitor connections
sudo ss -antp | grep 443