Nginx の動作原理、最適化、および脆弱性。

WBOY
リリース: 2016-08-08 09:32:37
オリジナル
924 人が閲覧しました


1. Nginx のモジュールと動作原理

その中で、カーネルの設計は非常に小さく簡潔であり、実行される作業も非常に簡単です。クライアントに接続するための構成ファイル リクエストはロケーション ブロックにマップされます (ロケーションは、URL マッチングに使用される Nginx 構成内のディレクティブです)。このロケーションに構成された各ディレクティブは、対応する作業を完了するために異なるモジュールを開始します。

Nginx モジュールは構造的にコア モジュール、基本モジュール、サードパーティ モジュールに分かれています:

コア モジュール: HTTP モジュール、EVENT モジュール、MAIL モジュール

基本モジュール: HTTP Access モジュール、HTTP FastCGI モジュール、HTTPプロキシ モジュールと HTTP Rewrite モジュール、

サードパーティ モジュール: HTTP アップストリーム リクエスト ハッシュ モジュール、通知モジュール、および HTTP アクセス キー モジュール。

ユーザーが独自のニーズに従って開発したモジュールはサードパーティモジュールです。 Nginx の機能が非常に強力なのは、まさに多くのモジュールのサポートがあるからです。

Nginx モジュールは機能的に次の 3 つのカテゴリに分類されます。

ハンドラー (プロセッサーモジュール)。このタイプのモジュールはリクエストを直接処理し、コンテンツの出力やヘッダー情報の変更などの操作を実行します。通常、存在できるハンドラー プロセッサ モジュールは 1 つだけです。

フィルター (フィルターモジュール)。このタイプのモジュールは主に他のプロセッサ モジュールによって出力されたコンテンツを変更し、最終的に Nginx によって出力されます。

Proxies (プロキシ クラス モジュール)。このようなモジュールは、Nginx の HTTP アップストリームなどのモジュールであり、主に FastCGI などのいくつかのバックエンド サービスと対話して、サービス プロキシや負荷分散などの機能を実装します。

図 1-1 は、Nginx モジュールの通常の HTTP リクエストとレスポンスのプロセスを示しています。図 1-1 は、Nginx モジュールの通常の HTTP リクエストとレスポンスのプロセスを示しています。

Nginx は、HTTP リクエストを受信すると、設定ファイルを検索してリクエストをロケーション ブロックにマッピングするだけで、このロケーションに設定された各命令が開始され、作業が完了します。したがって、モジュールは Nginx の実際の労働者とみなすことができます。通常、ある場所の命令には、ハンドラー モジュールと複数のフィルター モジュールが含まれます (もちろん、複数の場所で同じモジュールを再利用できます)。ハンドラー モジュールはリクエストの処理と応答コンテンツの生成の完了を担当し、フィルター モジュールは応答コンテンツを処理します。

Nginx モジュールは Nginx に直接コンパイルされるため、静的コンパイル方法です。 Nginx を起動すると、Apache とは異なり、まずモジュールが so ファイルにコンパイルされてから、ロードするかどうかを設定ファイルで指定します。設定ファイルを解析する際、Nginx の各モジュールは特定のリクエストを処理することがありますが、同じ処理リクエストを完了できるのは 1 つのモジュールだけです。

動作モードに関して、Nginx はシングルワーカープロセスとマルチワーカープロセスの 2 つのモードに分かれています。シングル ワーカー プロセス モードでは、メイン プロセスに加えてワーカー プロセスも存在します。マルチ ワーカー プロセス モードでは、ワーカー プロセスはシングルスレッドであり、各ワーカー プロセスには複数のスレッドが含まれます。 Nginx のデフォルトはシングルワーカー プロセス モードです。

2. Nginx+FastCGIの動作原理

1. FastCGIとは

FastCGIは、HTTPサーバーと動的スクリプト言語間のスケーラブルで高速な通信インターフェースです。 Apache、Nginx、lighttpd など、最も一般的な HTTP サーバーは FastCGI をサポートしています。同時に、FastCGI は、PHP を含む多くのスクリプト言語でもサポートされています。

