错误:在 AWS lambda 函数中使用 ssh2-sftp-client 连接到 SFTP 服务器会引发超时



我正在尝试连接到SFTP服务器并列出/ARCHIVE文件夹中的文档。凭据存储在 .env 文件中。当我在本地计算机上运行它时,它可以工作并列出文档。

async function main (event){
let Client = require('ssh2-sftp-client');
let sftp = new Client();
const dotenv = require('dotenv');
dotenv.config();
const ftpOptions = {
host: process.env.FTP_HOST,
port: process.env.FTP_PORT,
username: process.env.FTP_USER,
password: process.env.FTP_PASSWORD,
debug: console.log
}
await sftp.connect(ftpOptions);
let documentList = await sftp.list('/ARCHIVE');
console.log(documentList);
sftp.end();
}

但是,如果我在我的 AWS lambda 函数中尝试它,它会尝试连接并超时。env 变量在执行sftp.connect(ftpOptions)之前加载并可用。日志显示该函数正在尝试连接到服务器,但甚至无法使用凭据登录。

Function Logs:
START RequestId: 20d3c3b7-19d8-49cf-8997-1f2331eb0b6e Version: $LATEST
2020-06-04T08:27:12.837Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    Debugging turned on
2020-06-04T08:27:12.860Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    DEBUG: Local ident: 'SSH-2.0-ssh2js0.4.10'
2020-06-04T08:27:12.898Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    DEBUG: Client: Trying ftp_foo.com on port 22 ...
2020-06-04T08:27:32.929Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    CLIENT[sftp]: Connection attempt 1 failed. Trying again.
2020-06-04T08:27:33.931Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    DEBUG: Local ident: 'SSH-2.0-ssh2js0.4.10'
2020-06-04T08:27:33.931Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    DEBUG: Client: Trying ftp_foo.com on port 22 ...
2020-06-04T08:27:53.951Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    INFO    CLIENT[sftp]: Exhausted all connection attempts. Giving up
2020-06-04T08:27:53.957Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    ERROR   Invoke Error    {"errorType":"Error","errorMessage":"connect: Timed out while waiting for handshake after 2 attempts","code":"ERR_GENERIC_CLIENT","custom":true,"stack":["Error: connect: Timed out while waiting for handshake after 2 attempts","    at Object.formatError (/var/task/node_modules/ssh2-sftp-client/src/utils.js:62:18)","    at Client.connectErrorListener (/var/task/node_modules/ssh2-sftp-client/src/index.js:98:21)","    at Object.onceWrapper (events.js:417:26)","    at Client.emit (events.js:310:20)","    at Timeout._onTimeout (/var/task/node_modules/ssh2/lib/client.js:697:14)","    at listOnTimeout (internal/timers.js:549:17)","    at processTimers (internal/timers.js:492:7)"]}
2020-06-04T08:27:53.959Z    20d3c3b7-19d8-49cf-8997-1f2331eb0b6e    ERROR   Unhandled Promise Rejection     {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error: end: No SFTP connection available","reason":{"errorType":"Error","errorMessage":"end: No SFTP connection available","code":"ERR_NOT_CONNECTED","custom":true,"stack":["Error: end: No SFTP connection available","    at formatError (/var/task/node_modules/ssh2-sftp-client/src/utils.js:62:18)","    at Object.haveConnection (/var/task/node_modules/ssh2-sftp-client/src/utils.js:612:20)","    at /var/task/node_modules/ssh2-sftp-client/src/index.js:1248:19","    at new Promise (<anonymous>)","    at SftpClient.end (/var/task/node_modules/ssh2-sftp-client/src/index.js:1236:12)","    at downloadPDFs (/var/task/index.js:40:14)","    at processTicksAndRejections (internal/process/task_queues.js:97:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: end: No SFTP connection available","    at process.<anonymous> (/var/runtime/index.js:35:15)","    at process.emit (events.js:310:20)","    at processPromiseRejections (internal/process/promises.js:209:33)","    at processTicksAndRejections (internal/process/task_queues.js:98:32)"]}
[ERROR] [1591259273978] LAMBDA_RUNTIME Failed to post handler success response. Http response code: 403.

我的本地机器上是否发生了一些事情来提供我没有在lambda函数中实现的连接?

问题可能是您的 Lambda 函数无法访问 SFTP 主机。

此 SFTP 服务器托管在 AWS 外部还是您的账户内?

如果它托管在互联网上,而不是由您在 AWS 上托管,您可以执行以下操作:

  1. 创建公有 VPC [如果您已有公有 VPC,请跳过此操作]
  2. 在该公有 VPC 中添加 NAT 网关 [如果您已有 NAT 网关,请跳过此操作]
  3. 在 Lambda 函数所在的 VPC 中,添加一个路由表,通过将目标设置为0.0.0.0/0并将目标设置为我们在步骤 2 中创建的 NAT 网关,将流量重定向到 NAT 网关。

您可以访问此 AWS 文章,找到有关如何向 Lambda 函数添加互联网连接的详细答案:如何在 VPC 中授予对 Lambda 函数的互联网访问权限?

如果 SFTP 服务器已由您在 AWS 中托管,则只需使用 AWS 安全组添加对它的访问权限即可。

查看这篇文章,了解如何将 Lambda 与其他 AWS 服务连接(它使用 RDS,但您可以对 SFTP 服务器遵循相同的逻辑(: 配置 Lambda 函数以访问 Amazon VPC 中的 Amazon RDS

此外,请确保将 Lambda 超时设置为足够长,以允许与外部 SFTP 服务器连接和交换数据。

适用于

AWS 外部 SFTP 服务器的解决方案

正如@Atef之前提到的,问题是SFTP服务器托管在AWS之外,并且仅授予对白名单IP的访问权限。所以我使用了以下解决方法:

使用 VPC 为 Lambda 函数配置静态 IP

  1. 打开专有网络管理控制台
  2. 创建弹性 IP
  3. 使用向导创建 VPC("具有私有子网和公有子网"(
  4. 将弹性 IP 附加到 VPC("弹性 IP 分配 ID"(
  5. 使用路由表将您的私有子网和公有子网从 0.0.0.0/0 路由到弹性 IP
  6. 创建互联网网关并将其附加到 VPC
  7. 将 Lambda 函数附加到专有网络
    1. 为您的 lambda 服务的角色授予权限AWSLambdaVPCAccessExecutionRoleAmazonEC2FullAccess

您可以通过从函数调用 ipify API 并检查 HTTP 响应中提供的 ip 来测试这一点。它应该与您的弹性 IP 相同。现在,您可以将此 IP 列入白名单以访问 SFTP 服务器。

有关详细信息,另请参阅此文章。

我通过谷歌提出了这个问题,但即使在查看了Alex Strutz和Atef的答案后仍然被困住了。

如果您在已预先配置的环境中工作,则除了确保 NAT、安全组和互联网网关存在之外,您还需要检查 Lambda ENI 正在使用的子网和 NAT 网关所在的子网上存在的网络 ACL。

如果您仍然遇到问题,那么我建议您使用 AWS 可达性分析器来帮助您进行调试 - 这是一个很好的工具,可以一次性检查配置的多个部分。我已经在我的网站上写过如何将可达性分析器与 Lambda 一起使用(太长了,无法在此处包含(。

相关内容

  • 没有找到相关文章

最新更新