使用 Nginx 的 ngx_stream_proxy_module 模块实现 TCP 级别的 SSH 端口转发,通过 SSL/TLS 加密通道。
# Ubuntu/Debian
sudo apt update
sudo apt install nginx libnginx-mod-stream
# CentOS/RHEL
sudo yum install nginx nginx-mod-stream
编辑 /etc/nginx/nginx.conf,在 http 块同级添加 stream 配置:
# /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
# SSH 代理配置(TCP 层)
stream {
# 上游 SSH 服务器组
upstream ssh_backend {
server 192.168.1.100:22; # 目标服务器1
server 192.168.1.101:22; # 目标服务器2
server 192.168.1.102:22; # 目标服务器3
}
# SSH 代理服务器配置
server {
listen 8022; # 代理监听端口
proxy_pass ssh_backend;
proxy_connect_timeout 30s;
proxy_timeout 1h;
# 可选:SSL/TLS 加密
# ssl_preread on;
# ssl_certificate /path/to/cert.pem;
# ssl_certificate_key /path/to/key.pem;
}
# 基于 SNI 的多域名转发
map $ssl_preread_server_name $backend_name {
host1.example.com 192.168.1.100:22;
host2.example.com 192.168.1.101:22;
default ssh_backend;
}
server {
listen 8023 ssl;
ssl_preread on;
proxy_pass $backend_name;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
}
}
http {
# 原有的 HTTP 配置...
}
# 生成自签名证书
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/ssh-proxy.key \
-out /etc/nginx/ssl/ssh-proxy.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Company/CN=ssh-proxy.example.com"
# 使用 ProxyCommand
ssh -o ProxyCommand="nc -X connect -x nginx-host:8022 %h %p" user@target-host
# 或配置 ~/.ssh/config
Host jump-host
HostName nginx-host
Port 8022
User your-username
方式二:通过 SSL/TLS 连接
# 使用 sslh 或自定义代理
# 安装 sslh(应用层分流)
sudo apt install sslh
# sslh 配置(将 SSH 和 HTTPS 分流到不同端口)
stream {
# 带认证的 SSH 代理
server {
listen 8024;
# 使用 nginx 的 auth 模块或结合 Lua 脚本
# proxy_pass ssh_backend;
# 通过变量控制访问
set $allow_access 0;
# 这里可以结合 nginx 的 http 认证模块
# 或使用 nginx-stream-lua-module
}
}
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
# SSH 隧道配置
stream {
# 日志格式
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr"';
access_log /var/log/nginx/ssh-access.log proxy;
error_log /var/log/nginx/ssh-error.log;
# 目标服务器映射
map $ssl_preread_server_name $target_backend {
web-server 192.168.1.100:22;
db-server 192.168.1.101:22;
app-server 192.168.1.102:22;
default 192.168.1.100:22;
}
# SSL 加密的 SSH 代理
server {
listen 443 ssl reuseport;
ssl_preread on;
proxy_pass $target_backend;
proxy_connect_timeout 30s;
proxy_timeout 2h;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
}
# 明文 SSH 代理(内网使用)
server {
listen 8022 reuseport;
proxy_pass 192.168.1.100:22;
proxy_buffer_size 16k;
}
}
# Web 服务配置
http {
# ... 原有的 HTTP 配置
server {
listen 80;
server_name jump.example.com;
# 跳板机管理页面
location / {
root /usr/share/nginx/html;
index index.html;
}
# SSH over WebSocket 示例(使用 websockify)
location /ssh/ {
proxy_pass http://127.0.0.1:6080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
~/.ssh/config 文件配置:
# 通过 Nginx 代理连接
Host *.internal
ProxyCommand nc -X connect -x nginx-proxy:8022 %h %p
ServerAliveInterval 60
TCPKeepAlive yes
# 具体主机配置
Host web-server
HostName web-server.internal
User admin
Port 22
Host db-server
HostName db-server.internal
User root
Port 22
# 限制访问 IP
server {
listen 8022;
allow 10.0.0.0/8; # 内网 IP 段
allow 192.168.1.0/24;
deny all;
proxy_pass ssh_backend;
# 连接速率限制
proxy_upload_rate 512k;
proxy_download_rate 2m;
}
# 连接数限制
limit_conn_zone $binary_remote_addr zone=ssh_conn:10m;
server {
listen 8022;
limit_conn ssh_conn 5; # 每个 IP 最多 5 个连接
proxy_pass ssh_backend;
}
# 检查配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
# 查看日志
sudo tail -f /var/log/nginx/ssh-access.log
# 测试连接
ssh -p 8022 user@nginx-proxy -t 'ssh user@target-server'
如果需求更复杂,可以考虑:
OpenSSH 内置跳板机:使用 SSH 的ProxyJump 或 ProxyCommand
专业堡垒机:如 Jumpserver、Teleport
SSH over HTTPS:使用 SSLH 或 GoTTY
这种 Nginx 方案适合简单的 TCP 端口转发需求,如果需要完整的会话审计、用户管理、权限控制等功能,建议使用专业的堡垒机解决方案。