FastCGI は CGI から開発および改良されました。従来の CGI インターフェイス方式の主な欠点は、パフォーマンスが低いことです。これは、HTTP サーバーが動的プログラムに遭遇するたびに、スクリプト パーサーを再起動して解析を実行する必要があり、結果が HTTP サーバーに返されるためです。これは、同時アクセスが多い場合にはほとんど使用できません。また、従来の CGI インターフェース方式はセキュリティが低く、現在ではほとんど使用されていません。 FastCGI インターフェイス モードは C/S 構造を採用しており、HTTP サーバーとスクリプト解析サーバーを分離し、スクリプト解析サーバー上で 1 つ以上のスクリプト解析デーモンを起動できます。 HTTP サーバーが動的プログラムに遭遇するたびに、そのプログラムは実行のために FastCGI プロセスに直接配信され、その結果がブラウザーに返されます。この方法により、HTTP サーバーは静的リクエストを排他的に処理したり、動的スクリプト サーバーの結果をクライアントに返すことができるため、アプリケーション システム全体のパフォーマンスが大幅に向上します。

2. Nginx+FastCGI の動作原理

Nginx は、外部プログラムの直接呼び出しや解析をサポートしていません (PHP を含む) は、FastCGI インターフェイスを介して呼び出す必要があります。 FastCGI インターフェイスは、Linux 上のソケットです (このソケットはファイル ソケットまたは IP ソケットにすることができます)。

ラッパー: CGI プログラムを呼び出すには、FastCGI ラッパーも必要です (ラッパーは、別のプログラムを開始するために使用されるプログラムとして理解できます)。このラッパーは、ポートやファイル ソケットなどの固定ソケットにバインドされます。 Nginx が CGI リクエストをこのソケットに送信すると、ラッパーは FastCGI インターフェイスを通じてリクエストを受信し、新しいスレッドをフォーク (派生) して、インタープリターまたは外部プログラムを呼び出してスクリプトを処理し、戻りデータを読み取ります。次に、ラッパーは返されたデータを FastCGI インターフェイス経由で Nginx に渡し、最後に Nginx は返されたデータ (HTML ページまたは画像) をクライアントに送信します。図 1-3 に示すように、これは Nginx+FastCGI の全体的な動作プロセスです。先 首、最初にラッパーが必要です。このラッパーは以下を完了する必要があります:

FastCGI (ライブラリ) の関数が呼び出されます。これは fastcgi によって内部的に実装される関数であり、ラッパーに対して透過的ではありません) スレッドのスケジューリング、 fork と kill の実行 アプリケーション (php) との通信

3. spawn-fcgi と PHP-FPM FastCGI インターフェイス メソッドはスクリプト内にあります 動的スクリプトを解析するために、解析サーバー上で 1 つ以上のデーモン プロセスが開始されます。これらのプロセスは、FastCGI プロセス マネージャー、または FastCGI エンジンです。 spawn-fcgi と PHP-FPM は、PHP をサポートする 2 つの FastCGI プロセス マネージャーです。

したがって、HTTPServer は完全に解放され、より適切に応答し、同時実行性をより適切に処理できるようになります。 N w SPAWN-FCGI と PHP-FPM の類似点:
1) Spawn-FCGI は HTTP サーバー Lighttpd の一部であり、通常、PHP をサポートするために LIGHTTPD とともに使用されます。ただし、ligttpd の spwan-fcgi はメモリ リークを引き起こしたり、同時アクセスが多いときに FastCGI が自動的に再起動したりする可能性があります。つまり、この時点でユーザーがアクセスすると、PHP スクリプト プロセッサがクラッシュし、白いページが表示される可能性があります (つまり、PHP を解析できないか、エラーが発生します)。

2) Nginx は軽量の HTTP サーバーであり、PHP を解析するにはサードパーティの FastCGI プロセッサを使用する必要があります。したがって、実際には、nginx は非常に柔軟で、解析を提供するあらゆるサードパーティのプロセッサと連携できるようです。 PHP を解析するための接続 (nginx.conf で簡単にセットアップできます)。 nginx も spwan-fcgi を使用できます (lighttpd を一緒にインストールする必要がありますが、nginx ではポートを回避する必要があります。一部の古いブログにはこれに関するインストール チュートリアルが記載されています)。ただし、spawn-fcgi には次のような欠陥があるため、ユーザーによって徐々に発見されます。上で述べたように、現在、nginx + spawn-fcgi の組み合わせの使用を徐々に減らしています。
  1. spawn-fcgi の欠陥のため、現在はサードパーティ製の (現在 PHP コアに追加されている) PHP FastCGI プロセッサ PHP-FPM が存在しており、spawn-fcgi と比較すると次のような利点があります。 PHP パッチとして開発されているため、インストール時に PHP ソース コードと一緒にコンパイルする必要があります。つまり、PHP コアにコンパイルされるため、パフォーマンスの面でも優れています。 、高い同時実行性を処理します。また、spawn-fcgi よりも優れており、少なくとも fastcgi プロセッサを自動的に再起動しません。したがって、PHP を解析するには、Nginx+PHP/PHP-FPM の組み合わせを使用することをお勧めします。
