You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSHD动态管控端口转发:如何获取客户端-L参数并实现基于权限的访问限制

SSHD动态管控端口转发:如何获取客户端-L参数并实现基于权限的访问限制

嘿,这个需求太贴合大规模运维的痛点了——静态配置PermitOpen根本扛不住上万用户和数万主机的规模,必须搞动态验证才行。我来给你捋捋可行的方案,尤其是能精准拿到客户端-L参数并做权限校验的方法。

首先得纠正一个误区:你之前尝试的PAM auth阶段拿不到端口转发参数,因为SSH的端口转发请求是用户认证完成之后才会发送给sshd的,auth阶段还没到那一步呢,所以得换思路。

最优雅的方案:用OpenSSH的PermitOpen exec:动态验证(推荐)

从OpenSSH 7.8版本开始,官方支持了PermitOpen exec:的特性——每次客户端发起端口转发请求(不管是-L本地转发还是其他类型),sshd都会调用你指定的脚本,把目标主机和端口作为参数传进去,脚本返回0就允许转发,非0就直接拒绝。这完全契合你的动态权限校验需求,而且不需要维护任何静态列表!

具体操作步骤:

  1. 修改sshd_config配置
    在你的跳板机sshd配置文件里添加这两行:

    AllowTcpForwarding yes
    PermitOpen exec:/usr/local/bin/check_permitopen.sh
    

    注意:如果之前有PermitOpen的其他配置,要替换掉,因为这个参数是排他的。

  2. 编写权限校验脚本
    创建/usr/local/bin/check_permitopen.sh脚本,内容如下:

    #!/bin/bash
    # 脚本会自动接收sshd传递的两个参数:目标主机、目标端口
    TARGET_HOST="$1"
    TARGET_PORT="$2"
    # 获取当前登录的用户名(sshd会以登录用户身份执行这个脚本)
    CURRENT_USER="$USER"
    
    # 调用你的权限校验工具
    if /path/to/can_access "$CURRENT_USER" "$TARGET_HOST"; then
        # 权限通过,允许转发
        exit 0
    else
        # 权限不通过,拒绝转发
        echo "You are not authorized to access $TARGET_HOST" >&2
        exit 1
    fi
    

    给脚本加上执行权限:

    chmod +x /usr/local/bin/check_permitopen.sh
    
  3. 测试验证
    从你的工作站执行:

    ssh -NL 1234:my-server:3389 the-jumphost
    

    如果can_access脚本返回允许,转发就能正常建立;如果返回拒绝,sshd会直接断开这个转发请求,用户连不上敏感主机。

兼容旧版本OpenSSH的方案:ForceCommand+进程端口解析

如果你的跳板机OpenSSH版本低于7.8,没法用上面的特性,那就用ForceCommand来拦截所有会话,然后解析当前SSH进程的端口转发信息。

  1. 修改sshd_config
    添加:

    ForceCommand /usr/local/bin/validate_forwards.sh
    

    这个配置会让所有登录的用户先执行你的校验脚本,再进入shell(如果需要的话)。

  2. 编写校验脚本
    validate_forwards.sh的核心逻辑是找到当前SSH会话对应的sshd进程,然后解析它的端口转发目标:

    #!/bin/bash
    CURRENT_USER="$USER"
    # 获取当前会话的sshd父进程ID(因为ForceCommand脚本是sshd子进程的子进程)
    SSHD_PID="$PPID"
    
    # 用ss命令找到这个sshd进程关联的所有端口转发
    # 输出格式类似:LISTEN 0      128          127.0.0.1:1234      0.0.0.0:*    users:(("sshd",pid=1234,fd=6))
    FORWARDS=$(ss -tulpn | grep "pid=$SSHD_PID")
    
    # 解析每个转发的目标主机
    while read -r LINE; do
        # 提取目标地址(比如从"-> my-server:3389"里拿到my-server)
        # 这里的解析逻辑可能需要根据ss命令的输出格式调整
        TARGET=$(echo "$LINE" | grep -oP '-> \K[^:]+')
        if [ -n "$TARGET" ]; then
            if ! /path/to/can_access "$CURRENT_USER" "$TARGET"; then
                echo "Unauthorized access to $TARGET" >&2
                exit 1
            fi
        fi
    done <<< "$FORWARDS"
    
    # 校验通过,放行到shell
    exec "$SHELL"
    

    同样给脚本加执行权限,然后测试即可。

注意事项

  • 如果你不需要用户登录跳板机的shell,只允许端口转发,可以在sshd_config里加上PermitTTY no,这样用户连上来只能做转发,没法打开终端。
  • 对于反向转发(-R),如果需要限制,同样可以用PermitOpen exec:的方案,只要调整脚本的校验逻辑就行。
  • 确保can_access脚本的权限正确,只能被root或者特定用户执行,避免被篡改。

备注:内容来源于stack exchange,提问作者John Oxley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 09:24:36