In modern development environments, we often need to access multiple SSH servers while maintaining strict firewall policies. Traditional approaches like port forwarding (e.g., mapping server1:22 → gateway:2222, server2:22 → gateway:2223) quickly become unmanageable and violate security best practices by exposing multiple ports.
The HTTP world solved this elegantly with name-based virtual hosting in reverse proxies like Nginx or HAProxy. A single port (80/443) serves multiple websites based on the Host header. We need similar functionality for SSH connections.
While HAProxy doesn't natively support SSH proxying, several specialized tools can achieve this:
1. SSH ProxyCommand with Host Headers
Combine SSH's ProxyCommand with a lightweight HTTP server to route connections:
# ~/.ssh/config Host *.dev.example.com ProxyCommand curl -s -H "Host: %h" http://gateway.example.com/ssh-route | nc -U /var/run/sshgate.sock
2. SNI-Based SSH Routing
Leverage TLS SNI extension with tools like:
# socat example for SNI routing socat openssl-listen:2222,reuseaddr,cert=gateway.pem,fork \ openssl-connect:$(openssl s_client -connect $DESTINATION:2222 -servername $SNI -tlsextdebug 2>&1 | grep -i '^subject' | cut -d= -f4).internal:22
3. Custom SSH Gateway with Go
Here's a basic implementation in Go:
package main import ( "net" "strings" ) func main() { ln, _ := net.Listen("tcp", ":2222") for { conn, _ := ln.Accept() go handleConnection(conn) } } func handleConnection(conn net.Conn) { // Parse initial SSH protocol exchange to extract hostname buf := make([]byte, 256) n, _ := conn.Read(buf) hostname := extractHostname(buf[:n]) // Route to backend backend, _ := net.Dial("tcp", hostname+":22") go copyStream(conn, backend) go copyStream(backend, conn) }
For enterprise environments, consider:
- Teleport: Open-source SSH gateway with RBAC
- Apache Guacamole: Web-based SSH gateway
- Bastillion: Centralized SSH management
When implementing any SSH proxy solution:
- Always use TLS for the outer connection
- Implement rate limiting
- Use certificate-based authentication
- Log all connection attempts
In modern development environments, managing SSH access for multiple teams or projects often leads to port explosion. While HTTP reverse proxies like Nginx or HAProxy elegantly solve this for web traffic using name-based virtual hosting, SSH traditionally requires either:
- Different ports for each backend (e.g., 22, 2222, 2223)
- Complex SSH tunneling configurations
- Individual user management on jump hosts
We can implement name-based SSH routing using:
Client → (SSH on port 22) → Reverse Proxy → (Proper backend based on SNI/hostname)
Modern SSH clients (OpenSSH 7.7+) support TLS-style SNI extensions. Here's how to leverage this:
# On the proxy server (using OpenSSH 8.0+)
Match Host *.dev-env.example.com
ProxyJump backend-%h:22
# In ssh_config for clients
Host *.dev-env.example.com
HostName ssh-gateway.example.com
Port 22
RequestTTY force
RemoteCommand ssh $(echo %h | sed 's/\\.dev-env//')
While HAProxy primarily handles HTTP, its TCP mode can route SSH:
frontend ssh-in
bind *:22
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
use_backend team1_ssh if { req_ssl_sni -i team1.dev-env.example.com }
use_backend team2_ssh if { req_ssl_sni -i team2.dev-env.example.com }
backend team1_ssh
mode tcp
server team1-server 192.168.1.10:22 check
backend team2_ssh
mode tcp
server team2-server 192.168.1.20:22 check
For restricted networks, consider wrapping SSH in HTTPS:
# Client-side config using corkscrew
Host restricted-ssh
HostName your-proxy.example.com
Port 443
ProxyCommand corkscrew %h %p ~/.ssh/proxy-auth
# Server-side (Nginx config)
location /ssh-proxy {
proxy_pass http://backend-ssh;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
- Always use SSH certificate-based authentication at the proxy level
- Implement rate limiting to prevent brute force attacks
- Log all connection attempts with timestamps and source IPs
- Consider using port knocking for additional security layer