1

我正在尝试连接到 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 函数中实现的连接?

4

2 回答 2

1

适用于 AWS 之外的 SFTP 服务器的解决方案

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

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

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

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

有关详细信息,另请参阅这篇文章

于 2020-06-04T10:26:18.280 回答
0

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

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

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

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

您可以通过访问这篇 AWS 文章找到有关如何将 Internet 连接添加到您的 Lambda 函数的详细答案:如何在 VPC 中为我的 Lambda 函数提供 Internet 访问权限?

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

查看这篇文章,了解如何将 Lambda 与另一个 AWS 服务连接(它使用 RDS,但您可以使用 SFTP 服务器遵循相同的逻辑):Configuring a Lambda function to access Amazon RDS in an Amazon VPC

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

于 2020-06-04T08:52:50.027 回答