Spawn-FCGI と比較して、PHP-FPM は CPU とメモリの制御が優れており、前者は簡単にクラッシュして crontab で監視する必要がありますが、PHP-FPM にはそのような問題はありません。

FastCGI の主な利点は、動的言語を HTTP サーバーから分離することです。そのため、Nginx と PHP/PHP-FPM は、フロントエンド Nginx サーバーへの負荷を共有するために別のサーバーにデプロイされることが多く、Nginx が排他的に実行できるようになります。静的リクエストと動的リクエストの転送を処理し、PHP/PHP-FPM サーバーは PHP 動的リクエストを排他的に解析します。

4. Nginx+PHP-FPM

PHP-FPM は、PHP のプラグインとして存在し、PHP-FPM をインストールする必要があります。古いバージョンの php (php5. 3.3)、PHP-FPM はパッチの形で PHP にインストールする必要があり、PHP は PHP-FPM のバージョンと一致している必要があり、これは必須です)

PHP-FPM は実際にはFastCGI プロセス管理用に設計された PHP ソース コードのパッチが PHP パッケージに統合されています。 PHP ソース コードにパッチを適用する必要があり、PHP をコンパイルしてインストールした後に使用できるようになります。

PHP5.3.3 には php-fpm が統合されており、サードパーティのパッケージではなくなりました。 PHP-FPM は、メモリとプロセスを効果的に制御し、PHP 設定をスムーズにリロードできる、より優れた PHP プロセス管理方法を提供します。そのため、spawn-fcgi よりも多くの利点があるため、PHP に正式に組み込まれています。 PHP-FPM を有効にするには、./configure で –enable-fpm パラメーターを渡します。

Fastcgi はすでに php5.3.5 のコアに含まれているため、設定時に --enable-fastcgi を追加する必要はありません。 php5.2などの古いバージョンではこの項目を追加する必要があります。

Nginx と PHP-FPM をインストールするときの構成情報は次のとおりです:

PHP-FPM のデフォルト設定 php-fpm.conf:

listen_address 127.0.0.1:9000 #これは、php の fastcgi プロセスがリッスンする IP アドレスとポートを表します

start_servers

サーバー

Max_spare_servers

php を実行するように Nginx を設定します: nginx.conf を編集して次のステートメントを追加します:

Location ~ .php$ { Fastcgi_pass 127.0.0.1:9000; fastcgi プロセス検出のリスニング ポートを指定し、nginx が通信しますこれを通じて php を使用して
fastcgi_index Index.php;
の ' fastcgi_param SCRIPT_FILENAME '- のポートをリッスンします
Nginx


ロケーション経由 引き継ぎ指示処理対象の 127.0.0.1:9000 のサフィックスとして php を持つすべてのファイル。ここでの IP アドレスとポートは、FastCGI プロセスによって監視される IP アドレスとポートです。
全体的なワークフロー: 1) FastCGI プロセス マネージャー php-fpm が自身を初期化し、メイン プロセス php-fpm を開始し、CGI 子プロセス start_servers を開始します。 メインプロセス php-fpm は主に fastcgi サブプロセスを管理し、ポート 9000 をリッスンします。 fastcgi 子プロセスは Web サーバーからの接続を待ちます。

2) クライアントリクエストが Web サーバー Nginx に到達すると、

Nginx

は location コマンドを使用して、サフィックスとして php を持つすべてのファイルを 127.0.0.1:9000 に渡して処理します。つまり、

Nginx

location コマンドを使用して、php をサフィックスとして持つすべてのファイルを 127.0.0.1:9000 に渡して処理します。 3) FastCGI プロセス マネージャー PHP-FPM は、子プロセス CGI インタープリターを選択して接続します。 Web サーバーは、CGI 環境変数と標準入力を FastCGI 子プロセスに送信します。 4) FastCGI サブプロセスは処理が完了すると、同じ接続から Web サーバーに標準出力とエラー情報を返します。 FastCGI 子プロセスが接続を閉じると、リクエストが処理されます。 5). 次に、FastCGI 子プロセスは、FastCGI プロセス マネージャー (Web サーバーで実行されている) からの次の接続を待機して処理します。

3. Nginx の IO モデル

まず、nginx でサポートされているイベント モデルは次のとおりです (nginx の wiki):

