NGINX Full Version

NGINX Plus R29の発表

NGINX Plus Release 29 (R29)の提供を開始することをお知らせします。NGINX Plusは、NGINXオープンソースをベースにした、唯一のオールインワン・ソフトウェアWebサーバー、ロードバランサー、リバースプロキシ、コンテンツキャッシュ、およびAPIゲートウェイです。
NGINX Plus R29の新機能は以下の通りです。

重要な動作の変化

注:もしNGINX Plus R28以外のリリースからアップグレードする場合、現在利用中のリリースから今回のリリースまでの過去のブログで紹介されている「重要な動作の変化」の項目を必ず確認してください。

パッケージ提供リポジトリの変更

古いパッケージ提供リポジトリplus-pkgs.nginx.comはNGINX Plus R29の提供と同時に廃止になります。このリポジトリはNGINX Plus R25からアップデートはされません。また、NGINX Plus R24から提供されるpkgs.nginx.comの利用が強く推奨されます

プラットフォーム対応の変更

新たに以下のプラットフォームがサポートされます。

以下プラットフォームはサポート対象外となります。

以下プラットフォームはNGINX Plus R30でサポート対象外となる予定です。

ModSecurity EOLのアナウンスに関する対応

ModSecurityのEOL発表に合わせて、NGINX Plus R29はModSecurityパッケージのサポートを削除します。もしModSecurityパッケージの利用を利用している場合、まもなくModSecurityからNGINX App Protectへの切り替えプログラムの利用が可能になります。これらの詳細は近日案内されます。詳細についてはF5へお問い合わせください。

新機能の詳細

MQTTプロトコルのサポート

MQTT (Message Queuing Telemetry Transport)は人気で軽量なパブリッシュ-サブスクライブなメッセージ交換のプロトコルで、IoTデバイスやインターネット上のアプリケーション(クライアント)の接続に最適です。あるトピックに対してクライアントがメッセージをパブリッシュ(投稿)や他のトピックのサブスクライブ(購読)することが可能になります。サブスクライブを行ったクライアントはそのトピックに対してパブリッシュされたすべてのメッセージを受け取り、多くのデバイスやサービス間における効果的で耐障害性に優れたデータの交換が可能になります。

MQTTの中心となる機能がブローカーです。ブローカーはクライアントやそのクライアントがサブスクライブするトピックや、メッセージの処理、それらのメッセージを適切なシステムに転送することを役割に持つサーバです。NGINX Plus R29はMQTT 3.1.1MQTT 5.0をサポートします。これはクライアントとブローカー間のプロキシとして動作し、システムの構成を簡素化し、機能のオフロードや、コストの削減を実現します。

このたび提供するMQTTの機能は以下の内容です。

MQTTとプロトコルは複数のメッセージタイプを定義し、CONNECT、PUBLISH、SUBSCRIBEが含まれます。NGINX Plus R29は様々なMQTTのCONNECTメッセージをパースし書き換え、以前はカスタムスクリプトのみで可能であった設定のシナリオを実現することができるようになりました。

MQTTのメッセージのパースや書き換えはNGINX設定ファイルのStreamコンテキストに定義する必要があり、ngx_stream_mqtt_preread_module
ngx_stream_mqtt_filter_moduleによって可能となっています。

MQTTの記述例

MQTTのデバイスによって送付されるデフォルトのクライアント識別子を変更することにより、NGINXはデバイスのシリアルナンバーなど機密情報を隠すことが可能になります。このはじめのレイデイは、識別子がデバイスのIPアドレスとなっています。

注:デバイスのIPアドレスをMQTTのクライアントの識別子とすることは本番環境では推奨されていません。

stream {
      mqtt on;
    server {         listen 1883;         proxy_pass 10.0.0.8:1883;         mqtt_rewrite_buffer_size 16k;         mqtt_set_connect clientid '$remote_addr';     } }

MQTTクライアントの一時的な性質を考慮すると、単純にデバイスのホスト名やIPアドレスを使ったブローカーへの負荷分散におけるセッションの維持は適切なものではありません。この例では、デバイスのMQTTクライアント識別子が、クラスタへの負荷分散の際に個々のMQTTブローカーへ通信の維持を行うためのハッシュキーとして利用されます。

