简体   繁体   English

了解 FTP 项目的 TLS 排列:nodejs 中的 ftp-srv

[英]Understanding TLS arragement for FTP project: ftp-srv in nodejs

I am trying to understand how TLS can be set up accurately for my FTP project (typescript, nodejs) based on this API: ftp-srv我试图了解如何基于此 API 为我的 FTP 项目(打字稿,nodejs)准确设置 TLS: ftp-srv

The documentation there is very basic.那里的文档非常基础。 In one of the related github issues of the project, the author points to his source code / test example - here在项目的相关 github 问题之一中,作者指向他的源代码/测试示例 - 这里

In that example is a section:在该示例中是一个部分:

  describe('#EXPLICIT', function () {
    before(() => {
      return server.close()
      .then(() => Promise.all([
        readFile(`${process.cwd()}/test/cert/server.key`),
        readFile(`${process.cwd()}/test/cert/server.crt`),
        readFile(`${process.cwd()}/test/cert/server.csr`)
      ]))
      .then(([key, cert, ca]) => startServer({
        url: 'ftp://127.0.0.1:8881',
        tls: {key, cert, ca}
      }))
      .then(() => {
        return connectClient({
          secure: true,
          secureOptions: {
            rejectUnauthorized: false,
            checkServerIdentity: () => undefined
          }
        });
      });
    });

From this example I can read that a programmer can create references to 3 crypto files:从这个例子中我可以读到程序员可以创建对 3 个加密文件的引用:

 - ../server.key

 - ../server.crt

 - ../server.csr

than, to read these files and direct their output to a tls object eg:比,读取这些文件并将它们的 output 定向到 tls object 例如:

const tls: SecureContextOptions = {
  key:    <-- readFile('server.key'),
  cert:   <-- readFile('server.crt'),
  ca:     <-- readFile('server.csr'),
}

If this is right (correct me if wrong), I need the understanding of what the 3 files represent from the prospective of TLS.如果这是对的(如果错了,请纠正我),我需要从 TLS 的角度了解这 3 个文件所代表的内容。

TLS for NodeJS documentation is pretty clear - here NodeJS 文档的 TLS 非常清楚 -这里

Following this documentation we create 5 (five) SSL crypto files:根据本文档,我们创建 5(五)个 SSL 加密文件:

file 1:  ryans-key.pem    <--- by command:  openssl genrsa -out ryans-key.pem 2048
file 2:  ryans-csr.pem    <--- by command:  openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem
file 3:  ryans-cert.pem   <--- by command:  openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem
file 4:  ca-cert.pem      <--- by command:  cat ryans-cert.pem > ca-cert.pem
file 5:  ryans.pfx        <--- by command:  openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem -certfile ca-cert.pem -out ryans.pfx

Now, which of these five crypto files go to which property of the 'tls' object?现在,这五个加密文件 go 中的哪一个到“tls”object 的哪个属性? Below here is my assumption and would ask some of you for correction:以下是我的假设,并会要求你们中的一些人进行更正:

const tls: SecureContextOptions = {
  key:    <-- readFile('server.key'),    =  <-- ryans-key.pem   ?
  cert:   <-- readFile('server.crt'),    =  <-- ryans-cert.pem  (or ca-cert.pem)  ?
  ca:     <-- readFile('server.csr'),    =  <-- ryans-csr.pem   ?
}

If other steps are required, please explain.如果需要其他步骤,请说明。

Further, related to this arrangement, which of the five SSL crypto files do I supply to the FTP client, so both, the server and the client are properly configured for a secure FTP communication?此外,与此安排相关,我将五个 SSL 加密文件中的哪一个提供给 FTP 客户端,因此服务器和客户端都正确配置为安全的 ZC728A49363C9A93A54AZ7E7F232B 通信?


I am assuming that this arrangement above, of the crypto files pointing to the properties of the 'tls' object for '#EXPLICIT' connections is practically the same for '#IMPLICIT' connections as well.我假设上面的这种安排,指向“#EXPLICIT”连接的“tls”object 属性的加密文件对于“#IMPLICIT”连接实际上也是相同的。 Please correct me again, if not.请再次纠正我,如果不是。


Last portion of this configuration is selection of the initial URL header.此配置的最后一部分是选择初始 URL header。 The ftp-srv documentations offers: ftp-srv 文档提供:

  • ftp - Plain FTP ftp - 普通 FTP
  • ftps - Implicit FTP over TLS ftps - 基于 TLS 的隐式 FTP

for example:例如:

"ftp://0.0.0.0:21"   or
"ftps://0.0.0.0:21"

It confuses me on how to programmatically organize the selection between:它让我对如何以编程方式组织以下选择感到困惑:

  • pure FTP - no security/TLS involved and,纯 FTP - 不涉及安全/TLS,并且,
  • FTP with TLS via implicit mode and, FTP 通过隐式模式和 TLS,
  • FTP with TLS via explicit mode FTP 通过显式模式使用 TLS

Here is what I figured out and is working.这是我想出的并且正在工作的。

Few understandings 1st. 1、了解少。

  • The FTP server is based on node.js and API: ftp-srv FTP 服务器基于 node.js 和 API: ftp-srv
  • The FTP client is FileZilla FTP 客户端是 FileZilla

The standard config (non TLS) works OK on both client and server as per their documentations.根据他们的文档,标准配置(非 TLS)在客户端和服务器上都可以正常工作。

TLS: TLS:

ftp-srv has two modes: ftp-srv有两种模式:

  • ftp - explicit - recommended (is the same as without TLS) ftp - 显式 - 推荐(与没有 TLS 相同)
  • ftps - implicit - (appears to be going out of fashion) ftps - 隐式 - (似乎过时了)

The TLS - explicit mode - config: TLS - 显式模式 - 配置:

Generate crypto files: See here生成加密文件:见这里

openssl genrsa -out ryans-key.pem 2048
openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem
openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem
cat ryans-cert.pem > ca-cert.pem

In your node.js app (the example is for typescript):在您的 node.js 应用程序中(示例用于打字稿):

import * as path from 'path';
import { promises as fsAsync, readFileSync } from "fs";
import { FtpServerOptions, FtpSrv } from 'ftp-srv';


configureTls(): Promise<SecureContextOptions> {

    const CRYPTO_FILES_DIR = // provide your dir where the crypto files are located
    
    const path_key:  string = path.join(CRYPTO_FILES_DIR , 'ryans-key.pem');
    const path_cert: string = path.join(CRYPTO_FILES_DIR , 'ryans-cert.pem');
    const path_ca:   string = path.join(CRYPTO_FILES_DIR , 'ca-cert.pem');
    
    
    const key:  string = await fsAsync.readFile(path_key,  'utf8');
    const cert: string = await fsAsync.readFile(path_cert, 'utf8');
    const ca:   string = await fsAsync.readFile(path_ca,   'utf8');
    
    
    const tls_ConfigOptions: SecureContextOptions = {
        key:  key,
        cert: cert,
        ca:   ca,
    }
    
    return tls_ConfigOptions;
}

                /**
                 * Start the server and listen for requests / connections
                 */
async startFtpServer() {

                // make this configurable ...
    const url: string = 'ftp://127.0.0.1:21'
    
    const ftpSrvCfg: FtpServerOptions = {
        url:      url,
        pasv_url: pasv_url,
        greeting: greeting,
        ...,
        tls = await this.configureTls()
    }
    
    ...
                // create the server instance with all its configs
    const ftpServer: FtpSrv = new FtpSrv(ftpSrvCfg);

                // FTP server is event driven.
                // Here we register the events we need or want to use.
    this.onUserLogin(ftpServer);
    this.onUserDisconnect(ftpServer);
    this.onClientError(ftpServer);

                // start listening for requests
    ftpServer.listen().then( () => {
                // your actions when the server starts ...
        ...
    }


                /**
                 * Occurs on each (user's) login attempt
                 */
    private onUserLogin(ftpServer: FtpSrv) {

        ftpServer.on('login',
                   async ({ connection, username, password }, resolve, reject) => { 
          ....
        }
    }

 



}

In the client - FileZilla:在客户端 - FileZilla:

  • Click menu - Edit > Settings (Settings box will appear)单击菜单 - 编辑 > 设置(将出现设置框)
  • Choose: Connection > SFTP选择:连接 > SFTP
  • Click: Add key file, and navigate to the private key crypto file: ../ryans-key.pem单击:添加密钥文件,并导航到私钥加密文件:../ryans-key.pem
  • Click: OK点击:确定

Start the server and try to connect.启动服务器并尝试连接。 eg: ftp://127.0.0.1:21例如: ftp://127.0.0.1:21

Should work.应该管用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM