この記事は、データが単純なものから複雑なものまで示されているため、初心者に優しいものです。 DevOps エンジニアとしてのキャリアを始めたとき、そのような資料が不足していました。 Nginxの仕組みと、実際の経験からのヒントとコツについてお話しします。 NGINXの仕組み NGINX は、ノンブロッキングのイベント駆動型アーキテクチャ上に構築されています。 1 つのプライマリ プロセス、複数の worker_processes、および 2 つのキャッシュ管理プロセスがあります。これを確認するには、スイッチを指定して を実行するだけです。 ps コマンド ps -ef --forest | grep nginx プライマリ プロセスはルートとして実行され、次のような昇格を必要とする操作を実行します。 構成の読み取り; ポートを開く; 新しいプロセスの作成。 ワーカーはすべての作業を行います: ネットワーク接続を処理します。 ディスクへのデータの読み取りと書き込み。 バックエンド サーバーと通信します。 通常、ワーカーの数は CPU コアの数と同じです。これにより、システム リソースを可能な限り効率的に使用できます。 Worker_processes は、次の 2 種類のソケットをリッスンします。 listener - 新しいクライアント イベント (接続要求) 用。 接続 - 処理が必要なイベント用。 worker_processes は、2 種類の API ( または ) を使用してイベントを待機します。リスナー ソケットで新しいクライアント イベントを受信すると、worker_process は新しいソケット接続を作成します。 epoll kqueue 接続ソケットでイベントを受信すると、worker_process はこの要求を実行します。イベントの処理後、イベントはブロックされませんが、スタンバイ モードになるため、オペレーティング システムのコンテキスト スイッチの数が最小限に抑えられます。 上記のアーキテクチャでは、NGINX 構成の更新は、プライマリ プロセスに SIGHUP シグナルを送信するのと同じくらい簡単です。 NGINX が適切に構成されていれば、各ワーカー プロセスは同時に数十万の接続を処理できます。 その後、worker_processes は新しい接続の受け入れを停止し、イベントを処理した現在の接続は (キープアライブを待たずに) 閉じられます。すべての接続が閉じられるとすぐに、worker_process は終了します。これにより、接続を失ったり、リソースをアイドル状態にしたり、クライアント サービスを中断したりすることなく、サーバー構成を更新できます。 ヒントとコツ 1.適用する前に、書き込まれた構成の正確性を確認します 構成を変更または作成した後、構成ファイルの構文と書き込みの正確さを確認する必要があります。 Nginx では、次のコマンドを使用して、構成の書き込みが正しいことを確認できます。 nginx -t 2.サービスを再起動せずにNginxをリロードする サービスを再起動せずに設定を適用することをお勧めします。これにより、現在の接続が終了せず、サービスをロードする際の待ち時間がなくなります。つまり、ダウンタイムがありません。 nginx -s reload また /etc/init.d/nginx reload また service nginx reload 3. Nginx server_tokens を無効にする デフォルトでは、Nginx の server_tokens ディレクティブは Nginx のバージョン番号を表示します。これは、自動生成されたすべてのエラー ページと、サーバー ヘッダーのすべての HTTP 応答で直接表示されます。 これにより、情報漏えいが発生する可能性があります。許可されていないユーザーが Nginx のバージョンを知ることができます。次のように設定して、Nginx構成ファイルのディレクティブである を無効にすると役立ちます。 server_tokens server_tokens off; 4. 従来の SSL/TLS プロトコルを無効にする ssl_protocols TLSv1.2 TLSv1.3; 5. 望ましくない HTTP メソッドを無効にする 使用されず、Web サーバーに実装する必要のない HTTP メソッドを無効にします。 Nginx 仮想ホスト構成ファイルの location ブロックに次の条件を追加すると、サーバーは 、および メソッドのみを許可し、 や などのメソッドを除外します。 GET, HEAD POST DELETE TRACE location / { limit_except GET HEAD POST { deny all; } } もう 1 つの方法は、サーバー セクション (またはサーバー ブロック) に次の条件を追加することです。より一般的なものと見なすこともできますが、ロケーション コンテキストの には注意する必要があります。 if ステートメント if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; } 6. Nginx のアクセス ログとエラー ログのセットアップと構成 Nginx のアクセス ログとエラー ログはデフォルトで有効になっており、それぞれ logs と ます。 logs/error.log logs/access.log, 場所を変更する場合は、Nginx 構成ファイルで error_log ディレクティブを使用できます。このディレクティブを使用して、重大度レベルに従ってログに記録するログを指定することもできます。 たとえば、重大度が重大な場合、Nginx は重大な問題と、重大度レベルが重大な問題よりも高いすべての問題をログに記録します。重大度レベルをクリティカルに設定するには、次のように error_log ディレクティブを設定します。 error_log logs/error.log crit; error_log 重大度レベルの完全なリストは、Nginx の公式ドキュメントで確認できます。 Nginx 構成ファイルの access_log ディレクティブを変更して、アクセス ログの非標準の場所を指定することもできます。 最後に、Nginx のドキュメントで説明されているように、log_format ディレクティブを使用して、ログに記録されるメッセージの形式をカスタマイズできます。 7. Nginx ワーカー接続 構成する重要な設定の 1 つは、Nginx 構成ファイル のワーカー プロセスの数とワーカー接続の数です。 /etc/nginx/nginx.conf DDoS 攻撃を処理するために、ワークフローとワーカーの接続をより高い値またはより低い値に徐々に調整します。 events { worker_connections 20000; } この設定により、各ワーカー プロセスは最大 20,000 の接続を処理できます。 8.リクエストレート制限 DDoS 攻撃を防ぐための多くの有効な戦術の中で、最も単純で最も効果的な戦術の 1 つは、受信トラフィックのレートを制限することです。 たとえば、NGINX が受信リクエストを受け入れるレートを、指定された期間の特定のクライアント IP アドレスからのサービスの平均レートに指定できます。 Nginx 構成ファイルで limit_req_zone ディレクティブを設定して、リクエストの数を制限します。 limit_req_zone $binary_remote_addr zone=req_per_ip:1m rate=30r/m; server { location /login { limit_req zone=req_per_ip; } } この例では、最大 16,000 (1m) の一意の IP アドレスを保持できる one という名前のストレージ領域を作成します。30r/m は、1 分間に 30 リクエストのみが許可されることを意味します。 次に limit_req ディレクティブを使用して、特定の場所またはファイル (この場合はログイン) への接続速度を制限します。 9. 接続数の制限 1 つのクライアント IP アドレスから開くことができる接続の数を制限できます。ここでは、limit_conn_zone および ディレクティブを設定して、IP アドレスごとの接続数を制限しています。 limit_conn limit_conn_zone $binary_remote_addr zone=conn_per_ip:1m; server { location / { limit_conn conn_per_ip 10; } } この例では、 という名前のストレージ ゾーンを作成して、指定されたキー (この場合はクライアントの IP アドレス $binary_remote_addr) のリクエストを保存します。 ディレクティブは、各クライアントの IP アドレスから 10 個の接続を設定します。 conn_per_ip limit_conn 10.タイムアウトオプション 接続が遅い場合は、接続を長時間開いたままにしようとしている可能性があります。その結果、サーバーは新しい接続を受け入れることができません。 server { client_body_timeout 5s; client_header_timeout 5s; } この例では、 ディレクティブは、Nginx がクライアント ボディ エントリ間で待機する時間を指定し、 は、Nginx がクライアント ヘッダー エントリ間で待機する時間を指定します。どちらも 5 秒に設定されています。 client_body_timeout client_header_timeout 11. リクエストのサイズを制限する 同様に、大きなバッファ値または大きな HTTP 要求サイズは、DDoS 攻撃を容易にします。そのため、DDoS 攻撃を軽減するために、Nginx 構成ファイルで次のバッファー値を制限します。 client_body_buffer_size 200K; client_header_buffer_size 2k; client_max_body_size 200k; large_client_header_buffers 3 1k; どこ、 — (デフォルトは 8k または 16k) ディレクティブは、クライアント要求本文バッファーのサイズを指定します。 client_body_buffer_size 1k - ディレクティブは、クライアントからのリクエスト ヘッダーのヘッダー バッファー サイズを設定します。大部分の要求には、1Kb のバッファ サイズで十分です。 client_header_buffer_size 1k クライアント (wap クライアントなど) から送信されたカスタム ヘッダーまたは巨大な Cookie がある場合は、この値を増やします。 - ディレクティブは、リクエスト ヘッダーの Content-Length 行で指定されたクライアント リクエスト ボディの最大許容サイズを設定します。 client_max_body_size 1k サイズが指定されたサイズよりも大きい場合、クライアントは「Request Entity Too Large」エラー (413) を受け取ります。 POST メソッドを使用してファイルをアップロードする場合は、この値を増やしてください。 - ディレクティブは、クライアント要求から大きなヘッダーを読み取るためのバッファーの最大数とサイズを割り当てます。 large_client_header_buffers 2 1k デフォルトでは、1 つのバッファーのサイズは、プラットフォームに応じてページ サイズと同じで、4K または 8K です。 作業要求の最後に接続がキープアライブ状態になると、これらのバッファは解放されます。 たとえば、2x1k は 2 KB のデータ URI を受け入れます。また、悪質なボットや DoS 攻撃との戦いにも役立ちます。 12. IP ブラックリスト 攻撃に使用されたクライアント IP アドレスを特定できる場合は、拒否ディレクティブを使用してそれらをブラックリストに登録し、NGINX および NGINX Plus がそれらの接続または要求を受け入れないようにすることができます。 location / { deny 111.111.111.4; deny 111.111.111.0/24; } この例では、最初の Deny は特定の IP アドレスをブロックし、2 番目の Deny は IP アドレスの範囲全体をブロックします。 13. IP ホワイトリスト Web サイトまたはアプリケーションが、クライアント IP アドレスの 1 つ以上の特定のセットまたは範囲からのアクセスのみを許可されている場合、allow ディレクティブと deny ディレクティブを一緒に使用して、それらのアドレスのみがサイトまたはアプリケーションにアクセスできるようにすることができます。 location / { allow 111.111.111.4; deny all; } 特定のローカル ネットワーク上のアドレスのみにアクセスを制限できます。ここで、deny all ディレクティブは、allow ディレクティブで指定された範囲にないすべてのクライアント IP アドレスをブロックします。 14. ファイルまたは場所へのアクセスをブロックする Nginx を使用して、ファイルまたは場所へのアクセスを完全にブロックできます。たとえば、register.php ファイルが攻撃の対象であることに気付いた場合、このファイルへのアクセスを完全にブロックできます。 location /register { deny all; return 444; } これにより、このファイルにアクセスしようとするすべてのリクエストが破棄されます。コード 444 は、応答なしで接続を閉じます。 15. sysctl ベースの保護を有効にする sysctl ベースの保護を有効にします。サーバーのカーネルとシステム変数を微調整できます。 ファイルを編集し、次のようにこれら 2 行を 1 に設定します。 /etc/sysctl.conf net.ipv4.conf.all.rp_filter = 1 net.ipv4.tcp_syncookies = 1 最初の設定は IP アドレス スプーフィング保護を有効にし、2 番目の設定は TCP SYN Cookie 保護を有効にします。 16.ロードバランサーとしてのNginx Nginx をロード バランサーとして使用する場合、サーバーごとの接続数を制限するように設定を構成できます。 upstream domain { server 111.111.111.4:80 max_conns=100; server 111.111.111.5:80 max_conns=100; queue 20 timeout=10s; } ここで、max_conns ディレクティブは、Nginx がサーバーに対して開くことができる接続の数を指定します。 queue ディレクティブは、そのグループ内のすべてのサーバーが接続制限に達したときに、キューに入れられるリクエストの数を制限します。 最後に、timeout ディレクティブは、リクエストをキューに保持できる期間を指定します。 17. 特定のユーザー エージェントを拒否する サーバーを悪用している可能性のあるユーザー エージェント (クローラー、ボット、スパマーなど) を簡単にブロックできます。 ## Block download agents ## if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; } ## Block some robots ## if ($http_user_agent ~* msnbot|scrapbot|PxBroker) { return 403; } 18.紹介スパムをブロックする 紹介スパムは危険です。リファラー フィールドがスパム サイトにリンクしているため、ウェブログ (公開されている場合) を介した SEO ランキングが損なわれる可能性があります。これらの行を使用して、リファラー スパマーへのアクセスをブロックできます。 if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ) { return 403; } 19. 画像のホットリンクを停止する 画像のホットリンクまたは HTML は、誰かがあなたのサイトをあなたの画像の 1 つにリンクしているが、それを自分のサイトに表示していることを意味します。 帯域幅にお金を払い、コンテンツをサイトの一部のように見せることになります.これは通常、フォーラムやブログで行われます。サーバーの同じレベルで画像のホットリンクをブロックして停止することを強くお勧めします。 location /images/ { valid_referers none blocked www.domain.com domain.com; if ($invalid_referer) { return 403; } } 20. ファイアウォール レベルで IP アドレスごとの接続数を制限する Web サーバーは接続を監視し、1 秒あたりの接続数を制限する必要があります。これは 101 を提供します。pf と iptables の両方が、Nginx サーバーにアクセスする前にエンドユーザーをブロックできます。 Linux Iptables: 1 秒あたりの Nginx 接続のスロットリング。 次の例では、IP がポート 80 で 60 秒以内に 15 回を超える接続試行を行うと、着信接続がドロップされます。 /sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set && \ /sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 15 -j DROP && \ service iptables save 21. 一部のブラウザでコンテンツ タイプ スニッフィングを無効にする 応答で誤ったコンテンツ タイプが指定されている場合、ブラウザは予期しない方法で応答を処理する可能性があります。 コンテンツ タイプがレンダリング可能なテキストベースの形式であると判断された場合、ブラウザは通常、応答の実際の内容に関係なく、応答をその形式であると解釈しようとします。 さらに、特定のブラウザーの特異性により、他の指定されたコンテンツ タイプが HTML として解釈される場合があります。これにより、画像が HTML としてレンダリングされるなどの「安全な」コンテンツが発生し、特定の条件下でクロスサイト スクリプティング攻撃が可能になる可能性があります。以下を構成に追加します。 add_header X-Content-Type-Options nosniff; 22. クロスサイト スクリプティング (XSS) フィルターを有効にする 次の行を構成ファイルに追加して、Nginx Web サーバーで X-XSS-Protection ヘッダーを有効にします。完了したら、変更を保存して Nginx をリロードします。 add_header X-XSS-Protection "1; mode=block"; 23. HTTP/2 サポートの構成 HTTP/2 は、HTTP 1.x ネットワーク プロトコルの後継です。 HTTP/2 は、待ち時間の短縮、プロトコルのオーバーヘッドの最小化、リクエストの優先順位付けのサポートの追加、および Web アプリケーションの読み込みの高速化のために広く使用されています。 したがって、パフォーマンス最適化の手法と戦略を最新の状態に保つことが重要です。 HTTP/2 の主な目的は、Web ページの全体的な読み込み時間を短縮して、パフォーマンスを最適化することです。 また、HTTP/2 を使用する場合は SSL/TLS 暗号化が必須であるため、ネットワークとサーバー リソースの使用、およびセキュリティの強化にも焦点を当てています。 前提条件として、ビルド時に Nginx のバージョンが 1.9.5 以降であることを確認してください。それ以外の場合は、手動で追加する必要があり、サーバーで SSL/TLS を有効にする必要があります。 HTTPS サーバー ブロックは次のようになります。 server { listen 443 ssl http2; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; } 24. (CSP) を追加する コンテンツ セキュリティ ポリシー CSP は、クロスサイト スクリプティング (XSS) やデータ インジェクション攻撃など、特定の種類の攻撃を検出して緩和するのに役立つ追加のセキュリティ レイヤーです。これらの攻撃は、データの盗難、Web サイトの破損、およびマルウェアの配布に使用されます。 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; 25. Nginx の監視 サーバーの状態は常に監視する必要があります。たとえば、サードパーティの有料サービスを通じて、サーバーに定期的にリクエストを送信することで、サーバーが返すものを見ることができます。または、すべてを微調整することもできます。それにはさまざまな方法があります。詳細については、 を参照してください。 Nginx ブログ 代わりに結論 柔軟に対応し、ケースごとに個別に構成を開発することが不可欠です。