stream {
      mqtt_preread on;
    upstream brokers{         zone tcp_mem 64k;         hash $mqtt_preread_clientid consistent;
        server 10.0.0.7:1883; # mqtt broker 1         server 10.0.0.8:1883; # mqtt broker 2         server 10.0.0.9:1883; # mqtt broker 3     }
    server {         listen 1883;         proxy_pass brokers;         proxy_connect_timeout 1s;     } }

次のステップ

NGINX Plusにおける将来的な実装では、CONNECTメッセージの詳細なパースと同様に、その他のMQTTメッセージ種別のパースを含む可能性があり、以下のような機能が有効になります。

我々は、みなさんがご興味のある機能に関する機能に対してのフィードバックを歓迎します。お気軽にコメントをお寄せください。

認証と認可で利用するSAMLのサポート

SAML(Security Assertion Markup Language)は認証プロバイダ(IdP)がリソースへの接続を行うためユーザーの認証(エンドユーザーが実際に誰であるのか確認すること)を行い、ユーザーが接続するシステムのアクセス権限と一緒に認証情報を、認可を行うサービスプロバイダ(SP)へ転送することを可能にする、オープンなフェデレーションの標準技術です。

ID データを交換するための安全な手段を提供してきた長い実績を持つSAMLは、IdPとSPの間で認証および認可の情報を交換するために広く採用されているプロトコルです。

企業や政府機関がSAMLの採用を選択する主な理由は次のとおりです。

SAMLはいくつかの利益を提供します。

現在提供するSAMLの参考の実装はSAML 2.0を使用し、NGINX JavaScript (njs)フレームワークを使用して構築されています。この実装では、NGINX PlusはSAML SPとして機能し、SAML IdPを使用してSSO利用環境に参加できるようにします。現在の実装は、既存のNGINX Plusの機能であるキーバリューストアに依存しているため、追加で実装の変更をしない場合NGINXオープンソースには適用できません。

NGINX PlusでのSAMLのサポートは、GitHub 上にある参考の実装を利用できるというものです。GitHubリポジトリには、特定のユースケース向けのインストール、構成、および微調整に関する手順が記載されたサンプルの設定が含まれています。

OpenTelemetryのネイティブ提供

OpenTelemetry (OTel) は、アプリケーションの監視、トレース、トラブルシューティング、および最適化に使用できる標準的なテクノロジです。デプロイされたアプリケーションスタック内のプロキシ、アプリケーション、またはその他のサービスなど、OTelは様々なソースからテレメトリデータを収集することによって機能します。

プロトコル対応のリバースプロキシおよびロードバランサーとして、NGINXは、アプリケーションの要求と応答を追跡するためのテレメトリ呼び出しを開始するのに理想的な位置にあります。サードパーティのOTelモジュールはしばらくの間利用可能でしたが、新しい動的モジュールを使用してNGINX PlusでOTelのネイティブのサポートを発表できることを嬉しく思います。

新しいモジュールngx_otel_moduleは、nginx-plus-module-otelパッケージを使用してインストールすることができ、サードパーティモジュールに対して次のようないくつかの重要な改善を提供します。

OTelの動的モジュールの詳細については、NGINXのドキュメントを参照してください。

OTelによるトレーシングの例

アプリケーションの基本的な OTelトレース情報をNGINXが直接提供する例を次に示します。

load_module modules/ngx_otel_module.so;
events {}
http {     otel_exporter {         endpoint localhost:4317;     }  
    server {         listen 127.0.0.1:8080;         
        otel_trace on;         otel_span_name app1;     } }

この次の例では、受信するリクエストからトレース コンテキストを継承し、親スパンがサンプリングされた場合にのみスパンを記録します。また、トレースコンテキストとサンプリングの決定をアップストリームサーバーに伝達します。

load_module modules/ngx_otel_module.so;
http {     server {         location / {             otel_trace $otel_parent_sampled;             otel_trace_context propagate;             proxy_pass http://backend;         }     } }

この比率を指定した例では、トラフィックを指定した割合 (この場合は 10%) に対してトレースが構成されるようになります。

http {
      # trace 10% of requests
      split_clients "$otel_trace_id" $ratio_sampler {
          10%     on;
          *       off;
      }
    # or we can trace 10% of user sessions
    split_clients "$cookie_sessionid" $session_sampler {         10%     on;         *       off;     }
    server {         location / {             otel_trace $ratio_sampler;             otel_trace_context inject;
            proxy_pass http://backend;         }     } }

このAPI制御の例では、/apiエンドポイントを介してキーバリューストアを操作することにより、トレースが有効になります。

http {
      keyval "otel.trace" $trace_switch zone=name;
    server {         location / {             otel_trace $trace_switch;             otel_trace_context inject;             proxy_pass http://backend;         }
        location /api {             api write=on;         }      } }

実験的なQUIC+HTTP/3パッケージ

NGINXオープンソースのプレビュー バイナリパッケージの発表に続いて、NGINX Plus R29の実験的なQUICパッケージを発表できることを嬉しく思います。これにより、NGINX Plus を使用した HTTP/3 のテストと評価が可能になります。

新しい基盤となるプロトコル スタックにより、HTTP/3 は UDP と QUIC をトランスポート層として利用します。 QUICは、接続の多重化を提供し、ヘッドオブラインブロッキングなどの問題を解決することにより、TCP を改善するように設計された暗号化されたトランスポートプロトコルです。接続の確立、輻輳制御、信頼性の高い配信など、HTTP/1.1 および HTTP/2 の多くの TCP機能を再実装および強化します。また、TLSを別のレイヤーとして持つ HTTP/1.1 および HTTP/2 とは異なり、QUICは、TLSを統合されたコンポーネントとして組み込みます。これは、HTTP/3 メッセージがデフォルトで暗号化された接続を介して送信されるため、本質的に安全であることを意味します。

通常、安全な通信と暗号化機能のために、NGINX Plusは、オペレーティングシステムに同梱されている SSL/TLSライブラリとして利用されているOpenSSLに依存しています。ただし、この記事の執筆時点では、QUICのTLSインターフェースはOpenSSLでサポートされていないため、HTTP/3 で必要とされる不足している TLS機能を提供するには、サードパーティライブラリが必要です。

この懸念に対処するために、QUICに用いるOpenSSLの互換性レイヤーを開発しました。これにより、quictls、BoringSSL、LibreSSL などのサードパーティのTLSライブラリを構築して出荷する必要がなくなりました。 これにより、カスタムTLS実装の負担や、サードパーティライブラリのスケジュールやロードマップへの依存なしに、NGINXでエンドツーエンドのQUIC+HTTP/3エクスペリエンスを管理できます。

注: OpenSSL互換性レイヤーは実験的な NGINX Plus QUIC+HTTP/3 パッケージに含まれており、TLSv1.3(QUIC プロトコルで必要) を提供するにはOpenSSL 1.1.1以降が必要です。0-RTTはまだ実装されていません。

QUIC+HTTP/3のサンプル設定

NGINX Plus での QUIC+HTTP/3 の設定例を見てみましょう。

http {
      log_format quic '$remote_addr - $remote_user [$time_local]'
      '"$request" $status $body_bytes_sent '
      '"$http_referer" "$http_user_agent" "$http3"';
    access_log logs/access.log quic;
    server {         # for better compatibility it's recommended         # to use the same port for quic and https         listen 8443 quic reuseport;         listen 8443 ssl;
        ssl_certificate     certs/example.com.crt;         ssl_certificate_key certs/example.com.key;
        location / {             # required for browsers to direct them into quic port             add_header Alt-Svc 'h3=":8443"; ma=86400';         }     } }

HTTP/2の実装と同様に、NGINX Plus がプロキシとして機能する場合、クライアント側で QUIC+HTTP/3 接続が作成され、バックエンドおよびアップストリーム サービスに接続する際に HTTP/1.1に変換されます。

NGINX Plus QUIC+HTTP/3 実験的なパッケージは別のリポジトリから入手でき、既存のNGINX Plus証明書とキーでアクセスできます。 実験的なQUICパッケージのインストールは、標準のNGINX Plusインストールに似ています。 インストール手順で強調表示されているように、必ず QUIC リポジトリを使用してください。

QUIC+HTTP/3用にNGINXを構成する方法の詳細については、QQUIC+HTTP/3用にNGINXを構成するを参照してください。 すべての新しいディレクティブと変数の詳細については、nginx-quic READMEの構成セクションを参照してください。

次のステップ

近い将来、QUIC+HTTP/3コードをNGINXメインラインブランチにマージする予定です。その後、QUIC+HTTP/3をサポートする NGINXメインラインの最新バージョンは、次のNGINX Plusリリースにマージされます。今年後半に、NGINX PlusでのQUIC+HTTP/3 サポートが正式に利用可能となることに関する発表を期待してください。

NGINX Plus R29 のその他の機能強化

OpenID Connectの変更点

OpenID Connect (OIDC) サポートは NGINX Plus R15 で導入され、その後のバージョンで大幅に強化されました。 NGINX Plus R29 は、以下の追加により、OIDC を強化し続けています。

アクセストークンのサポート

アクセストークンはトークンベースの認証で使用され、OIDC クライアントがユーザーに代わって保護されたリソースにアクセスできるようにします。 NGINX Plusは、ユーザーがアクセスの認証と認可に成功した後にアクセストークンを受け取り、それをキーバリューストアに保存します。 NGINX Plusは、後段のアプリケーションに送信されるすべてのリクエストのBearerトークンとして、HTTP Authorization ヘッダーでそのトークンを渡すことができます。

注: : NGINX Plus は、(IDトークンの場合のように) 各リクエストでアクセストークンの有効性を検証せず、アクセストークンが既に期限切れになっているかどうかを知ることができません。アクセス トークンの有効期間が ID トークンの有効期間よりも短い場合は、proxy_intercept_errors on ディレクティブを使用する必要があります。 これにより、401 Unauthorized応答が傍受されて NGINX にリダイレクトされ、アクセス トークンが更新されます。

NGINX Plusを使用した OpenID ConnectおよびJSON Web Token (JWT) 検証の詳細については、Authenticating Users to Existing Applications with OpenID Connect and NGINX Plusを参照してください。

OIDC 認証エンドポイントに追加された引数

Keycloakなどの一部のIDプロバイダでは、認証リクエストに追加のクエリ文字列引数を追加して、追加機能を有効にすることができます。 たとえば、Keycloakでは、認証リクエストにkc_idp_hintパラメーターを追加することで、デフォルトのIdPを指定できます。 この機能強化の一環として、ユーザーはOIDC承認エンドポイントに追加の引数を指定できます。

Prometheus-njs モジュールの拡張された SSL カウンター

NGINX Plus R28 では、クライアントサイドとサーバーサイドの接続における HTTPモジュールとストリームモジュールの両方で、ハンドシェイクエラーと証明書検証の失敗に対する追加のSSLカウンターのサポートを追加しました。 NGINX PlusメトリクスをPrometheus 準拠の形式に変換するPrometheus-njsモジュールが、これらのカウンターをサポートするようになりました。

新しいinternal_redirectディレクティブ

新しいinternal_redirectディレクティブとモジュールにより、リクエスト処理の制限、接続処理の制限、およびアクセス制限を確認した後、内部リダイレクトが可能になります。

internal_redirect構成の例を次に示します。

http {
      limit_req_zone $jwt_claim_sub zone=jwt_sub:10m rate=1r/s; 
    server {         location / {             auth_jwt "realm";             auth_jwt_key_file key.jwk;
            internal_redirect @rate_limited;         }
        location @rate_limited {             internal;             limit_req zone=jwt_sub burst=10;
         proxy_pass http://backend;         }     } }

上記の例では、ロケーションブロックで JWT 認証が実行され、トークンが有効な場合は、リクエストが内部コンテンツ ハンドラ @rate_limited に渡されますが、ここではsub claimの値に基づいてリクエストレート制限が適用されます。 これは、リクエストがアップストリーム サービスに渡される前に JWT で発生します。

この設定は、攻撃者が、subの値として特定のユーザー情報がエンコードされた読み取り可能なJWT を持つリクエストのフラッドを送信するサービス妨害 (DoS) 攻撃を防ぎます。 その大量のリクエストは認証を通過しませんが、レート制限にカウントされます。リクエストをコンテンツのハンドラに渡す前に JWT を認証することで、有効なリクエストのみがレート制限にカウントされるようになります。

NGINX オープン ソースから継承された変更

NGINX Plus R29 は、NGINX Open Source 1.23.4 に基づいており、NGINX Plus R28 がリリースされてから(NGINX 1.23.3 から 1.23.4)行われた機能変更とバグ修正を継承しています。

変更点

機能

バグフィックス

ワークアラウンド

このリリースから継承された新機能、変更、バグ修正、およびワークアラウンドの完全なリストについては、CHANGESファイルを参照してください。

NGINX JavaScript モジュールへの変更

NGINX Plus R29 には、NGINX JavaScript (njs) モジュール バージョン 0.7.9 から 0.7.12 への変更が組み込まれています。 njs には、次のようないくつかの優れた機能が追加されました。

njs バージョン 0.7.9 から 0.7.12 までのすべての機能、変更、およびバグ修正の包括的なリストについては、njs Changes logを参照してください。

拡張されたフェッチ API サポート

Headers()Request()、およびResponse()コンストラクターが Fetch API に追加され、その他の機能強化が行われました。

async function makeRequest(uri, headers) {
      let h = new Headers(headers);
      h.delete("bar");
      h.append("foo", "xxx");
      let r = new Request(uri, {headers: h});
      return await ngx.fetch(r);
  }

拡張されたWeb 暗号 API

JSON Web Key (JWK) 形式をサポートするように Web Crypto API が拡張され、importKey() は JWK 形式のキーを入力として受け取るようになりました。

async function importSigningJWK(jwk) {
     return await crypto.subtle.importKey('jwk', jwk,
                                          {name: "RSASSA-PKCS1-v1_5"},
                                          true, ['sign']);
  }

njs 0.7.10 では、generateKey()およびexportKey()メソッドも追加されました。generateKey()メソッドを使用すると、対称アルゴリズムの新しい鍵または公開鍵アルゴリズムの鍵ペアを生成できます。exportKey()メソッドは、CryptoKeyオブジェクトを入力として取り、キーを外部の移植可能な形式で返します。 JWK 形式をサポートし、キーを JSONオブジェクトとしてエクスポートします。

詳細については、Web Crypto APIを参照してください。

XMLドキュメントのサポート

XMLモジュールは njs 0.7.10 で追加され、XMLドキュメントを操作するためのネイティブサポートを提供します。

XMLキュメントの解析

XMLドキュメントの文字列またはバッファを解析できるようになりました。これにより、解析された XMLドキュメントを表すXMLDocラッパーオブジェクトが返されます。

const xml = require("xml");
  let data = `<note><to b="bar" a= "foo">Tove</to><from>Jani</from></note>`;
  let doc = xml.parse(data);
   
console.log(doc.note.to.$text) /* 'Tove' */ console.log(doc.note.to.$attr$b) /* 'bar' */ console.log(doc.note.$tags[1].$text) /* 'Jani' */

XMLドキュメントを変更するための XMLNode API

XML ドキュメントを変更するために、njs 0.7.11 で XMLNode API が追加されました。

Const xml = require("xml"); let data = `<note><to b="bar" a="foo">Tove</to><from>Jani</from></note>`; let doc = xml.parse(data);  
doc.$root.to.$attr$b = 'bar2'; doc.$root.to.setAttribute('c', 'baz'); delete doc.$root.to.$attr$a;  
console.log(xml.serializeToString(doc.$root.to)) /* '<to b="bar2" c="baz">Tove</to>' */  
doc.$root.to.removeAllAttributes(); doc.$root.from.$text = 'Jani2';  
console.log(xml.serializeToString(doc)) /* '<note><to>Tove</to><from>Jani2</from></note>' */  
doc.$root.to.$tags = [xml.parse(`<a/>`), xml.parse(`<b/>`)]; doc.$root.to.addChild(xml.parse(`<a/>`));
console.log(xml.serializeToString(doc.$root.to)) /* '<to><a></a><b></b><a></a></to>' */  
doc.$root.to.removeChildren('a');  
console.log(xml.serializeToString(doc.$root.to)) /* '<to><b></b></to>' */

すべての XML 関連の拡張機能の詳細については、XML documentsを参照してください。

Zlib モジュール圧縮のサポート

zlib モジュールは njs 0.7.12 で追加され、deflate および inflate アルゴリズムを使用した圧縮機能を提供します。

Const zlib = require('zlib');
  zlib.deflateRawSync('αβγ').toString('base64')
  /* "O7fx3KzzmwE=" */
   
zlib.inflateRawSync(Buffer.from('O7fx3KzzmwE=', 'base64')).toString() /* "αβγ" */

zlib の詳細については、zlib documentsを参照してください。

NGINX Plusのアップグレードまたは試用

NGINX Plusを実行している場合、できるだけ早くNGINX Plus R29にアップグレードすることを強くお勧めします。また、いくつかの追加修正と改善点をピックアップし、サポートチケットを発行する必要があるときにNGINXを支援することができるようになります。

NGINX Plusをまだお試しでない方は、セキュリティ、ロードバランシング、APIゲートウェイとして、あるいは強化された監視・管理APIを備えたフルサポートのウェブサーバーとして、ぜひお試しください。30日間の無料トライアルlで、今すぐ始めることができます。