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

PHP通过SSH隧道访问SFTP/SSH的认证失败问题求助

问题描述

我的PHP服务器无法直接连接互联网,必须通过AdminServer建立SSH隧道才能访问外部SFTP/SSH服务器。在Bash中使用ssh -J命令可以成功建立跳转连接,但PHP代码实现时遇到问题——通过ssh2_tunnel创建隧道后,用ssh2_auth_password认证目标SFTP/SSH账户时触发错误:

PHP Warning: ssh2_auth_password(): supplied resource is not a valid SSH2 Session resource

导致认证失败。查阅ssh2_sftp相关文档未找到隧道相关解决方案,特此求助。

初始SFTP测试代码

<?php
$connection = ssh2_connect("172.16.0.2", 22); // AdminServer
if(ssh2_auth_password($connection, "user", "password"))
{
    if ($tunnel = ssh2_tunnel($connection, "sftpservice.domain.com", 22)) // SFTP server
    {
        echo "tunnel ok";
        // 如何认证SFTP?
        if (ssh2_auth_password($tunnel, "sftp_user", "sftp_password")) {
            echo "auth sftp";
        }
        else {
            echo "passwd tunnel fail";
        }
    }
    else {
        echo "Tunnel creation failed.\n";
    }
}
else
{
    echo "failed!";
}
?>

初始测试结果

  • tunnel ok
  • PHP Warning: ssh2_auth_password(): supplied resource is not a valid SSH2 Session resource in /var/www/sftp_test.php on line 11
  • auth sftp fail

可行的Bash跳转命令

tunnel_ip='172.16.0.2'
tunnel_port='22'
tunnel_user='xxx';
tunnel_pwd='abc'

ssh_ip='ip_addresse'
ssh_port='5962'
ssh_user='xyz'
ssh_pwd='abc'

# 此命令可正常执行
ssh -J ${tunnel_user}@${tunnel_ip} -p ${ssh_port} ${ssh_user}@${ssh_ip}

SSH连接测试PHP代码

$connection = ssh2_connect($tunnel_ip, $tunnel_port);
if(ssh2_auth_password($connection, $tunnel_user, $tunnel_pwd))
{
    echo "* connection $tunnel_ip ok \n";
    if ($tunnel = ssh2_tunnel($connection, $ssh_ip, $ssh_port))
    {
        echo "* tunnel ok \n";

        if (ssh2_auth_password($tunnel, $ssh_user, $ssh_pwd)) {
            echo "* auth ssh ok \n";
        }
        else {
            echo "* auth ssh fail \n";
        }
    }
    else {
        echo "* tunnel creation failed.\n";
    }
}
else
{
    echo "* connection $tunnel_ip fail \n";
}

SSH测试结果

  • tunnel ok
  • PHP Warning: ssh2_auth_password(): supplied resource is not a valid SSH2 Session resource in /var/www/test.php on line 22
  • auth ssh fail

解决方案

问题根源

原生PHP ssh2扩展的ssh2_tunnel仅创建TCP层的隧道连接,返回的是流资源,而非SSH会话资源。ssh2_auth_password仅能接收ssh2_connect返回的SSH会话对象,因此直接用隧道流调用该方法会报错。

方案1:调用系统ssh命令实现端口转发

通过PHP执行系统ssh命令建立本地端口转发,再连接本地转发端口访问目标服务器,模拟ssh -J的跳转逻辑:

<?php
// 配置参数
$jumpHost = '172.16.0.2';
$jumpUser = 'user';
$jumpPass = 'password';
$targetHost = 'sftpservice.domain.com';
$targetPort = 22;
$targetUser = 'sftp_user';
$targetPass = 'sftp_password';
$localPort = 2222; // 本地临时转发端口

// 用sshpass实现非交互式输入密码,建立端口转发并后台运行
$cmd = "sshpass -p '$jumpPass' ssh -L $localPort:$targetHost:$targetPort $jumpUser@$jumpHost -Nf";
exec($cmd, $output, $returnVar);

if ($returnVar === 0) {
    // 连接本地转发端口,等同于直接连接目标服务器
    $connection = ssh2_connect('localhost', $localPort);
    if ($connection && ssh2_auth_password($connection, $targetUser, $targetPass)) {
        echo "SFTP认证成功\n";
        // 后续可执行SFTP操作
        $sftp = ssh2_sftp($connection);
        // 示例:读取目标文件
        $file = fopen("ssh2.sftp://$sftp/path/to/file", 'r');
        // ...
    } else {
        echo "SFTP认证失败\n";
    }
    // 关闭隧道(按需保留,若长期使用可省略此步骤)
    exec("pkill -f 'ssh -L $localPort:$targetHost:$targetPort'");
} else {
    echo "建立端口转发失败\n";
}
?>

注意:需在服务器安装sshpass工具,或提前配置PHP服务器与AdminServer的SSH免密登录,避免明文密码风险。

方案2:使用phpseclib库(推荐)

原生ssh2扩展对跳转连接支持有限,phpseclib的SSH2类原生支持ProxyJump功能,实现更简洁安全:

<?php
require_once 'vendor/autoload.php'; // 需通过Composer安装

use phpseclib3\Net\SSH2;
use phpseclib3\Net\SFTP;

// 跳板机配置
$jumpHost = '172.16.0.2';
$jumpUser = 'user';
$jumpPass = 'password';

// 目标SFTP服务器配置
$targetHost = 'sftpservice.domain.com';
$targetUser = 'sftp_user';
$targetPass = 'sftp_password';

// 连接跳板机
$jumpSSH = new SSH2($jumpHost);
if (!$jumpSSH->login($jumpUser, $jumpPass)) {
    exit('跳板机登录失败');
}

// 通过跳板机连接目标SFTP服务器
$sftp = new SFTP($targetHost, 22, ['proxy' => $jumpSSH]);
if ($sftp->login($targetUser, $targetPass)) {
    echo "SFTP认证成功\n";
    // 示例:列出目标服务器根目录
    print_r($sftp->nlist('/'));
} else {
    echo "SFTP认证失败\n";
}
?>

安装方式:在项目目录执行composer require phpseclib/phpseclib:^3.0


内容的提问来源于stack exchange,提问作者BeWog

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 10:15:38