トランスポート層セキュリティ (TLS) は非常に人気のある暗号化プロトコルです。 カーネルに TLS を実装する (kTLS) と、ユーザー空間とカーネル間のコピー操作の必要性が大幅に減少し、パフォーマンスが向上します。
kTLS とsendfile()
を組み合わせると、データはネットワーク スタックに渡されて送信される前に、カーネル空間で直接暗号化されます。 これにより、TLS ライブラリで暗号化するデータをユーザー空間にコピーし、その後カーネル空間に戻して送信する必要がなくなります。kTLS では、TLS対称暗号化処理をネットワーク デバイスにオフロードするなど、TLS 処理をハードウェアにオフロードすることもできます。
最新の Linux および FreeBSD カーネルはカーネルへの TLS のオフロードをサポートしており、NGINX Open Source でも同様にサポートされるようになりました。 NGINX 1.21.4 では、 SSL_sendfile()
を使用して静的ファイルとキャッシュされた応答を提供するときにkTLS のサポートが導入され、パフォーマンスが大幅に向上します。 以下に詳述するように、NGINX がSSL_sendfile()
を使用するには、カーネルと OpenSSL の両方が kTLS を使用してビルドされている必要があります。
このブログでは、どのオペレーティング システムと OpenSSL バージョンが kTLS をサポートしているかを詳しく説明し、kTLS 用にカーネルと NGINX を構築および構成する方法を示します。 kTLS で期待できるパフォーマンスの向上についてご理解いただけるよう、FreeBSD と Ubuntu でのテストの仕様と結果も共有します。
注: kTLS 実装は非常に新しいものであり、急速に進化しています。 このブログでは、2021 年 11 月時点での kTLS のサポートについて説明していますが、ここで提供されている情報と手順の変更については、 nginx.orgとNGINX ブログ<.htmla> での発表に注意してください。
オペレーティング システム – 次のいずれか:
FreeBSD 13.0以降。 2021 年 11 月現在、OpenSSL 3.0.0 以降を組み込むために NGINX を手動でビルドしなくても、NGINX で kTLS をサポートする OS は FreeBSD 13.0 以降のみです。 FreeBSD で kTLS を使用して NGINX を有効にするを参照してください。
Linux カーネル バージョン 4.17 以降でビルドされた Linux ディストリビューション。ただし、可能な場合はバージョン 5.2 以降でビルドされたものを使用することをお勧めします。(kTLS サポートは実際にはバージョン 4.13 で使用できますが、OpenSSL 3.0.0 にはカーネル ヘッダー バージョン 4.17 以降が必要です。)
OpenSSL – バージョン 3.0.0 以降
NGINX – バージョン 1.21.4 以降 (メインライン)
[編集者注– NGINX Plus R27以降では、対象となる Linux ベースのオペレーティング システム バージョンで kTLS がサポートされます。NGINX Plus R26 以降では、対象となる FreeBSD バージョンで kTLS がサポートされます。 サポートされている OS の詳細については、NGINX Plusリリースページを参照してください。
2021 年 11 月現在、 NGINX Open Source がサポートしているOS のうち、以下が kTLS と指定の暗号をサポートしています。 暗号サポートの詳細については、 「TLS プロトコルと暗号サポート」を参照してください。
TLSv1.2 暗号 | TLSv1.3 暗号スイート |
TLS_CHACHA20_POLY1305_SHA256 暗号 |
Linuxカーネルバージョン | |
---|---|---|---|---|
Amazon Linux 2 * | ✅ | ✅ | ❌ | 5.10 |
CentOS8 ** | ✅ | ❌ | ❌ | 4.18 |
フリーBSD 13.x | ✅ | ✅ | ❌ *** | 該当なし |
8 の | ✅ | ❌ | ❌ | 4.18 |
SLES 15 SP2 | ✅ | ✅ | ✅ | 5.3 |
Ubuntu 20.04 LTS | ✅ | ❌ | ❌ | 5.4 |
ウブントゥ 21.04 | ✅ | ✅ | ✅ | 5.11 |
ウブントゥ 21.10 | ✅ | ✅ | ✅ | 5.13 |
*カーネルバージョンは 4.14 ではなく 5.10 である必要があります。kTLSをサポートしない OSとAmazon Linux 2 FAQ を参照してください。
**上流ソースであるRHEL 8からkTLSサポートステータスを継承
*** FreeBSDコミットログを参照
以下の OS は、示されている理由により kTLS をサポートしていません。
CONFIG_TLS=n
オプションを使用して構築されており、kTLS をモジュールまたはカーネルの一部として構築することが無効になっています。CONFIG_TLS=n
オプションでビルドされます ( Debian バグレポート ログを参照)。上で詳述したように、kTLS をサポートする OS は、TLS プロトコルと暗号のサポートが異なります。
TLSv1.2 では、kTLS モジュールは次の暗号をサポートします。
AES128-GCM-SHA256
AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
TLSv1.3 では、kTLS モジュールは次の暗号スイートをサポートします。
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
( kTLS をサポートする OSで指定されている一部の OS のみ)OpenSSL でサポートされている TLS 暗号が NGINX バイナリで有効になっているかどうかを確認するには、NGINX をビルドしたディレクトリ (ホーム ディレクトリなど) でopenssl-3.0.0/.openssl/bin/openssl
ciphers
コマンドを実行します。
はじめに述べたように、kTLS ではすべての暗号化と復号化がカーネル内で行われるため、NGINX のパフォーマンスが向上します。 データは、ネットワーク スタックに渡されて送信される前にカーネル空間で直接暗号化されるため、TLS ライブラリによって暗号化されるデータをユーザー空間にコピーし、その後カーネル空間に戻して送信する必要がなくなります。
最近の FreeBSD および Linux ディストリビューションでは、kTLS は通常、モジュールとして構築されます ( CONFIG_TLS=m
オプションを使用)。 NGINX を起動する前に、kTLS モジュールをカーネルに明示的にロードする必要があります。
FreeBSD では、 root
ユーザーとして次のコマンドを実行します。
# kldload ktls_ocf.ko # sysctl kern.ipc.tls.enable=1
FreeBSD コマンド オプションの詳細については、 ktls(4)
のマニュアル ページを参照してください。
Linux ディストリビューションでは、 root
ユーザーとして次のコマンドを実行します。
# modprobe tls
FreeBSD 上の NGINX で kTLS サポートを有効にするには、Linux ディストリビューションの場合と同じ手順を使用できます。 ただし、 FreeBSD Ports Collectionのsecurity/openssl-develポートで kTLS を使用した NGINX のビルドを活用するには、次の手順を実行することをお勧めします。 kTLS の概要を含む詳細については、FreeBSD Web サイトの「TLS Offload in the Kernel」を参照してください。
構成メニューで適切なオプションを選択して、kTLS サポート付きの OpenSSL 3.0 をビルドします。
# cd /usr/ports/security/openssl-devel && config を実行 && インストールを実行
openssl-devel をデフォルトの SSL ライブラリとして使用するように/etc/make.conf を変更します。
# echo "DEFAULT_VERSIONS+=ssl=openssl-devel" >> /etc/make.conf
NGINX をビルドします。
# cd /usr/ports/www/nginx-devel && インストールする
現在の Linux ディストリビューションのほとんどには、OpenSSL バージョン 3.0.0 より前 (通常はバージョン 1.1) が含まれています。 したがって、OpenSSL 3.0.0 を使用してソースから NGINX をビルドする必要があります。
kTLS サポートを有効にするconfigure
コマンドの 2 つの重要なオプションは次のとおりです。
--with-openssl=../openssl-3.0.0
--with-openssl-opt=ktls を有効にする
その他の構成
オプションは、 nginx.orgで入手可能な公式NGINX バイナリ パッケージに含まれるモジュール用です。 代わりにカスタムのモジュール セットを指定することもできます。 現在の NGINX バイナリに使用されているビルド オプションを確認するには、 nginx
-V
を実行します。
OpenSSL 3.0.0 を使用して NGINX をビルドするには、次のコマンドを実行します。
$ wget https://nginx.org/download/nginx-1.21.4.tar.gz $ wget https://www.openssl.org/source/openssl-3.0.0.tar.gz $ tar xzf openssl-3.0.0.tar.gz $ cd nginx-1.21.4 $ ./configure \ --with-debug \ --prefix=/usr/local \ --conf-path=/usr/local/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/var/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --http-client-body-temp-path=/var/cache/nginx/client_temp \ --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ --user=nginx \ --group=nginx \ --with-compat \ --with-file-aio \ --with-threads \ --with-http_addition_module \ --with-http_auth_request_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_mp4_module \ --with-http_random_index_module \ --with-http_realip_module \ --with-http_secure_link_module \ --with-http_slice_module \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_sub_module \ --with-http_v2_module \ --with-mail \ --with-mail_ssl_module \ --with-stream \ --with-stream_realip_module \ --with-stream_ssl_module \ --with-stream_ssl_preread_module \ --with-openssl=../openssl-3.0.0 \ --with-openssl-opt=enable-ktls \ --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' \ -with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' $ make –j4 $ make install
注記: 生成された NGINX バイナリは、OpenSSL 3.0.0 ライブラリと静的にリンクされます。 後で OpenSSL にパッチを適用する必要がある場合は、新しい OpenSSL ソース アーカイブをダウンロードして解凍し、上記のコマンドを実行して NGINX バイナリを再構築する必要があります。
kTLS を有効にするには、テストに使用したこのサンプル構成のように、 server{}
コンテキストにOptions
KTLS
パラメータを含むssl_conf_command
ディレクティブを含めます。
worker_processes auto;error_log /var/log/nginx/error.log debug;
events {}
http {
sendfile on;
server {
listen 443 ssl;
ssl_certificate ssl/example.crt;
ssl_certificate_key ssl/example.key;
ssl_conf_command Options KTLS;
ssl_protocols TLSv1.3;
location / {
root /data;
}
}
}
NGINX が kTLS を使用していることを確認するには、デバッグ モードを有効にし、エラー ログでBIO_get_ktls_send()
とSSL_sendfile()
を確認します。
$ grep BIO /var/log/nginx/error.log 2021/11/10 16:02:46 [デバッグ] 274550#274550: *2 BIO_get_ktls_send(): 1 2021/11/10 16:02:49 [デバッグ] 274550#274550: *3 BIO_get_ktls_send(): 1 $ grep SSL_sendfile /var/log/nginx/error.log 2021/11/10 16:02:46 [デバッグ] 274550#274550: *2 SSL_sendfile: 1048576 2021/11/10 16:02:49 [デバッグ] 274550#274550: *3 SSL_sendfile: 1048576
注記: 特に実稼働環境では、これらのチェックを行った後、デバッグ モードを無効にすることをお勧めします。 デバッグ ログでは、書き込み操作の量が多いためパフォーマンスが低下します。また、デバッグ ログはサイズが大きくなり、ディスク パーティションの使用可能な領域がすぐに使い果たされる可能性があります。
高負荷状態で静的ファイルとキャッシュされた応答を提供する場合、 SSL_sendfile() は
ユーザー空間 TLS と比較してスループットを最大 2 倍向上させることができますが、パフォーマンスの向上の程度はさまざまな要因 (ディスク パフォーマンス、システム負荷など) に大きく依存します。 ネットワーク カードが TLS オフロードをサポートしている場合は、CPU 使用率を削減することもできます。
セットアップのパフォーマンス向上を測定するには、次の手順に従って、単純な 1 スレッド テストを実行します。 以下に詳述するように、テスト結果では、特別な調整を行わなくてもパフォーマンスが最大 30% 近く向上することが示されています。
使用されるハードウェアとソフトウェア:
TLS_AES_256_GCM_SHA384
暗号スイートを使用した TLSv1.3テストを実行するには:
ディスク キャッシュに完全に収まる大きなファイルを作成します。
#切り捨て -s 1g /data/1G
スループットを確認するには、このコマンドを実行します。より正確な結果を得るために、基本コマンドを複数回繰り返します。 基本的な統計分析を行うには、出力をministat
ユーティリティ [ FreeBSD ][ Ubuntu ] にパイプします。
# for i in 'seq 1 100'; do curl -k -s -o /dev/null -w '%{speed_download}\n' https://localhost/1G | ministat
以下のテスト結果はministat
からの出力として示されており、各値はダウンロード速度(kBytes/秒)です。 読みやすくするために出力は 2 行に分割されます。
kTLS なしの FreeBSD 13.0 のスループット:
N 最小 最大 中央値 ...x 10 532225 573348 555616 ...
... 平均標準偏差
... 555155.6 10239.137
kTLS を使用した FreeBSD 13.0 のスループット:
N 最小 最大 中央値 ...x 10 629379 723164 717349 ...
... 平均標準偏差
... 708600.4 28304.766
kTLS なしの Ubuntu 21.10 のスループット:
N 最小 最大 中央値 ...x 10 529199 705720 662354 ...
... 平均標準偏差
... 654321.6 48025.103
kTLS を使用した Ubuntu 21.10 のスループット:
N 最小 最大 中央値 ...x 10 619105 760208 756278 ...
... 平均標準偏差
... 741848.3 43255.246
私たちのテストでは、kTLS は Ubuntu よりも FreeBSD でパフォーマンスを向上させました。 改善率は次のとおりです。
分 | マックス | 中央値 | 平均 | |
---|---|---|---|---|
フリーBSD 13.0 | 18% | 26% | 29% | 28% |
ウブントゥ 21.10 | 16% | 8% | 14% | 13% |
NGINX 1.21.4 では、 SSL_sendfile()
を使用して静的ファイルとキャッシュされた応答を提供するときに kTLS のサポートが導入されています。 当社のテストでは、オペレーティング システムに応じてパフォーマンスが 8% ~ 29% 向上することが示されています。
kTLS と NGINX に関する皆様のご経験、特に他の OS でのテスト結果についてお聞かせください。 ぜひ下のコメント欄でシェアしてください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"