メモのページ - チラシの裏メモ 3枚目

通信技術や気になった事を黙々とメモし続ける

Alpine LinuxのFTPで暗号化通信 FTPS編

AndroidスマホにはAndFTPやFtp Server等といったFTPサーバのアプリが存在するものの、自分の環境ではAndroidスマホにデプロイしたAlpine Linuxにて無線LANでFTPサーバとして運用を続けている。
目立ったトラブルは発生せず正常稼動継続中につき少しづつ機能を追加していこうという事で、前回はAwall(iptables)を追加、今回はFTPにて暗号化通信が出来るようvsftpdにFTPSを導入してみた。
FTP通信の暗号化としては、FTPの通信をSSLやTSLで暗号化する「FTPS」と、SSH通信にFTPの通信を乗せる「SFTP」が挙げられる。
今回はvsftpの通信をSSLやTSLで暗号化させる為、FTPSを採用した。


当方の環境
・スマホ(ホスト機):SONY Xperia XZ2 / Android OS 9
・ホスト機の通信環境:WLANと4G回線
・エミュレータ:Limbo PC Emulator 2.10.0
・ゲストOS:alpine-virt-3.14.3-x86.iso
・ソフトウェアキーボード:Androidアプリの「Hacker's Keyboard」
※スマホ内で動作するAlpine LinuxにMacBook Airからsshでログインし設定投入した。
※勿論、VirtualBoxやVMware WorkstationにデプロイしたAlpine Linuxでも当記事の内容で設定可能。


FTPSとは
FTPで送受信するデータをTLSまたはSSLで暗号化する通信プロトコル。
FTPSとはFile Transfer Protocol over SSL/TLSの略称。RFC2228とRFC4217にて標準化されている。
今まではユーザ名やパスワードがクリアテキスト(非暗号化な状態)で流れていたが、FTPSの実装により暗号化された状態で流れる事となる。
FTPSにおいてはポート番号は990を使用しTCPで通信する。今回はvsftpdにて暗号化設定を追加するだけに留め、ポート番号は今まで使ってきた番号22221をそのまま使用する。

Alpine LinuxではOpenSSLではなくLibreSSLが推奨されている為、LibreSSLをインストールした。
LibreSSLはOpenSSLの派生改良版で、2014年にOpenBSDプロジェクトによってLibreSSLプロジェクトが立ち上げられて以降、今も継続して開発が進められている。macOSの現行バージョン(2022年1月1日現在は10.13.6以降)のSSL実装はLibreSSLである。
また、同じ時期にGoogleはOpenSSLの派生改良版であるBoringSSLプロジェクトを立ち上げ、LibreSSLと同様に今も開発が継続している。Android OSバージョン6.0以降SSLの実装はBoringSSLである。
https://gihyo.jp/admin/clip/01/linux_dt/201610/18 Alpine Linux,OpenSSLからLibreSSLへ

FTPサーバへの接続確認は、MacBook Airで動作するFTPクライアント「Cyberduck」を使用した。
作業の流れは、LibreSSLのインストールから始まりSSLの秘密鍵の生成とCSRファイルの作成と証明書への自己署名...という内容。OpenSSLと同じである。


LibreSSLをインストール
apk addコマンドでLibreSSLのパッケージをインストールする。
インストール完了後、libressl versionコマンドでバージョンが確認出来る。少し古いOS(macOS 10.13.6など)の場合はopenssl versionコマンドでLibreSSLのバージョンが確認出来る。

$ sudo apk add libressl
(1/4) Installing libressl3.3-libcrypto (3.3.3-r0)
(2/4) Installing libressl3.3-libssl (3.3.3-r0)
(3/4) Installing libressl3.3-libtls (3.3.3-r0)
(4/4) Installing libressl (3.3.3-r0)
Executing busybox-1.33.1-r6.trigger
OK: 175 MiB in 138 packages
$
$ libressl version
LibreSSL 3.3.3
$



秘密鍵を生成
libresslコマンドを打ち秘密鍵を生成。 -aes128オプション無しにつき鍵自体は暗号化されない。

# libressl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
...+++++
.........+++++
e is 65537 (0x10001)
#



CSR(証明書署名要求)を作成
libresslコマンドで秘密鍵の内容を参照しCSRファイルを作成。
CSR作成の際に聞かれる情報は一部を覗き、非常にテキトーな内容になっている。

# libressl req -new -key server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:TOKYO
Locality Name (eg, city) []:MITAKA
Organization Name (eg, company) [Internet Widgits Pty Ltd]:hoge
Organizational Unit Name (eg, section) []:hoge
Common Name (e.g. server FQDN or YOUR name) []:hoge
Email Address []:hechtia@hoge.jp

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
#



証明書への署名
上記にて生成した自分の秘密鍵で、証明書に自己署名する。
証明書の有効期限は3650日(10年)の期限で設定した。