Nginx は次の接続処理方法 (I/O 多重化方式) をサポートしています。 )、これらのメソッド use ディレクティブを通じて指定できます。

  • 選択 – 標準的な方法。 現在のプラットフォームでこれより効率的な方法がない場合、これがコンパイル時のデフォルトの方法になります。このモジュールは、構成パラメータ –with-select_module および –without-select_module を使用して有効または無効にできます。
  • 世論調査 – 標準的な方法。 現在のプラットフォームでこれより効率的な方法がない場合、これがコンパイル時のデフォルトの方法になります。このモジュールは、構成パラメータ –with-poll_module および –without-poll_module を使用して有効または無効にできます。
  • kqueue – FreeBSD 4.1+、OpenBSD 2.9+、NetBSD 2.0、および MacOS X で使用される効率的な方法。デュアルプロセッサ MacOS X システムで kqueue を使用すると、カーネル パニックが発生する可能性があります。
  • epoll – Linux カーネル バージョン 2.6 以降のシステムで使用される効率的な方法。 SuSE 8.2 などの一部のディストリビューションには、2.4 カーネルで epoll をサポートするパッチがあります。
  • rtsig – Linux カーネル バージョン 2.2.19 以降のシステムで使用される、実行可能なリアルタイム シグナル。デフォルトでは、システム全体で表示できる POSIX リアルタイム (キュー) シグナルは 1024 個までです。この状況は負荷の高いサーバーでは非効率的であるため、カーネル パラメータ /proc/sys/kernel/rtsig-max を調整してキュー サイズを増やす必要があります。ただし、Linux カーネル バージョン 2.6.6-mm2 以降、このパラメータは使用されなくなり、プロセスごとに独立したシグナル キューが存在し、このキューのサイズを使用できるようになります。 RLIMIT_SIGPENDING パラメータの調整。このキューが混雑しすぎると、nginx はキューを放棄し、正常に戻るまでポーリング メソッドを使用して接続を処理し始めます。
  • /dev/poll – 効率的な方法。Solaris 7 11/99+、HP/UX 11.22+ (eventport)、IRIX 6.5.15+、および Tru64 UNIX 5.1A+ で使用されます。
  • eventport – 効率的な方法、 Solaris 10 で使用されています。カーネルのクラッシュを防ぐために、この セキュリティ パッチをインストールする必要があります。

epoll のみが効率的な方法です

"
アンケート。 epoll を使用するには、epoll_create(2)、epoll_ctl(2)、epoll_wait(2) の 3 つのシステム コールだけが必要です。これは 2.5.44 カーネルで導入され (epoll(4) は Linux カーネル 2.5.44 で導入された新しい API)、2.6 カーネルで広く使用されています。 epoll の利点

は、多数の

ソケットを開くプロセスをサポートします
  • 記述子 (FD) FD_SETSIZE で設定される select Limitデフォルト値は 2048 です。何万もの接続をサポートする必要がある IM サーバーには明らかに少なすぎます。現時点では、まずこのマクロを変更してカーネルを再コンパイルすることを選択できますが、これによりネットワーク効率が低下することもデータによって指摘されています。次に、マルチプロセス ソリューション (従来の Apache ソリューション) を選択できます。 Linux 上で作成されていますが、プロセスのコストは比較的小さいですが、それでも無視することはできません。また、プロセス間のデータ同期はスレッド間同期よりもはるかに効率が悪いため、完全な方法ではありません。 美しい計画。ただし、epoll にはこの制限はなく、開くことができるファイルの最大数は通常 2048 よりもはるかに大きくなります。たとえば、1 GB のメモリを搭載したマシンでは約 100,000 です。特定の数値は cat /proc Check /sys/fs/file-max です。一般に、この数値はシステム メモリに大きく関係します。

FD の数が増加しても IO 効率は直線的に減少しません

  • 従来の選択/ポーリングのもう 1 つの致命的な弱点は、大規模なソケット セットがあるにもかかわらず、ネットワーク遅延によりその一部のみがソケット セットに影響を与えることです。いつでも利用可能 ソケットは「アクティブ」ですが、select/poll を呼び出すたびにコレクション全体が線形にスキャンされるため、効率が線形に低下します。しかし、epoll にはこの問題はなく、「アクティブな」ソケット上でのみ動作します。これは、カーネル実装では、epoll が各 fd のコールバック関数に基づいて実装されているためです。次に、「アクティブ」ソケットのみがコールバック関数をアクティブに呼び出し、他のアイドル状態のソケットは呼び出されません。この時点では、駆動力は OS カーネルにあるため、epoll は「疑似」AIO を実装します。いくつかでは ベンチマークでは、高速 LAN 環境など、基本的にすべてのソケットがアクティブな場合、epoll は select/poll よりも効率的ではありません。逆に、epoll_ctl を使用しすぎると、効率がわずかに低下します。ただし、アイドル接続を使用して
  • WAN

環境をシミュレートすると、epoll の効率は select/poll の効率よりもはるかに高くなります。

  • mmapを使用して、カーネルとユーザー空間の間のメッセージ受け渡しを高速化します。

この点は、実際には epoll の特定の実装に関係します。 select、poll、epoll のいずれの場合でも、カーネルは FD メッセージをユーザー空間に通知する必要があります。この時点で、epoll は、ユーザー空間内の同じメモリを mmap することによって実装されます。カーネル。そして、私のように 2.5 カーネルから epoll をフォローしている場合は、手動の mmap ステップを決して忘れることはありません。

  • カーネルの微調整

これは実際には epoll の利点ではなく、Linux プラットフォーム全体の利点です。 Linux プラットフォームを疑うかもしれませんが、Linux プラットフォームが提供するカーネルを微調整する機能を避けることはできません。たとえば、カーネルTCP/IPプロトコル スタックはメモリ プールを使用して sk_buff 構造を管理するため、このメモリ プール (skb_head_pool) のサイズは実行時に動的に調整できます。これは echo XXXX>/proc/sys/net/core/hot_list_length によって行われます。もう 1 つの例は、listen 関数の 2 番目のパラメータ (TCP が 3 ウェイ ハンドシェイクを完了した後のパケット キューの長さ) です。これも、プラットフォームのメモリ サイズに応じて動的に調整できます。データ パケットの数は膨大ですが、各データ パケット自体のサイズは非常に小さい特別なシステムで、最新の NAPI ネットワーク カード ドライバー アーキテクチャも試しました。

(epoll コンテンツ、epoll_Interactive Encyclopedia を参照)

4. Nginx の最適化

1. 1 ). Nginx のコンパイルを削減した後、

のファイルサイズ Nginx をコンパイルする場合、デフォルトではデバッグ モードで実行され、コンパイル完了後に大量のトラッキング情報と ASSERT 情報が挿入されます。コンパイル前に Nginx のデバッグ モードをキャンセルすると、コンパイル後の Nginx の容量は数百キロバイトのみになります。したがって、コンパイル前に関連するソース コードを変更し、デバッグ モードをキャンセルできます。具体的な方法は次のとおりです。

Nginx ソース コード ファイルが解凍されたら、ソース コード ディレクトリで auto/cc/gcc ファイルを見つけ、その中の次の行を見つけます。

  1. # debug  
  2. CFLAGS=”$CFLAGS -g” 

これらの 2 行をコメント アウトするか削除します。デバッグモードをキャンセルします。

2. 特定の CPU の CPU タイプのコンパイル最適化を指定します

Nginx をコンパイルするとき、デフォルトの GCC コンパイル パラメーターは「-O」です。GCC コンパイルを最適化するには、次の 2 つのパラメーターを使用できます。 CPU の種類を確認するには、次のコマンドを使用します:

  1. --with-cc-opt='-O3' 
  2. --with-cpu-opt=CPU  #为特定的 CPU 编译,有效的值包括:
    pentium, pentiumpro, pentium3, # pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64 

2. TCMalloc を使用して Nginx のパフォーマンスを最適化します

TCMalloc の正式名は Thread-Caching Malloc で、オープン ソース ツール google- のメンバーです。 Googleが開発したperftools。標準の glibc ライブラリの Malloc と比較して、TCMalloc ライブラリはメモリ割り当てがはるかに効率的で高速であるため、同時実行性が高い状況でのサーバーのパフォーマンスが大幅に向上し、システムの負荷が軽減されます。以下は、TCMalloc ライブラリのサポートを Nginx に追加する方法について簡単に紹介します。

TCMalloc ライブラリをインストールするには、libunwind (32 ビット オペレーティング システムをインストールする必要はありません) と google-perftools という 2 つのソフトウェア パッケージをインストールする必要があります。 libunwind ライブラリは、プログラム ベースの基本的な関数呼び出しチェーンと関数呼び出しレジスタを提供します。 64 ビット CPU およびオペレーティング システムでの機能。 TCMallocを利用してNginxを最適化する具体的な操作手順を以下に説明します。

1) libunwind ライブラリをインストールします

ここでダウンロードしたものは、libunwind-0.99-alpha.tar から対応する libunwind バージョンをダウンロードできます。ガズ。インストール プロセスは次のとおりです:

  1. [root@localhost home]#cat /proc/cpuinfo | grep "model name" 
2) google-perftools


