サーバークラウドセキュリティネットワーク

NGINX PlusでmTLS認証を試してみた!

NGINXでは様々な認証方式が利用できます、今回はmTLS認証の設定方法や動作確認を試してみましたのでブログ記事にしたいと思います。

1.はじめに

ブログを読んでいただきありがとうございます!
東京エレクトロンデバイスのJo Nishikawaです。

今回は、mTLS認証について検証してみましたのでブログを書いていきたいと思います。

これまでもNGINX Plusを利用した認証関連の検証結果などをご紹介してきました。

NGINX PlusでHttp Basic認証を検証してみた!

NGINX PlusとOktaの認証連携

NGINX Plus と Okta Customer Identity Cloud(旧Auth0)の認証連携

NGINX PlusでSAML認証をやってみた!

近年、セキュリティの重要性が高まる中で、通信の暗号化と認証は必須の要素となっています。
特に、サーバーとクライアント間の相互認証を実現するmTLS認証は、強固なセキュリティを提供する手段となっていますので今回のブログで設定方法や動作のイメージをつかみたいと思います。


2.mTLSとは?

mTLSとは、Mutual TLSの略でサーバーとクライアントの両方がお互いを認証する仕組みです。
通常のTLSでは、サーバーがクライアントに対して証明書を提示し、クライアントはサーバーの正当性を確認します。
mTLS認証では、クライアントも証明書を提示し、サーバーがクライアントの正当性を確認します。これにより、TLSよりも安全な通信が実現されます。

TLSとmTLSの違いも調査したので表にしてみました。

TLSとmTLSの違い(比較表)

項目 TLS認証 mTLS認証
認証対象 サーバーのみ(クライアントはサーバー証明書を検証) サーバー & クライアント(双方向で証明書を検証)
証明書の種類 サーバー証明書のみ 必要 サーバー証明書 & クライアント証明書 が必要
セキュリティ強度 基本的な暗号化(通信内容を暗号化) 高度なセキュリティ(なりすまし防止、ゼロトラスト環境向け)
設定の難易度 比較的簡単(サーバー証明書を設定するだけ) 設定が複雑(CA管理・証明書配布が必要)

3.検証構成&動作確認したいこと

  • 今回は以下の検証構成で動作確認を行います。

    ✅ コンテンツに対して正しい証明書を提示してアクセスできること
    ✅ コンテンツに対して証明書がないリクエストでアクセスできないこと


4.検証

STEP0:NGINX Plusをサーバーにインストール、コンテンツサーバーの用意

  • 手順はこちらをご参照ください
  • 実際にコンテンツを表示させるサーバーも用意します。
    今回はクライアントからapp1.example.com宛にCurlでGETリクエストを行い、NGINX Plusとクライアント間でmTLS認証が成功した場合にコンテンツサーバーのコンテンツがクライアントに応答されるようにNGINX Plusを設定していきます。

STEP1:証明書の準備

  • NGINX Plusをインストールしたサーバーにて以下のファイルをOpenSSLを使って作成します。
ファイル名 役割
CA.key ルートCAの秘密鍵
CA.pem ルートCAの証明書(自己署名)
SERVER.key サーバーの秘密鍵
SERVER.pem サーバー証明書(CAが署名)
CLIENT1.key クライアントの秘密鍵
CLIENT1.pem クライアント証明書(CAが署名)
openssl ecparam -out ./CA.key -name prime256v1 -genkey
openssl req -new -key ./CA.key -out ./CA-csr.pem -subj '/C=JP/ST=Tokyo/O=EXAMPLE COM/CN=ROOT EXAMPLE COM/emailAddress=admin@example.com'
openssl req -x509 -nodes -days 3650 -key ./CA.key -in ./CA-csr.pem -out ./CA.pem
openssl ecparam -out ./SERVER.key -name prime256v1 -genkey
openssl req -new -key ./SERVER.key -out ./SERVER-csr.pem -subj '/C=JP/ST=Tokyo/O=EXAMPLE COM/CN=app1.example.com/emailAddress=admin@example.com'
openssl ca -config ./openssl.cnf -in SERVER-csr.pem -out SERVER.pem
openssl ecparam -out ./CLIENT1.key -name prime256v1 -genkey
openssl req -new -key ./CLIENT1.key -out ./CLIENT1-csr.pem -subj '/C=JP/ST=Tokyo/O=EXAMPLE COM/CN=client1.example.com/emailAddress=admin@example.com'
openssl ca -config ./openssl.cnf -in CLIENT1-csr.pem -out CLIENT1.pem
  • 証明書や鍵などを /etc/nginx/conf.d/ssl に配置します。
