把经 SOCKS 打开的套接字交给 ssh2
先协商 SOCKS 连接,再在打开 SFTP 子系统之前把它的目标套接字交给 ssh2。
ssh2 通过 sock 选项接受一个已连接的流。让 socksv5 建立通往 SSH 服务器的路由,然后把该流交给 SSH:
const socks = require('socksv5');
const { Client } = require('ssh2');
const connection = socks.connect({
host: sshConfig.host,
port: sshConfig.port || 22,
proxyHost: 'proxy.example',
proxyPort: 1080,
localDNS: false,
auths: [socks.auth.None()],
}, socket => {
const ssh = new Client();
ssh.on('error', error => console.error(error.message));
ssh.on('ready', () => {
ssh.sftp((error, sftp) => {
if (error) {
console.error(error.message);
ssh.end();
return;
}
sftp.readdir('.', (error, entries) => {
if (error) console.error(error.message);
else console.log(entries);
ssh.end();
});
});
});
ssh.connect({ ...sshConfig, sock: socket });
});
connection.on('error', error => console.error(error.message));
sshConfig 是应用现有的 SSH 配置,包括账号、密钥和 hostVerifier 策略。SOCKS 的主机和端口标识中间层;sshConfig.host 和 port 标识最终的 SSH 服务。
示例使用不带认证的 SOCKS 端点。对于可从公网访问的 SSH 服务器,SOCKS5 代理列表可以提供候选;每个候选仍需允许该 SSH 目标和端口。其用户名/密码方式要在 auths 中使用 socks.auth.UserPassword(proxyUser, proxyPassword)。这些凭据并不替代 SSH 账号。
localDNS false 会把目标主机名交给 SOCKS 服务器,即使用代理侧的目标解析。若不做这一明确选择,socksv5 文档所述的默认行为会尝试本地解析。
SOCKS 回调在协商之后运行。要等到 ssh2 的 ready 事件再请求 SFTP。这是两个各自成功的阶段;到代理的 TCP 连接和 SOCKS 应答都不能证明 SSH 认证或 SFTP 子系统已经成功。