をインストールするには、http://google-perftools.googlecode.com から対応する google-perftools バージョンをダウンロードできます。ここでダウンロードしたものは次のとおりです。 google-perftools-1.8。インストールプロセスは次のとおりです:

  1. [root@localhost home]#tar zxvf libunwind-0.99-alpha.tar.gz  
  2. [root@localhost home]# cd libunwind-0.99-alpha/  
  3. [root@localhost libunwind-0.99-alpha]#CFLAGS=-fPIC ./configure  
  4. [root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC  
  5. [root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC install 

この時点で、google-perftools のインストールは完了です。

3). Nginx を再コンパイルします

Nginx が google-perftools をサポートするには、インストール プロセス中に「–with-google_perftools_module」オプションを追加して Nginx を再コンパイルする必要があります。インストールコードは以下の通りです:

  1. [root@localhost home]#tar zxvf google-perftools-1.8.tar.gz  
  2. [root@localhost home]#cd google-perftools-1.8/  
  3. [root@localhost google-perftools-1.8]# ./configure  
  4. [root@localhost google-perftools-1.8]#make && make install  
  5. [root@localhost google-perftools-1.8]#echo "/usr/
    local/lib" 
    > /etc/ld.so.conf.d/usr_local_lib.conf  
  6. [root@localhost google-perftools-1.8]# ldconfig 

これでNginxのインストールは完了です。

4). google-perftools のスレッド ディレクトリを追加します

スレッド ディレクトリを作成し、ファイルを /tmp/tcmalloc に配置します。操作は次のとおりです:

  1. [root@localhostnginx-0.7.65]#./configure \  
  2. >--with-google_perftools_module --with-http_stub_status_module  --prefix=/opt/nginx  
  3. [root@localhost nginx-0.7.65]#make  
  4. [root@localhost nginx-0.7.65]#make install 

5) Nginx のメイン設定ファイルを変更します

nginx.conf ファイルを変更し、pid 行の下に次のコードを追加します:

  1. [root@localhost home]#mkdir /tmp/tcmalloc  
  2. [root@localhost home]#chmod 0777 /tmp/tcmalloc 

次に、Nginx を再起動してロードを完了します。 google-perftools。

6). 実行ステータスを確認します

google-perftools が正常にロードされたことを確認するには、次のコマンドで確認できます:

  1. #pid        logs/nginx.pid;  
  2. google_perftools_profiles /tmp/tcmalloc; 

Nginx では worker_processes の値が 4 に設定されているため、構成ファイルでは、4 つの Nginx スレッドが開かれ、各スレッドには 1 行のレコードが含まれます。各スレッドファイルの後の数値は起動したNginxのpid値です。 この時点で、TCMallocを使用したNginxの最適化操作は完了です。

3. Nginx カーネル パラメーターの最適化

カーネル パラメーターの最適化は、主に Linux システムの Nginx アプリケーションのシステム カーネル パラメーターの最適化です。

参考までに、最適化の例を以下に示します。

  1. [root@ localhost home]# lsof -n | grep tcmalloc  
  2. nginx      2395 nobody   9w  REG    8,8       0    1599440 /tmp/tcmalloc.2395  
  3. nginx      2396 nobody   11w REG   8,8       0    1599443 /tmp/tcmalloc.2396  
  4. nginx      2397 nobody   13w REG  8,8        0    1599441  /tmp/tcmalloc.2397  
  5. nginx     2398 nobody    15w REG  8,8     0    1599442 /tmp/tcmalloc.2398 

上記のカーネルパラメータ値を /etc/sysctl.conf ファイルに追加し、次のコマンドを実行して有効にします:

  1. [root@ localhost home]#/sbin/sysctl -p 

下面对实例中选项的含义进行介绍:

net.ipv4.tcp_max_tw_buckets选项用来设定timewait的数量,默认是180 000,这里设为6000。

net.ipv4.ip_local_port_range选项用来设定允许系统打开的端口范围。

net.ipv4.tcp_tw_recycle选项用于设置启用timewait快速回收。

net.ipv4.tcp_tw_reuse选项用于设置开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接。

net.ipv4.tcp_syncookies选项用于设置开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies进行处理。

net.core.somaxconn选项的默认值是128, 这个参数用于调节系统同时发起的tcp连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此,需要结合并发请求数来调节此值。

net.core.netdev_max_backlog选项表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目。

net.ipv4.tcp_max_orphans选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤立连接将立即被复位并打印出警告信息。这个限制只是为了防止简单的DoS攻击。不能过分依靠这个限制甚至人为减小这个值,更多的情况下应该增加这个值。

net.ipv4.tcp_max_syn_backlog选项用于记录那些尚未收到客户端确认信息的连接请求的最大值。对于有128MB内存的系统而言,此参数的默认值是1024,对小内存的系统则是128。