sudo mkdir /etc/nginx/conf.d/ssl
sudo cp SERVER.key /etc/nginx/conf.d/ssl
sudo cp SERVER.pem /etc/nginx/conf.d/ssl
sudo cp CA.pem /etc/nginx/conf.d/ssl

STEP2:NIGNX Plusの設定

  • NGINX Plusの設定ファイル(default.conf)に以下の設定をします。
upstream server_group {
    zone backend 64k;
    server backend1:81; #app1.example.comを表示するコンテンツサーバー
}
server {
   listen 443 ssl; #待ち受けポートを443に指定してSSL/TLSを有効化
   ssl_certificate_key conf.d/ssl/SERVER.key; #TLSで使用する秘密鍵を指定
   ssl_certificate conf.d/ssl/SERVER.pem; #TLSで使用するサーバー証明書を指定
   ssl_client_certificate conf.d/ssl/CA.pem; #クライアント証明書を検証するためのCA証明書を指定
   ssl_verify_client on; #クライアント証明書の検証を必須に指定
   location / {
       proxy_pass http://server_group;
   }
}

STEP3:NIGNX Plusのリロード

  • NGINX Plusの設定を反映するためにリロードを実施します。
 sudo systemctl restart nginx

STEP4:動作確認

  • はじめにクライアント証明書を提示してリクエストを行います。
    NGINX Plusがインストールされているサーバーからのcurl結果は以下になります(一部抜粋)。
    問題なくリクエストが処理され、200 OKとなっています
ubuntu@ip-x-x-x-x:~$ curl -v --cacert ./CA.pem --key ./CLIENT1.key --cert ./CLIENT1.pem  https://app1.example.com --resolve app1.example.com:443:127.0.0.1

> GET / HTTP/1.1
> Host: app1.example.com
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.25.5
< Date: Thu, 27 Mar 2025 04:47:59 GMT
< Content-Type: application/octet-stream
< Content-Length: 65
< Connection: keep-alive
<
  • 次にクライアント証明書を提示せずにリクエストを行います。
    NGINX Plusがインストールされているサーバーからのcurl結果は以下になります(一部抜粋)。
    クライアント証明書を提示していないため、400 エラーが出力されています。

ubuntu@ip-x-x-x-x:~$ curl -v --cacert ./CA.pem https://app1.example.com --resolve app1.example.com:443:127.0.0.1

> GET / HTTP/1.1
> Host: app1.example.com
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Server: nginx/1.25.5
< Date: Thu, 27 Mar 2025 04:46:13 GMT
< Content-Type: text/html
< Content-Length: 237
< Connection: close
<
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.25.5</center>
</body>
</html>
  • 無事、期待通りの動作確認ができました。

5.まとめ

mTLS認証の動作確認が無事にできました。

最近、NGINX Plusにおける認証に関してお問い合わせをいただくことが増えてきましたので、新たに認証に特化したハンズオントレーニングを開設いたしました。
定期的にトレーニングを実施しておりますので、是非ご参加いただけますと幸いです。

お申し込みはこちらからお願いいたします。

今後も新たな動作確認や検証ができましたら、ブログを書きたいと思います!お楽しみに。

この記事に関連する製品・サービス

この記事に関連する記事

【動画で体験シリーズ 第三弾】NGINXにWAFを入れてセキュリティ強化を体験しよう #NGINX

【情報漏えい対策】WAFだけでは防げない?Webスキミング攻撃の脅威と対策

【証明書の管理はもう手間じゃない】VaultとTerraformで実現するBIG-IPの証明書自動更新