lftpで “Not connected”が起きた時の対処法

## 状況の説明
* AWSのEC2インスタンスでFTPSを設定 (OpenSSLで自己署名証明書を利用) しているときにこのエラーが発生。WSLからlftpというFTPクライアントツールを使用してパッシブモードで接続する。lftpでlsコマンドを実行したらタイトルのエラーになる。暗号化を行わない単なるFTP接続と、アップロードは既にできている。

* FTPの宛先のグローバルIPアドレスの指定や、ポートの解放 (クライアント側のufw、サーバー側の firewalld、EC2のセキュリティグループのインバウンドルール）は既におこなっている。

* FTPSの暗号化は、Expicitモードを使用する予定 (コントロールコネクションに使用するポート番号は 21）。

## 環境
ローカルOS: WSLのUbuntu-24.04
リモートOS: Amazon Linux 2023
vsftpd: version __3.0.5__
openssl __3.0.8__

## lftpの設定ファイルの内容
この投稿の最初の状態の設定を以下に示します。（一部を抜粋）
``` /etc/lftp.conf
set ftp:port-ipv4 <your.server.public.ipaddress>
set ftp:port-range <min-max> # パッシブモードで使用するポート番号の範囲を設定
set ftp:ssl-auth TLS
set ftp:ssl-force true
set ftp:ssl-allow true
set ftp:ssl-protect-list true
set ftp:ssl-protect-data true
set ftp:ssl-protect-fxp true
set ftp:passive-mode true # パッシブモードを使用
set ssl:verify-certificate false # 自己署名証明書のため、検証をしない
```

### 仮説 1
クライアント側でデータコネクションへの接続や再ネゴシエーションが失敗している。

### 確認すること (その 1)

【**前提**】__vsftpd.confで再ネゴシエーションにおけるセッションの再利用を必須にしないように設定していることを確認__

すべてのクライアントがセッションの再利用に対応しているわけではないので（curlなど）、オフ(NO)にしている

#### まずSSLを無効にしてみる
原因の切り分けのため、SSLを無効にします。

``` .bash
lftp -e "set ftp:ssl-allow off;" -u username ftp://xx.xx.xx.134
:~> ls
```

これで`ls`コマンドがうまくいく場合、SSLまわりを見直す必要があります。

#### ftp（FTPクライアント）から見た宛先のIPアドレスを確認

宛先がパッシブモードの転送先サーバーのグローバルIPアドレスであることを確認する
* SSLをオンにした場合、opensslやhttpdの設定でところどころ `localhost`を指定する箇所がある。クライアントから見た`localhost`のIPアドレスに接続しようとしてFTPが失敗しているのかもしれない。

``` .bash
# URLにグローバルIPアドレスを指定して接続する
lftp -u ftp-user -e "debug 12" ftp://xx.xx.xx.134
Password:
lftp ftp-user@xx.xx.xx.134:~> ls
---- Connecting to xx.xx.xx.134 (xx.xx.xx.134) port 21
<--- 220 (vsFTPd 3.0.5) # グローパルIPアドレスに接続している
......
..........
```

### 仮説 2
サーバー側ではOpenSSLで暗号化スイートを設定しているのに対して、lftpがGnuTLSの暗号化スイートを使用してFTPSで接続しようとしているため、再ネゴシエーションが拒否される

``` .bash
lftp ftp-user@xx.xx.xx.134:~> ls
...
..........
---> AUTH TLS
<--- 234 Proceed with negotiation. # ネゴシエーションが開始される
GNUTLS: added 3 protocols, 29 ciphersuites, 19 sig algos and 10 groups into priority list
Loaded 146 CAs
Loaded 0 CRLs
---> OPTS UTF8 ON
GNUTLS: Keeping ciphersuite 13.02 (GNUTLS_AES_256_GCM_SHA384) # GNUTLS側での暗号化スイートの設定が表示される
GNUTLS: Keeping ciphersuite 13.03 (GNUTLS_CHACHA20_POLY1305_SHA256)
GNUTLS: Keeping ciphersuite 13.01 (GNUTLS_AES_128_GCM_SHA256)
GNUTLS: Keeping ciphersuite 13.04 (GNUTLS_AES_128_CCM_SHA256)
GNUTLS: Keeping ciphersuite c0.2c (GNUTLS_ECDHE_ECDSA_AES_256_GCM_SHA384)
GNUTLS: Keeping ciphersuite cc.a9 (GNUTLS_ECDHE_ECDSA_CHACHA20_POLY1305)
GNUTLS: Keeping ciphersuite c0.ad (GNUTLS_ECDHE_ECDSA_AES_256_CCM)
GNUTLS: Keeping ciphersuite c0.0a (GNUTLS_ECDHE_ECDSA_AES_256_CBC_SHA1)
GNUTLS: Keeping ciphersuite c0.2b (GNUTLS_ECDHE_ECDSA_AES_128_GCM_SHA256)
GNUTLS: Keeping ciphersuite c0.ac (GNUTLS_ECDHE_ECDSA_AES_128_CCM)
GNUTLS: Keeping ciphersuite c0.09 (GNUTLS_ECDHE_ECDSA_AES_128_CBC_SHA1)
GNUTLS: Keeping ciphersuite c0.30 (GNUTLS_ECDHE_RSA_AES_256_GCM_SHA384)
......
..........
```

### 確認すること (その 2)

#### lftpでプロトコルの優先順位を設定する
vsftpdでは TLS v1.3をサポートしていない (サーバー側のOpenSSLでも TLS v1.2を設定している）ため、クライアント側でも TLS v1.2を使用するように設定します。

__lftpでコマンドラインから設定する場合__

``` .bash
# TLS v1.2 を使用するように設定。
lftp ftp-user@xx.xx.xx.134:~> set ssl:priority "NORMAL:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:+VERS-TLS1.2:-VERS-TLS1.3"
lftp ftp-user@xx.xx.xx.134:~> ls

# キャッシュをクリア
lftp -c cache flush
# 再ログイン
lftp -u ftp-user -e "debug 12" ftp://xx.xx.xx.134
Password:
lftp ftp-user@xx.xx.xx.134:~> ls
```

__lftp.confで設定する場合__
```.bash
# あるいは、lftpの設定ファイルに追加
sudo vi /etc/lftp.conf
```

``` /etc/lftp.conf
# プロトコルの優先順位を設定 (TLS v1.2)
set ssl:priority "NORMAL:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:+VERS-TLS1.2:-VERS-TLS1.3"
```

以上の確認&設定をおこなった後、lftpで``ls: Not connected``が解消されたかどうか確認してください。