net.ipv4.tcp_synack_retries参数的值决定了内核放弃连接之前发送SYN+ACK包的数量。

net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。

net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。默认值是60秒。正确设置这个值非常重要,有时即使一个负载很小的Web服务器,也会出现大量的死套接字而产生内存溢出的风险。

net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。

如果发送端要求关闭套接字,net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。接收端可以出错并永远不关闭连接,甚至意外宕机。

net.ipv4.tcp_fin_timeout的默认值是60秒。需要注意的是,即使一个负载很小的Web服务器,也会出现因为大量的死套接字而产生内存溢出的风险。FIN-WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能消耗1.5KB的内存,但是其生存期长些。

net.ipv4.tcp_keepalive_time选项表示当keepalive启用的时候,TCP发送keepalive消息的频度。默认值是2(单位是小时)。

4. PHP-FPM的优化

如果您高负载网站使用PHP-FPMFastCGI,这些技巧也许对您有用:

1)增加FastCGI进程数

PHP FastCGI子进程数调到100或以上,4G内存的服务器上200就可以建议通过压力测试获取最佳值。

2)增加 PHP-FPM打开文件描述符的限制

标签rlimit_files用于设置PHP-FPM对打开文件描述符的限制,默认值为1024。这个标签的值必须和Linux内核打开文件数关联起来,例如,要将此值设置为65 535,就必须在Linux命令行执行“ulimit -HSn 65536”。

       然后 增加 PHP-FPM打开文件描述符的限制:
     # vi /path/to/php-fpm.conf
    找到
1024”
1024更改为 4096或者更高
.
重启 PHP-FPM.

         3)适当增加max_requests

    标签max_requests指明了每个children最多处理多少个请求后便会被关闭,默认的设置是500。

     500

   

5.   Nginx的php漏洞

脆弱性の紹介: nginx は、リバース プロキシとしてよく使用されるだけでなく、PHP の動作も非常によくサポートする高性能 Web サーバーです。 80sec は、デフォルトでは、PHP のあらゆる種類のファイルを誤って解析する可能性があり、悪意のある攻撃者が PHP サーバーをサポートする nginx を侵害する可能性があることを発見しました。


脆弱性分析: nginx は、デフォルトで CGI モードで実行される php をサポートします。たとえば、設定ファイルでは、

<code><br>location ~ .php$ {<br>root html;<br>fastcgi_pass 127.0.0.1:9000;<br>fastcgi_index index.php;<br>fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;<br>include fastcgi_params;<br>}<br>
的方式支持对php的解析,location对请求进行选择的时候会使用URI环境变量进行选择,其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定,而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的,这里就是产生问题的点。而为了较好的支持PATH_INFO的提取,在PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。
那么假设存在一个http://www.80sec.com/80sec.jpg,我们以如下的方式去访问

http://www.80sec.com/80sec.jpg/80sec.php


将会得到一个URI
<br>/80sec.jpg/80sec.php<br>
经过location指令,该请求将会交给后端的fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为
<br>/scripts/80sec.jpg/80sec.php<br>
而在其他的webserver如lighttpd当中,我们发现其中的SCRIPT_FILENAME被正确的设置为
<br>/scripts/80sec.jpg<br>
所以不存在此问题。
后端的fastcgi在接受到该选项时,会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理,一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为
<br>/scripts/80sec.jpg和80sec.php<br>
最后,以/scripts/80sec.jpg作为此次请求需要执行的脚本,攻击者就可以实现让nginx以php来解析任何类型的文件了。

POC: 访问一个nginx来支持php的站点,在一个任何资源的文件如robots.txt后面加上/80sec.php,这个时候你可以看到如下的区别:

访问http://www.80sec.com/robots.txt
<br>HTTP/1.1 200 OK<br>Server: nginx/0.6.32<br>Date: Thu, 20 May 2010 10:05:30 GMT<br>Content-Type: text/plain<br>Content-Length: 18<br>Last-Modified: Thu, 20 May 2010 06:26:34 GMT<br>Connection: keep-alive<br>Keep-Alive: timeout=20<br>Accept-Ranges: bytes<br>
访问访问http://www.80sec.com/robots.txt/80sec.php
<br>HTTP/1.1 200 OK<br>Server: nginx/0.6.32<br>Date: Thu, 20 May 2010 10:06:49 GMT<br>Content-Type: text/html<br>Transfer-Encoding: chunked<br>Connection: keep-alive<br>Keep-Alive: timeout=20<br>X-Powered-By: PHP/5.2.6<br>
其中的Content-Type的变化说明了后端负责解析的变化,该站点就可能存在漏洞。

