SSH端口转发脚本

SSH端口转发脚本

概述

本脚本基于 autossh 工具实现 SSH 端口转发隧道管理,具备以下核心功能:

  • 端口转发:将远程服务器端口暴露至跳板机指定端口,实现内网访问
  • 自动重连:监控 SSH 连接状态,断线后自动重建隧道
  • 多层跳板:支持通过 -J 参数实现多级跳板机穿透

前置条件

  • 跳板机(运行脚本的目标机器)
  • 已安装 autossh 工具
  • SSH 免密登录或密钥认证已配置

安装 autossh

# CentOS / RHEL
yum install -y autossh

# Ubuntu / Debian
apt install -y autossh

脚本源码

将以下脚本保存为 /script/ssh-tunnel(或其他自定义路径),并赋予执行权限:

chmod +x /script/ssh-tunnel
#!/bin/bash
# SSH 隧道转发管理脚本
# 功能:通过跳板机开放端口,将远程服务转发至本地

export AUTOSSH_POLL=60
export AUTOSSH_PORT=0

# 启动所有隧道
function start() {
    # 隧道1:将内网 10.0.0.2 的 SSH 服务,暴露在跳板机 10001 端口
    autossh -M 0 \
        -o "ExitOnForwardFailure yes" \
        -o "ServerAliveInterval 30" \
        -o "ServerAliveCountMax 3" \
        -fNL 0.0.0.0:10001:192.168.1.2:22 root@10.0.0.2

    # 隧道2:通过两层跳板(10.0.0.2 → 172.32.0.2)访问 192.168.1.3:22,
    #         暴露在跳板机 10002 端口
    autossh -M 0 \
        -o "ExitOnForwardFailure yes" \
        -o "ServerAliveInterval 30" \
        -o "ServerAliveCountMax 3" \
        -fNL 0.0.0.0:10002:192.168.1.3:22 \
        -J root@10.0.0.2 root@172.32.0.2
}

# 停止所有隧道
function stop() {
    ps aux | grep -E 'autossh.*-NL' | grep -v grep | awk '{print $2}' | while read pid; do
        kill -9 "$pid"
    done
}

# 列出可用端口
function ls(){
        # 定义端口范围
        START_PORT=10001
        END_PORT=10499

        # 定义需要查找的空闲端口数量
        MAX_FREE=5
        count=0

        echo "正在扫描端口范围 $START_PORT - $END_PORT,查找前 $MAX_FREE 个空闲端口..."

        # 遍历指定范围内的端口
        for port in $(seq $START_PORT $END_PORT); do
                # 使用 ss 命令检查端口是否处于监听状态
                if ! ss -tln | grep -q ":$port "; then
                        echo "端口 $port 空闲"
                        ((count++)) # 计数器加1

                        # 如果已经找到10个空闲端口,退出循环
                        if [ $count -ge $MAX_FREE ]; then
                                break
                        fi
                fi
        done

        echo "扫描完成!共找到 $count 个空闲端口。"
}

# 主入口
case $1 in
    start)
        start
        ;;
    restart)
        stop
        start
        ;;
    stop)
        stop
        ;;
    ls)
        ls
        ;;
    *)
        echo "用法: $0 {start|restart|stop|ls}"
        ;;
esac

使用说明

命令 说明
./ssh-tunnel start 启动所有配置的隧道
./ssh-tunnel stop 停止所有隧道进程
./ssh-tunnel restart 重启所有隧道
./ssh-tunnel ls 列出当前运行的隧道端口及配置

参数详解

参数 含义
-M 0 禁用 autossh 监控端口(配合 ServerAlive 实现存活检测)
-f 后台运行
-N 不执行远程命令(纯转发)
-L 本地端口转发,格式:[本地IP]:本地端口:目标IP:目标端口
-J 跳板机(ProxyJump),多级用空格分隔
ExitOnForwardFailure yes 端口转发失败时退出
ServerAliveInterval 30 每 30 秒发送保活包
ServerAliveCountMax 3 连续 3 次无响应则断开重连

隧道配置示例

单层跳板

autossh -M 0 -fNL 0.0.0.0:10001:192.168.1.2:22 root@10.0.0.2

说明:通过跳板机 10.0.0.2,将远程主机 192.168.1.2 的 22 端口转发到跳板机的 10001 端口。

双层跳板

autossh -M 0 -fNL 0.0.0.0:10002:192.168.1.3:22 -J root@10.0.0.2 root@172.32.0.2

说明:依次通过 10.0.0.2172.32.0.2 两层跳板,访问 192.168.1.3 的 22 端口。


常见问题

Q:为什么使用 -M 0 而不是默认监控端口?

-M 0 会禁用 autossh 自带的监控端口,转而完全依赖 SSH 的 ServerAliveInterval 机制检测连接状态。这种方式更简洁,且避免额外端口占用。

Q:-J 参数的正确格式是什么?

错误写法

-J root@root@10.0.0.2

正确写法

-J root@10.0.0.2 root@172.32.0.2

多级跳板用空格分隔,按顺序依次跳转。

Q:如何添加更多隧道?

start() 函数中参照现有格式追加新的 autossh 命令即可。建议每条隧道使用不同端口,避免冲突。

Q:如何开机自启?

将启动命令添加到 /etc/rc.local 或使用 systemd 服务管理:

# /etc/rc.local
/script/ssh-tunnel start &

参考链接