# libressl x509 -days 3650 -req -signkey server.key -in server.csr -out server.crt
Signature ok
subject=/C=JP/ST=TOKYO/L=MITAKA/O=hoge/OU=hoge/CN=hoge/emailAddress=hechtia@hoge.jp
Getting Private key
#



秘密鍵と証明書ファイルの移動
秘密鍵と証明書を作業用ディレクトリからvsftpディレクトリに移動。

# cp server.key /etc/vsftpd/
# cp server.crt /etc/vsftpd/



vsftpの設定
vsftpd.confに暗号化通信関連の設定を追記。以下の設定では、SSLバージョン2のみ有効、パスワードとデータの通信の際は強制的に暗号化、秘密鍵と証明書の保存ディレクトリの指定を設定している。

$ sudo vi /etc/vsftpd/vsftpd.conf
:
# SSL settings
ssl_enable=YES
ssl_sslv2=YES
ssl_sslv3=NO
ssl_tlsv1=NO
#ssl_tlsv1_1=NO
#ssl_tlsv1_2=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES
rsa_cert_file=/etc/vsftpd/server.crt
rsa_private_key_file=/etc/vsftpd/server.key



vsftpdの再起動
設定完了後、rc-service vsftpd restartコマンドでvsftpdサービスを再起動させて上記の設定内容をシステムに反映させる。
vsftpdサービスの再起動後、rc-service vsftpd statusコマンドでvsftpdサービスが正常に立ち上がっている事を確認する。
status: crashedが出力された場合、vsftpd.confに追加設定した内容を見直す。
自分の場合、追加設定直後はstatus: crashedが出力されたが、ssl_tlsv1_1とssl_tlsv1_2をコメントアウトしssl_sslv2=NOをYESに修正したらvsftpdサービスが正常に立ち上がった。

$ sudo rc-service vsftpd restart
 * Caching service dependencies ...                                  [ ok ]
 * Starting vsftpd ...                                               [ ok ]
$
$ sudo rc-service vsftpd status
 * status: started
$



FTP通信の確認
Cyberduckという、昔ながらのMac使いであればどこかで聞いたようなアプリを使用し、FTPサーバへのアクセスを試みる。
新規接続から入り、接続方式は「FTP-SSL (Explicit AUTH TLS)」を選択。
FTPサーバのIPアドレスやポート番号やユーザ名、パスワードを入力し接続ボタンをクリックすると、FTPサーバに接続する。
FTP SSLの接続確率中に「証明書の信頼性検証中のエラーが起きました。アップデートを必要とする証明書の情報設定を指定してください。」の警告が表示された場合、続けるをクリックし先に進める。
今回生成した証明書は自己署名ルート証明書である為に、この警告が表示される。


以下の画像は、LibreSSL未実装の状態でクライアント側(MacBook Air)とサーバ側(Alpine Linux)との間の通信をWiresharkでパケットキャプチャした内容。
クライアント側とサーバ側との間でSYN, ACKもしくはPSH ACK(クライアント側から一方的に送信開始)のやりとりが淡々と続いている事が分かる。
※画像をクリックすると拡大表示します



それに対し、以下の画像はLibreSSL実装済みの状態でクライアント側とサーバ側との間の通信をWiresharkでパケットキャプチャした内容。
TCPのセッションシーケンスの後に、TSLのセッションシーケンスが表示されている。
No.1:TCPセッションの開始
No.12:TLSv1.2 Client Hello
No.14:TLSv1.2 Server Hello, Certificate, Server Key Exchange, Certificate Request, Server Hello Done
No.17:TLSv1.2 Certificate
No.19:TLSv1.2 Client Key Exchabge
No.21:TLSv1.2 Change Cipher Spec
No.23:TLSv1.2 Encrypted Handshake Message
No.25:TLSv1.2 Change Cipher Spec, Encrypted Handshake Message
No.27:TLSv1.2 Application Data
※画像をクリックすると拡大表示します




Alpine Linuxの情報源等
https://alpinelinux.org/ Alpine Linux
https://wiki.alpinelinux.org/wiki/Main_Page Alpine Linux Wiki

LibreSSLの情報源
https://www.libressl.org/
https://www.ossnews.jp/compare/OpenSSL/LibreSSL OpenSSLとLibreSSLを比較
https://gihyo.jp/admin/clip/01/linux_dt/201610/18 Alpine Linux,OpenSSLからLibreSSLへ

Alpine Linuxに関する過去の記事
https://debslink.hatenadiary.jp/entry/20200418/1587204948 AndroidスマホでAlpine Linuxを動かす
https://debslink.hatenadiary.jp/entry/20200506/1588733149 Androidスマホで動作するAlpine LinuxにてFTPサーバを構築
https://debslink.hatenadiary.jp/entry/20211024/1635075047 Alpine Linuxの保守用コマンド
https://debslink.hatenadiary.jp/entry/20211228/1640668431 Alpine LinuxでAwallを使ってiptables設定