漏洞厂商:http://www.nginx.org

解决方案:

我们已经尝试联系官方,但是此前你可以通过以下的方式来减少损失
<br>关闭cgi.fix_pathinfo为0<br>
或者
<br>if ( $fastcgi_script_name ~ ..*/.*php ) {<br>return 403;<br>}<br>location ~ .php$ {

root html;

fastcgi_pass 127.0.0.1 を使用できます。 :9000;

fastcgi_indexindex.php;

fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;

include fastcgi_params;

}

🎜 は、location がリクエストを選択するときに、URI 環境変数を使用して選択します。このうち、バックエンド Fastcgi に渡されるキー変数 SCRIPT_FILENAME は、nginx によって生成された $fastcgi_script_name によって決定されます。これにより、$fastcgi_script_name が URI 環境変数によって直接制御されていることがわかります。 PATH_INFO の抽出をより適切にサポートするために、PHP 設定オプションに cgi.fix_pathinfo オプションが存在します。その目的は、SCRIPT_FILENAME から実際のスクリプト名を抽出することです。 🎜http://www.80sec.com/80sec.jpg があると仮定して、次の方法でアクセスします🎜🎜🎜http://www.80sec .com/80sec.jpg/80sec.php🎜🎜🎜 は URI を取得します🎜🎜/80sec.jpg/80sec.php🎜🎜 location コマンドの後に、リクエストこれは処理のためにバックエンドの fastcgi に渡され、nginx は環境変数 SCRIPT_FILENAME を設定します。その内容は 🎜🎜/scripts/80sec.jpg/80sec.php🎜🎜 です。 lighttpd などの Web サーバーでは、SCRIPT_FILENAME が 🎜🎜/scripts/80sec.jpg🎜🎜 に正しく設定されていることが判明したため、この問題は存在しません。 🎜バックエンドの fastcgi がこのオプションを受け取ると、fix_pathinfo 設定に基づいて SCRIPT_FILENAME に対して追加の処理を実行するかどうかを決定します。一般に、fix_pathinfo が設定されていない場合、ルーティングの選択に PATH_INFO を使用するアプリケーションに影響を与えるため、このオプションは通常はオンになるように設定されています。このオプションを渡すと、Php は実際のスクリプト ファイル名を検索します。このとき、SCRIPT_FILENAME と PATH_INFO は 🎜🎜/scripts/80sec.jpg と 2 つに分割されます。 80sec.php🎜🎜最後に、このリクエストで実行する必要があるスクリプトとして /scripts/80sec.jpg を使用すると、攻撃者は PHP を使用して nginx にあらゆる種類のファイルを解析させることができます。 🎜🎜POC: nginx が PHP をサポートしているサイトにアクセスします。robots.txt などのリソース ファイルの後に /80sec.php を追加します。この時点で、次の違いが確認できます。 🎜🎜 http://www. /robots.txt🎜<code>🎜HTTP/1.1 200 OK🎜Server: nginx/0.6.32🎜Date: Thu, 20 May 2010 10:05:30 GMT🎜Content-Type: text/plain🎜Content-Length: 18 🎜Last-Modified: Thu, 20 May 2010 06:26:34 GMT🎜Connection: keep-alive🎜Keep-Alive: timeout=20🎜Accept-Ranges: bytes🎜🎜 http:// /www にアクセスしてください。 80sec.com/robots.txt/80sec.php🎜🎜HTTP/1.1 200 OK🎜サーバー: nginx/0.6.32🎜日付: 木、20 5 月 2010 10:06:49 GMT🎜Content-Type : text/ html🎜Transfer-Encoding: chunked🎜Connection: keep-alive🎜Keep-Alive: timeout=20🎜X-Powered-By: PHP/5.2.6🎜🎜Content-Type の変更点の説明 バックエンドが変更の解析を担当しているため、サイトが脆弱になる可能性があります。 🎜🎜脆弱性ベンダー: http://www.nginx.org🎜🎜解決策: 🎜🎜公式に連絡を試みましたが、その前に次の方法で損失を減らすことができます🎜🎜cgi.fix_pathinfo を閉じてください0🎜 🎜or🎜🎜if ( $fastcgi_script_name ~ ..*/.*php ) {🎜return 403;🎜}🎜🎜🎜 PS: 分析プロセスについては、laruence Daniel に感謝します。助けてください🎜 🎜 上記では、Nginx の動作原理、最適化、抜け穴を紹介しました。 、関連コンテンツも含めて、PHP チュートリアルに興味のある友人に役立つことを願っています。 🎜 🎜 🎜
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート