基本#
TCP/IP ネットワークモデル#
-
アプリケーション層:ユーザーに一連のアプリケーションを提供する役割を担う。
HTTP、FTP、Telnet、DNS、SMTP など。アプリケーション層はユーザーモードで動作する。
-
トランスポート層:エンドツーエンドの通信を担当する。
TCP:フロー制御、タイムアウト再送、輻輳制御など。/UDP
MSS(最大セグメントサイズ) -> TCP セグメント(TCP Segment)
-
ネットワーク層:ネットワークパケットのカプセル化、分割、ルーティング、転送を担当する。
IP プロトコル:アドレッシング、ルーティング。/ICMP
MTU(最大転送単位) -> 分割
-
リンク層:物理ネットワーク内でのネットワークパケットの転送を担当し、ネットワークパケットのフレーミング、MAC アドレッシング、エラーチェック、ネットワークフレームの NIC を介した転送などを行う。/ARP
OSI 七層ネットワークモデル#
- アプリケーション層:アプリケーションに統一インターフェースを提供する役割;
- 表示層:データを別のシステムが認識できる形式に変換する役割;
- セッション層:表示層エンティティ間の通信セッションを確立、管理、終了する役割;
- トランスポート層:エンドツーエンドのデータ転送を担当する;
- ネットワーク層:データのルーティング、転送、分割を担当する;
- データリンク層:データのフレーミングとエラーチェック、MAC アドレッシングを担当する;
- 物理層:物理ネットワーク内でデータフレームを転送する役割;
URL からウェブページ表示まで#
- URL を解析 -> Web サーバーとファイル名
- HTTP リクエストを生成
- DNS ドメイン名解決
- TCP 三回のハンドシェイクで接続を確立
- TCP メッセージを生成
- IP メッセージを生成 -> IP アドレスはリモートロケーションを担当
- MAC メッセージを生成(ARP を使用して MAC アドレスを照会) -> MAC アドレスはポイントツーポイントの転送を担当
- NIC は、先頭にヘッダーと開始フレーム区切りを追加し、末尾にエラーチェック用のフレームチェックシーケンス(FCS)を追加し、デジタル情報 -> 電気信号
- スイッチ(二層ネットワークデバイス)は、スイッチの MAC アドレステーブル(MAC - ポート)を確認し、存在しない場合はすべてのポートに転送
- ルーター(三層ネットワークデバイス)は、ルーティングテーブルで IP を確認(ルーティングマッチ)、ARP で MAC を確認。
- サーバーに到達し、データパケットを解析し、HTTP 応答を送信
- クライアントが HTTP 応答を受信し、ページをレンダリング
- TCP 四回のハンドシェイクで接続を切断
転送プロセス中、ソース IP アドレスとターゲット IP アドレスは変わらず、ソース MAC とターゲット MAC は変化する。
全体的には以下のステップに分かれる:
- ブラウザに指定されたウェブページの URL を入力。
- ブラウザは DNS プロトコルを介して、ドメイン名に対応する IP アドレスを取得。
- ブラウザは IP アドレスとポート番号に基づいて、ターゲットサーバーに TCP 接続リクエストを送信。
- ブラウザは TCP 接続上で、サーバーに HTTP リクエストメッセージを送信し、ウェブページの内容を取得するように要求。
- サーバーは HTTP リクエストメッセージを受信後、リクエストを処理し、HTTP 応答メッセージをブラウザに返す。
- ブラウザは HTTP 応答メッセージを受信後、応答ボディ内の HTML コードを解析し、ウェブページの構造とスタイルをレンダリングし、同時に HTML 内の他のリソースの URL(画像、CSS、JS など)に基づいて再度 HTTP リクエストを発起し、これらのリソースの内容を取得し、ウェブページが完全に読み込まれるまで続ける。
- ブラウザはサーバーとの通信が不要な場合、TCP 接続を積極的に閉じるか、サーバーの閉鎖リクエストを待つことができる。
HTTP_インタビュー#
HTTP はハイパーテキスト転送プロトコル、すなわちHyperText Transfer Protocol です。
プロトコルとは#
プロトコル(protocol)は、二つ以上の通信エンティティ間で交換されるメッセージの形式と順序、メッセージの送信および / または受信時に取るアクションを定義します。
それは、コンピュータが理解できる言語を使用して、コンピュータ間の通信の規範(二人以上の参加者)と、関連するさまざまな制御およびエラーハンドリングの方法(行動規約と規範)を確立します。
HTTP のステータスコード#
- 1xx:ヒント的な応答を示す
- 101 はプロトコルの切り替えを示し、WebSocket 接続で一般的です;
- 2xx:成功した応答を示す
- 「200 OK」は成功を示す
- 「204 No Content」は応答にボディデータがないことを示す
- 「206 Partial Content」は部分的な内容のみが送信されたことを示す;
- 3xx:リダイレクトの応答を示す
- 「301 Moved Permanently」は永久リダイレクトを示す
- 「302 Found」は一時的なリダイレクトを示す
- 303 はクライアントが指定されたパスでリクエストを再送信すべきことを示す
- 「304 Not Modified」はリソースが変更されていないことを示し、キャッシュにリダイレクト(キャッシュリダイレクト);
- 4xx:クライアントの問題によるエラー応答を示す
- 「400 Bad Request」はクライアントのリクエストメッセージにエラーがあることを示す
- 「403 Forbidden」はサーバーがリソースへのアクセスを禁止していることを示す
- 「404 Not Found」は指定されたパスが存在しないことを示す;
- 5xx:サーバーの問題によるエラー応答を示す:
- 「500 Internal Server Error」はサーバー内部の故障を示す
- 「501 Not Implemented」はクライアントのリクエスト機能がまだサポートされていないことを示す
- 「502 Bad Gateway」はサーバー自体は正常に動作しているが、バックエンドサーバーへのアクセスでエラーが発生したことを示す
- 「503 Service Unavailable」はサーバーが忙しく、一時的に応答できないことを示す。
HTTP の一般的なフィールド#
HTTP リクエストの形式は固定されており、HTTP ヘッダーと HTTP ボディの二部分で構成されています。最初の行は常にリクエストメソッド パス HTTPバージョン
であり、例えば、GET / HTTP/1.1
はGET
リクエストを使用し、パスは/
、バージョンはHTTP/1.1
を示します。
その後の各行は固定のHeader: Value
形式であり、これを HTTP ヘッダーと呼びます。サーバーは特定のヘッダーに依存してクライアントのリクエストを識別します。例えば:
- Host:リクエストされたドメイン名を示します。1 台のサーバー上に複数のウェブサイトが存在する可能性があるため、Host に依存してリクエストがどのウェブサイトに送信されたかを識別する必要があります;
- User-Agent:クライアント自身の識別情報を示します。異なるブラウザには異なる識別があり、サーバーは User-Agent に基づいてクライアントのタイプが IE か Chrome か、Firefox か Python のクローラーかを判断します;
- Accept:クライアントが処理できる HTTP 応答形式を示します。
*/*
は任意の形式を示し、text/*
は任意のテキストを示し、image/png
は PNG 形式の画像を示します; - Accept-Language:クライアントが受け入れる言語を示します。複数の言語が優先順位に従って並べられ、サーバーはこのフィールドに基づいてユーザーに特定の言語のウェブページバージョンを返します。
GET
リクエストの場合、この HTTP リクエストには HTTP ヘッダーのみが含まれ、HTTP ボディはありません。POST
リクエストの場合、この HTTP リクエストにはボディが含まれ、空行で区切られます。
POST
リクエストでは通常、Content-Typeを設定してボディのタイプを示し、Content-Lengthを設定してボディの長さを示します。これにより、サーバーはリクエストのヘッダーとボディに基づいて正しい応答を行うことができます。
HTTP 応答もヘッダーとボディの二部分で構成されています。応答の最初の行は常にHTTPバージョン 応答コード 応答説明
であり、例えば、HTTP/1.1 200 OK
はバージョンがHTTP/1.1
、応答コードが200
、応答説明がOK
であることを示します。クライアントは応答コードに依存して HTTP 応答が成功したかどうかを判断します。HTTP には固定の応答コードがあります。
HTTP プロトコルは、キャリッジリターンとラインフィードを HTTP ヘッダーの境界として設定し、Content-Length フィールドを HTTP ボディの境界として使用します。この二つの方法は「バッファリング」の問題を解決するためのものです。
その他のフィールド:
- Connection:クライアントがサーバーに「HTTP 持続接続」メカニズムを使用するよう要求するために最も一般的に使用されます。
- Content-Encoding:データの圧縮方法を示します。サーバーが返すデータがどの圧縮形式を使用しているかを示します。
GET と POST#
GET の意味はサーバーから指定されたリソースを取得することです。GET リクエストのパラメータは一般的に URL に記載され、URL は ASCII のみをサポートするため、GET リクエストのパラメータは ASCII 文字のみが許可され、ブラウザは URL の長さに制限を設けます(HTTP プロトコル自体は URL の長さに関して何の規定も設けていません)。
POST の意味はリクエストペイロード(メッセージボディ)に基づいて指定されたリソースを処理することです。POST リクエストはデータをメッセージボディに記載し、ボディ内のデータはクライアントとサーバーが合意すれば任意の形式のデータを使用できます。また、ブラウザはボディのサイズに制限を設けません。
- HTTP プロトコルにおいて、「安全」とはリクエストメソッドがサーバー上のリソースを「破壊」しないことを指します。
- 「冪等」とは、同じ操作を何度も実行しても結果が「同じ」であることを意味します。
したがって、GET メソッドは安全で冪等です。なぜなら、それは「読み取り専用」操作であり、キャッシュ可能です;POST メソッドは安全でなく冪等でもありません。なぜなら、それはサーバー上のリソースを変更し、大部分がキャッシュ不可能だからです。
HTTP キャッシュ#
強制キャッシュ:ブラウザがキャッシュが期限切れでないと判断した場合、ブラウザのローカルキャッシュを直接使用します。キャッシュを使用するかどうかの決定権はブラウザにあります。
Cache-Control
は相対的な時間です;Expires
は絶対的な時間です;
協議キャッシュ:サーバーと協議した後、協議結果に基づいてローカルキャッシュを使用するかどうかを判断します。HTTP 200 OK/ HTTP 304
- ユニークな識別子に基づいて実現:応答ヘッダー中の
Etag
(応答リソースのユニーク識別子)とリクエストヘッダー中のIf-None-Match
; - 時間に基づいて実現:応答ヘッダー中の
Last-Modified
とリクエストヘッダー中のIf-Modified-Since
;
注意、協議キャッシュのこれら二つのフィールドは強制キャッシュの Cache-Control フィールドと組み合わせて使用する必要があります。強制キャッシュがヒットしなかった場合にのみ、協議キャッシュフィールドを持つリクエストを発起できます。
HTTP の特性(HTTP/1.1)#
HTTP の利点と欠点#
HTTP の利点は「シンプルで柔軟、拡張が容易、広く使用され、クロスプラットフォームである」ことです。
HTTP の欠点は「ステートレスで、平文での伝送」(平文伝送 + メッセージ完全性の検証ができない) -> 「安全でない」です。
HTTP の性能#
HTTP プロトコルはTCP/IPに基づいており、「リクエスト - 応答」の通信モードを使用しています:
- 長接続:いずれかの端が明示的に接続を切断しない限り、TCP 接続状態を保持し、TCP 接続の再確立と切断による余分なオーバーヘッドを減少させ、サーバー側の負荷を軽減します。
- パイプライン(pipeline)ネットワーク伝送:同じ TCP 接続で、クライアントがリクエストを送信した後、応答を受け取るのを待たずに次のリクエストを送信でき、全体の応答時間を短縮します。ただし、サーバーは受信したリクエストの順序に従ってこれらのパイプライン化されたリクエストに対する応答を送信する必要があります。
- ヘッダーのブロッキング:サーバーが A リクエストの処理に時間がかかると、後続のリクエストの処理がブロックされることを「ヘッダーのブロッキング」と呼びます。HTTP/1.1 のパイプラインはリクエストのヘッダーのブロッキングを解決しましたが、応答のヘッダーのブロッキングは解決していません。
HTTP/1.1 の性能は一般的であり、後続の HTTP/2 および HTTP/3 は HTTP の性能を最適化しています。
HTTP と HTTPS#
- 接続を確立する際、https は http よりも TLS のハンドシェイクプロセスが多い;
- コンテンツを転送する際、https はデータを暗号化し、通常は対称暗号化データを使用します;
HTTP と HTTPS の違い#
- セキュリティ
- 接続の確立
- デフォルトポート
- URL プレフィックス
- 証明書
HTTPS が解決する HTTP のセキュリティ問題#
HTTPSは HTTP と TCP 層の間にSSL/TLS
プロトコルを追加します。
-
盗聴リスク -> 情報暗号化 -> 混合暗号化
-
改ざんリスク -> チェックメカニズム -> ハッシュアルゴリズム
+ デジタル署名- ハッシュアルゴリズムを使用してメッセージの完全性を保証できます;
デジタル署名を使用してメッセージの出所の信頼性を保証できます(メッセージが秘密鍵を持つ側から送信されたことを確認できます);
-
なりすましリスク -> 身分証明書 -> サーバーの公開鍵をデジタル証明書に格納
CA はデジタル証明書に署名し、その証明書が信頼できることを保証します。(証明書の信頼チェーンの問題)
本質:クライアントがサーバーを信頼する問題
HTTPS 接続の確立#
SSL/TLS プロトコルの基本的な流れ:
- クライアントはサーバーの公開鍵を要求し、検証します。
- 双方は「セッションキー」を生成するために協議します。
- 双方は「セッションキー」を使用して暗号化通信を行います。
最初の二つのステップが SSL/TLS の確立プロセスであり、TLS ハンドシェイク段階に関与する四回の通信(SSL/TLS 1.2)です。
異なる鍵交換アルゴリズムを使用すると、TLS ハンドシェイクプロセスも異なります。現在一般的に使用される鍵交換アルゴリズムには二つがあります:RSA アルゴリズムと ECDHE アルゴリズム。
-
ClientHello
、クライアントがサーバーに暗号化通信リクエストを発起クライアントランダム数(Client Random) ...
-
ServerHello
、サーバーがクライアントのリクエストを受け取った後、クライアントに応答を発信サーバーランダム数(Server Random) + サーバーのデジタル証明書 ...
-
クライアントが応答
公開鍵で暗号化されたランダム数プレマスターキー + クライアントハンドシェイク終了通知 ...
-
サーバーの最終応答
サーバーハンドシェイク終了通知 + ハンドシェイクサマリー
これで、TLS のハンドシェイク段階が終了し、クライアントとサーバーは暗号化通信に入り、完全に通常の HTTP プロトコルを使用するだけで、ただ「セッションキー」で内容を暗号化します。
HTTPS がデータの完全性を保証する#
TLS は実装上、ハンドシェイクプロトコルとレコードプロトコルの二層に分かれています:
- TLS ハンドシェイクプロトコルは TLS の四回のハンドシェイクプロセスであり、暗号化アルゴリズムの協議と対称鍵の生成を担当します;
- TLS レコードプロトコルはアプリケーションデータを保護し、その完全性と出所を検証する役割を担い、レコードプロトコルを使用して HTTP データを暗号化します;
TLS レコードプロトコルは主にメッセージ(HTTP データ)の圧縮、暗号化およびデータの認証を担当します:
- メッセージを複数の短いセグメントに分割し、それぞれのセグメントを圧縮します
- 圧縮されたセグメントにメッセージ認証コード(MAC、ハッシュアルゴリズムによって得られる)を付加します。これはデータの完全性を保証し、データの認証を行うためです。
- 対称鍵を使用して圧縮されたメッセージセグメント + メッセージ認証コードを暗号化します
- 暗号化されたデータにデータタイプ、バージョン番号、圧縮された長さから構成されるヘッダーが加わると、最終的なメッセージデータになります。
レコードプロトコルが完了した後、最終的なメッセージデータはトランスポートコントロールプロトコル(TCP)層に渡されて転送されます。
HTTP の進化#
HTTP/1.1 と HTTP/1.0 の違い#
- 長接続
- パイプライン(pipeline)ネットワーク伝送をサポートし、応答を待たずに次のリクエストを発信できる
HTTP/2.0 と HTTP/1.1 の違い#
- HTTP/2.0 は HTTPS に基づいており、安全性が高い
- ヘッダー圧縮、HPACK アルゴリズム
- バイナリ形式
- 同時伝送、ストリーム、複数のリクエストが 1 つの TCP 接続を再利用
- サーバープッシュ
HTTP/2.0 は依然としてヘッダーのブロッキング問題が存在し、TCP 層で発生します。TCP データが連続している場合にのみ、アプリケーション層はカーネルからデータを読み取ることができます。一度パケットが失われると、すべての HTTP リクエストがブロックされます。
HTTP/3#
HTTP/3 は下層で UDP プロトコルを使用してヘッダーのブロッキング問題を解決します。
UDP に基づく QUIC プロトコルは、TCP の信頼性のある伝送を実現できます。QUIC プロトコルには以下の特徴があります:
- ヘッダーのブロッキングなし:特定のストリームでパケットが失われた場合、そのストリームのみがブロックされ、他のストリームには影響を与えません。複数のストリーム間には依存関係がなく、独立しています。
- より迅速な接続確立:QUIC は内部に TLS を含んでおり、1 回の RTT で「同時に」接続の確立と鍵の協議を完了できます。
- 接続の移行:QUIC プロトコルは接続を「バインド」するために四元組の方法を使用せず、接続 IDを使用して通信の二つのエンドポイントをマークします。
- セキュリティ:HTTP/2.0 では、TLS が全 HTTP セッションを暗号化および認証するために使用され、すべての HTTP ヘッダーとデータペイロードを含みます。TLS の作業は TCP 層の上にあり、TCP 接続内で転送されるアプリケーション層のデータを暗号化しますが、TCP ヘッダーや TLS レコード層のヘッダーは暗号化されません。したがって、通信中に TCP ヘッダーが攻撃者によって改ざんされる可能性があります。HTTP/3.0 の QUIC は、データパケット全体(ヘッダーとボディを含む)を暗号化および認証処理し、セキュリティを確保します。
したがって、QUIC は UDP の上にある擬似TCP + TLS + HTTP/2 のマルチプレクシングプロトコルです。
TCP_インタビュー#
TCP ヘッダー形式#
TCP ヘッダーはオプションを使用しない場合、20 バイトを占めます:
- ソースポート番号(16 ビット) + ターゲットポート番号(16 ビット)
- シーケンス番号(32 ビット):順序の乱れ問題を解決
- 確認応答番号(32 ビット):パケットロス問題を解決
- ヘッダー長(4 ビット) + 予約(6 ビット) + 制御ビット(6 ビット) + ウィンドウサイズ(16 ビット)
- チェックサム(16 ビット) + 緊急ポインタ(16 ビット)
TCP の存在意義#
ネットワーク層の IP プロトコルは信頼性のある配信を保証しません。ネットワークデータパケットの信頼性を保証する必要がある場合、上層(トランスポート層)の TCP プロトコルに責任を持たせる必要があります。
TCP プロトコルはトランスポート層で動作する信頼性のあるデータ転送サービスであり、受信したネットワークデータパケットが損傷なく、間隔なく、冗長なく、順序通りであることを保証します。
TCP とは#
TCP は接続指向の、信頼性のある、バイトストリームベースのトランスポート層通信プロトコルです。
TCP 接続とは#
接続:信頼性とフロー制御を維持するためのいくつかの状態情報の組み合わせであり、ソケット、シーケンス番号、ウィンドウサイズが含まれます。
TCP 接続を確立するには、クライアントとサーバーが以下の情報に関して合意する必要があります:
- ソケット:TCP 四元組
- シーケンス番号:順序の乱れ問題を解決するために使用
- ウィンドウサイズ:フロー制御に使用
TCP と UDP の違い#
UDP ヘッダーは固定で 8 バイトです:
- ソースポート番号(16 ビット) + 目的ポート番号(16 ビット)
- パケット長(16 ビット) + チェックサム(16 ビット)
UDP は IP が提供する非接続型の通信サービスを使用します。
TCP と UDP の違いは以下の点にあります(論理を把握して記憶):
- 接続:TCP は接続指向、UDP は非接続指向
- サービス対象:TCP はエンドツーエンドの二点サービス、UDP は一対多
- 信頼性:TCP はデータの信頼性ある配信を保証し、UDP は最大限の努力で配信し、信頼性のある配信を保証しない
- TCP は輻輳制御とフロー制御メカニズムを提供し、データ転送の安全性を保証しますが、UDP はそれを提供しません
- ヘッダーオーバーヘッド:TCP はオプションを使用しない場合、ヘッダーは 20 バイト、UDP は固定で 8 バイトです
- 転送方式:TCP はバイトストリームベースのストリーミング転送、UDP はパケット単位で送信され、境界があります
- 分割:TCP データサイズが MSS を超える場合、トランスポート層で分割され、UDP はネットワーク層 IP プロトコルの分割(MTU を超える)を使用します
TCP の適用シーン:
- FTP ファイル転送
- HTTP/HTTPS
UDP の適用シーン:
- マルチメディア通信
- ブロードキャスト通信
- パケット総量が小さい通信:DNS、SNMP など
TCP 接続の確立#
TCP 接続は三回のハンドシェイクを通じて確立されます。
なぜ三回のハンドシェイクなのか、二回や四回ではないのか?#
-
過去の接続の初期化を防ぐ
「古い SYN メッセージ」は過去の接続と呼ばれ、TCP が三回のハンドシェイクを使用して接続を確立する最も重要な理由は「過去の接続」の初期化を防ぐためです。
-
双方の初期シーケンス番号を同期する
クライアントが「初期シーケンス番号」を持つ
SYN
メッセージを送信する際、サーバーはクライアントの SYN メッセージが正常に受信されたことを示すACK
応答メッセージを返す必要があります。サーバーがクライアントに「初期シーケンス番号」を送信する際も、クライアントの応答を受け取る必要があります。こうして往復することで、双方の初期シーケンス番号が確実に同期されます。 -
リソースの無駄を避ける
「二回のハンドシェイク」だけの場合、クライアントが送信した
SYN
メッセージがネットワークでブロックされ、何度もSYN
メッセージを再送信する場合、サーバーはリクエストを受け取った後に複数の冗長な無効接続を確立し、不必要なリソースの無駄を引き起こします。
なぜ TCP 接続を確立する際に初期化のシーケンス番号が異なる必要があるのか?#
- 同じ四元組の接続によって過去のメッセージが誤って受信されるのを防ぐ(主な側面)
- ハッカーが同じシーケンス番号の TCP メッセージを偽造するのを防ぐ
初期シーケンス番号 ISN のランダム生成アルゴリズム:ISN = M + F (localhost, localport, remotehost, remoteport)。
M
はタイマーで、このタイマーは 4 マイクロ秒ごとに 1 加算されます。F
はハッシュアルゴリズムで、ソース IP、目的 IP、ソースポート、目的ポートに基づいてランダムな数値を生成します。ハッシュアルゴリズムが外部から容易に推測されないことを保証するために、MD5 アルゴリズムを使用するのが良い選択です。
ランダム数は時計タイマーに基づいて増加し、基本的に同じ初期シーケンス番号がランダムに生成されることはありません。
SYN 攻撃について#
攻撃者が短時間で異なる IP アドレスのSYN
メッセージを偽造したと仮定します。サーバーは受信するたびにSYN_RCVD
状態に入りますが、サーバーが送信するACK + SYN
メッセージは未知の IP ホストからのACK
応答を受け取ることができません。次第にサーバーの半接続キューが満杯になり、サーバーは正常なユーザーにサービスを提供できなくなります。
SYN 攻撃の最も直接的な影響は、TCP 半接続キューが満杯になることです。これにより、TCP 半接続キューが満杯になると、以降に受信した SYN メッセージは破棄され、クライアントはサーバーと接続を確立できなくなります。
SYN 攻撃を回避する方法は以下の四つです:
- netdev_max_backlog を増やす;
- TCP 半接続キューを増やす;
- tcp_syncookies を有効にする;
- SYN+ACK の再送信回数を減らす
TCP 接続の切断#
TCP 接続の切断は四回のハンドシェイクを通じて行われ、各方向に1 つの FIN と 1 つの ACKが必要です。
TIME_WAIT 状態について#
TIME_WAIT 状態が必要な主な理由は二つです:
-
過去の接続のデータが、後に同じ四元組の接続によって誤って受信されるのを防ぐ;
TIME_WAIT 状態は
2MSL
の期間持続し、この時間は両方向のデータパケットがすべて破棄されるのに十分であり、元の接続のデータパケットがネットワーク内で自然に消失し、再出現するデータパケットはすべて新しい接続によって生成されることを保証します。(MSL
は Maximum Segment Lifetime、メッセージの最大生存時間。) -
「受動的に接続を閉じる」側が正しく閉じられることを保証する;
TIME_WAIT の役割は最後の ACK が受動的に閉じる側に届くのを待つために十分な時間を待つことです。これにより、正常に閉じるのを助けます。
クライアントが TIME_WAIT 状態を持たず、最後の ACK メッセージを送信した後に直接 CLOSE 状態に入った場合、その ACK メッセージが失われ、サーバーは再送信の FIN メッセージを送信します。この時、クライアントはすでに閉じた状態になっており、サーバーからの再送信の FIN メッセージを受け取ると RST メッセージを返します。
このような状況を防ぐために、クライアントは十分な時間を待ち、サーバーが ACK を受け取ることを確認する必要があります。サーバーが ACK を受け取らなかった場合、TCP 再送信メカニズムがトリガーされ、サーバーは再度 FIN を送信します。このように往復することで、ちょうど二つの MSL の時間がかかります。
クライアントがサーバーからの再送信の FIN メッセージを受け取ると、TIME_WAIT 状態の待機時間は 2MSL にリセットされます。
過剰な TIME_WAIT 状態の主な危害は二つあります:
- 第一はシステムリソースを占有することです。例えばファイルディスクリプタ、メモリリソース、CPU リソース、スレッドリソースなど;
- 第二はポートリソースを占有することです。ポートリソースも有限であり、一般的に開くことができるポートは
32768~61000
であり、net.ipv4.ip_local_port_range
パラメータを使用して範囲を指定できます。
TIME_WAIT は私たちの友人であり、私たちにとって有益です。この状態を避けようとするのではなく、理解するべきです。
サーバーが過剰な TIME_WAIT 状態の接続を避けるためには、決して接続を積極的に切断せず、クライアントに切断させ、各地に分散したクライアントに TIME_WAIT を負担させるべきです。
サーバーに大量の TIME_WAIT 状態の TCP 接続が存在する場合、それはサーバーが多くの TCP 接続を積極的に切断したことを示しています。以下のようなシーンがあります:
- 第一のシーン:HTTP が長接続(Keep-Alive)を使用していない
- 第二のシーン:HTTP 長接続がタイムアウトした
- 第三のシーン:HTTP 長接続のリクエスト数が上限に達した
TCP のキープアライブメカニズム#
一定の時間を定義し、その時間内に接続に関連する活動がない場合、TCP キープアライブメカニズムが作動し、一定の時間間隔で探査メッセージを送信します。この探査メッセージには非常に少ないデータが含まれ、連続して数回探査メッセージに応答がない場合、現在の TCP 接続は死んでいると見なされ、システムカーネルはエラー情報を上層アプリケーションに通知します。
TCP キープアライブのこのメカニズムは検出時間が長いため、アプリケーション層で独自のハートビートメカニズムを実装できます。
ソケットプログラミング#
TCP に対するソケットプログラミング:
- サーバーとクライアントが
socket
を初期化し、ファイルディスクリプタを取得; - サーバーが
bind
を呼び出し、指定された IP アドレスとポートにソケットをバインド; - サーバーが
listen
を呼び出し、リスニングを行う; - サーバーが
accept
を呼び出し、クライアント接続を待つ; - クライアントが
connect
を呼び出し、サーバーのアドレスとポートに接続リクエストを送信; - サーバーの
accept
がデータ転送用のソケットのファイルディスクリプタを返す; - クライアントが
write
を呼び出してデータを書き込み、サーバーがread
を呼び出してデータを読み取る; - クライアントが接続を切断する際、
close
を呼び出し、サーバーがread
でデータを読み取るとEOF
が読み取られ、データ処理が完了した後、サーバーがclose
を呼び出して接続を閉じる。
サーバーがaccept
を呼び出すと、接続が成功した場合、完了した接続のソケットが返され、以降はデータ転送に使用されます。リスニングソケットと実際にデータを転送するソケットは「二つ」のソケットであり、一つはリスニングソケット、もう一つは完了した接続ソケットです。
接続が成功した後、双方はread
とwrite
関数を使用してデータを読み書きし、ファイルストリームに書き込むように操作します。
IP_基本#
IP は「直接接続されていない」二つのネットワーク間で通信転送を担当します;
MAC の役割は「直接接続されている」二つのデバイス間の通信を実現することです;
IP アドレスの分類#
分類アドレス:A クラス、B クラス、C クラス、D クラス、E クラス。
無分類アドレス CIDR:32 ビットの IP アドレスは二つの部分に分けられ、前半はネットワーク番号、後半はホスト番号です。
無クラスドメイン間ルーティング(英語:Classless Inter-Domain Routing、略称CIDR)
サブネットマスク、マスクの意味はホスト番号を隠すことで、残りがネットワーク番号になります。サブネットマスクと IP アドレスをビット単位で AND 計算すると、ネットワーク番号が得られます。
サブネットマスクを使用してネットワーク番号とホスト番号を分割できますが、実際にはサブネットマスクにはサブネットを分割する役割もあります。
サブネット分割は実際にはホストアドレスを二つの部分に分けることです:サブネットネットワークアドレスとサブネットホストアドレス。
IP アドレスとルーティング制御#
IP アドレスのネットワークアドレス部分はルーティング制御に使用されます。
ルーティング制御テーブルには、ネットワークアドレスと次に送信すべきルーターのアドレスが記録されています。ホストとルーターの両方にそれぞれのルーター制御テーブルがあります。
IP パケットを送信する際、最初に IP パケットのヘッダー内のターゲットアドレスを確認し、その後ルーティング制御テーブルからそのアドレスと同じネットワークアドレスを持つレコードを見つけ、そのレコードに基づいて IP パケットを適切な次のルーターに転送します。ルーティング制御テーブルに同じネットワークアドレスのレコードが複数存在する場合、同じビット数が最も多いネットワークアドレス、つまり最長マッチを選択します。
ループバックアドレスは、同一コンピュータ上のプログラム間でネットワーク通信を行う際に使用されるデフォルトアドレスです。
コンピュータは特別な IP アドレス127.0.0.1 をループバックアドレスとして使用します。このアドレスと同じ意味を持つのはlocalhost
というホスト名です。この IP またはホスト名を使用する際、データパケットはネットワークに流れません。
IP の分割と再構成#
各種データリンクの最大転送単位MTU
は異なります。例えば、FDDI データリンクの MTU は 4352、イーサネットの MTU は 1500 バイトなどです。
各種データリンクの MTU が異なるのは、異なるタイプのデータリンクの使用目的が異なるためです。使用目的が異なれば、許容される MTU も異なります。
IP データパケットのサイズが MTU を超えると、IP データパケットは分割されます。
分割された IP データグラムは、再構成時にターゲットホストによってのみ行われ、ルーターは再構成を行いません。
分割転送中に、特定の分割が失われると、全体の IP データグラムが無効になるため、TCP はMSS
を導入しました。つまり、TCP 層で分割を行い、IP 層での分割は行いません。したがって、UDP ではできるだけMTU
を超えるデータグラムを送信しないようにします。
IPv6 の基本的な理解#
IPv4 アドレスの長さは 32 ビット(4 バイト)で、8 ビットごとにグループ化され、ドット区切りの 10 進数で表現されます。
IPv6 アドレスの長さは 128 ビット(16 バイト)で、16 ビットごとにグループ化され、各グループはコロン「:」で区切られます。
連続する 0 がある場合、これらの 0 を省略し、二つのコロン「::」で区切ることができます。ただし、1 つの IP アドレス内で二つの連続したコロンが現れることは許可されていません。
IPv6 は単に割り当て可能なアドレスが増えただけでなく、非常に多くの利点があります。
- IPv6 は自動構成が可能で、DHCP サーバーがなくても自動的に IP アドレスを割り当てることができ、プラグアンドプレイの便利さを実現します。
- IPv6 のパケットヘッダーの長さは固定値
40
バイトで、パケットヘッダーのチェックサムを省略し、ヘッダー構造を簡素化し、ルーターの負荷を軽減し、伝送性能を大幅に向上させます。 - IPv6 には偽造 IP アドレスに対するネットワークセキュリティ機能や、回線盗聴を防ぐ機能があり、セキュリティが大幅に向上します。
- ...
IPv6 は IPv4 に比べてヘッダーが改善されています:
- ヘッダーのチェックサムフィールドを削除しました。 データリンク層とトランスポート層でチェックが行われるため、IPv6 は IP のチェックを直接削除しました。
- 分割 / 再構成に関連するフィールドを削除しました。 分割と再構成は時間がかかるプロセスであり、IPv6 では中間ルーターでの分割と再構成を許可せず、この操作はソースとターゲットホストでのみ行われます。これにより、ルーターの転送速度が大幅に向上します。
- オプションフィールドを削除しました。 オプションフィールドはもはや標準 IP ヘッダーの一部ではありませんが、消失したわけではなく、IPv6 ヘッダー内の「次のヘッダー」で指摘された位置に現れる可能性があります。このオプションフィールドを削除することで、IPv6 のヘッダーは固定長の
40
バイトになります。
IP プロトコル関連技術#
DNS ドメイン名解決#
DNS はドメイン名の URL を自動的に具体的な IP アドレスに変換できます。
ドメイン名の階層関係は木構造に似ています:
- ルート DNS サーバー
- トップレベルドメイン DNS サーバー(com)
- 権威 DNS サーバー(server.com)
ブラウザはまず自分のキャッシュにあるかどうかを確認し、なければオペレーティングシステムのキャッシュを確認し、さらにhosts
ファイルを確認し、それでもなければ DNS サーバーに問い合わせます。問い合わせのプロセスは以下の通りです:
- クライアントは最初に DNS リクエストを発信し、www.server.comの IP は何かを尋ね、ローカル DNS サーバー(クライアントの TCP/IP 設定で指定された DNS サーバーアドレス)に送信します。
- ローカル DNS はクライアントのリクエストを受け取った後、キャッシュ内のテーブルでwww.server.comを見つけた場合、直接 IP アドレスを返します。見つからない場合、ローカル DNS はルート DNS サーバーに「おお、www.server.comの IP アドレスを教えてもらえますか?」と尋ねます。ルート DNS サーバーは最上位のもので、直接ドメイン名解決には使用されませんが、道筋を示すことができます。
- ルート DNS はローカル DNS からのリクエストを受け取ると、後置が.com であることを確認し、「www.server.comというドメインは.com エリアが管理している」と言い、.com トップレベルドメインサーバーのアドレスを教えますので、そちらに尋ねてみてください。
- ローカル DNS はトップレベルドメインサーバーのアドレスを受け取った後、「おお、www.server.comの IP アドレスを教えてもらえますか?」と尋ねます。
- トップレベルドメインサーバーは「www.server.comエリアの権威 DNS サーバーのアドレスを教えますので、そちらに尋ねてみてください」と言います。
- ローカル DNS は権威 DNS サーバーに「おお、www.server.comに対応する IP は何ですか?」と尋ねます。server.com の権威 DNS サーバーは、ドメイン名解決結果の元の出所です。なぜ権威と呼ばれるのか?それは私のドメイン名だからです。
- 権威 DNS サーバーは照会後、対応する IP アドレス X.X.X.X をローカル DNS に伝えます。
- ローカル DNS は IP アドレスをクライアントに返し、クライアントはターゲットと接続を確立します。
DNS ドメイン名解決のプロセスは、日常生活で人に道を尋ねるプロセスに似ています。道を指し示すだけで、案内はしません。
ARP アドレス解決プロトコル#
ARP はネットワーク層アドレスを解析してデータリンク層アドレスを探すネットワーク伝送プロトコルです。
ARP はARP リクエストと ARP レスポンスの二種類のパケットを使用して MAC アドレスを特定します。
- ホストはブロードキャストで ARP リクエストを送信し、このパケットには知りたい MAC アドレスのホスト IP アドレスが含まれています。
- 同じリンク内のすべてのデバイスが ARP リクエストを受信すると、ARP リクエストパケットの内容を確認し、ARP リクエストパケット内のターゲット IP アドレスが自分の IP アドレスと一致する場合、そのデバイスは自分の MAC アドレスをARP レスポンスパケットに詰めてホストに返します。
オペレーティングシステムは通常、最初に ARP を介して取得した MAC アドレスをキャッシュしておき、次回はキャッシュから対応する IP アドレスの MAC アドレスを直接見つけることができます。
ARP プロトコルは既知の IP アドレスから MAC アドレスを求めるものであり、RARP プロトコルはその逆で、既知の MAC アドレスから IP アドレスを求めます。
さらに、送信ホストと目的ホストが同じローカルエリアネットワークにない場合、相手の MAC アドレスを知っていても、直接通信することはできず、ルーターを介して IP 層で転送する必要があります。なぜなら、ルーターはこのローカルエリアネットワークをリンク層で隔離しているからです(ネットワーク層での明示的な転送を行わない限り、ルーターは一つのローカルエリアネットワーク内のイーサネットフレームを自動的に別のローカルエリアネットワークや外部ネットワークに転送することはありません。もし自動転送が可能であれば、どれほど恐ろしいことになるか想像できます。無効なブロードキャストフレームが洪水のようにネットワーク全体を浸水させ、ネットワークが麻痺することになります。これがルーターの基本的な機能の一つであり、ネットワークを隔離することです)。この場合、送信ホストはゲートウェイ IP アドレスを目的 IP アドレスとして使用します(これは IP 層で決定されます)。したがって、ARP プロトコルを介して得られるのは目的ホストの真の MAC アドレスではなく、ローカルエリアネットワークの外に通じるルーターの MAC アドレスになります。したがって、その後、送信ホストが目的ホストに送信するすべてのフレームは、そのルーターに送信され、外部に送信されます。この状況は委任 ARP または **ARP プロキシ(ARP Proxy)** と呼ばれます。
DHCP 動的ホスト設定プロトコル#
DHCP はネットワーク管理者が IP ネットワークアドレスを集中管理し、自動的に割り当てることを可能にする通信プロトコルです。
DHCP クライアントプロセスは 68 ポートをリスニングし、DHCP サーバープロセスは 67 ポートをリスニングします。
- クライアントは最初にDHCP 発見メッセージ(DHCP DISCOVER)の IP データグラムを発信します。クライアントは IP アドレスを持っておらず、DHCP サーバーのアドレスも知らないため、UDPブロードキャスト通信を使用し、ブロードキャストの宛先アドレスは 255.255.255.255(ポート 67)で、ソース IP アドレスは 0.0.0.0(ポート 68)です。DHCP クライアントはこの IP データグラムをリンク層に渡し、リンク層はそのフレームをネットワーク内のすべてのデバイスにブロードキャストします。
- DHCP サーバーは DHCP 発見メッセージを受信すると、**DHCP 提供メッセージ(DHCP OFFER)** を使用してクライアントに応答します。このメッセージも IP ブロードキャストアドレス 255.255.255.255 を使用し、メッセージ情報にはサーバーが提供するリース可能な IP アドレス、サブネットマスク、デフォルトゲートウェイ、DNS サーバー、IP アドレスのリース期間が含まれています。
- クライアントは一つまたは複数のサーバーから DHCP 提供メッセージを受信した後、一つのサーバーを選択し、選択したサーバーに **DHCP リクエストメッセージ(DHCP REQUEST)** を送信して応答し、設定されたパラメータをエコーします。
- 最後に、サーバーはDHCP ACK メッセージで DHCP リクエストメッセージに応答し、要求されたパラメータを確認します。
クライアントが DHCP ACK を受信すると、インタラクションは完了し、クライアントはリース期間内に DHCP サーバーが割り当てた IP アドレスを使用できます。
リースされた DHCP IP アドレスが期限切れに近づくと、クライアントはサーバーに DHCP リクエストメッセージを送信します:
- サーバーがリースを続けることに同意すれば、DHCP ACK メッセージで応答し、クライアントはリース期間を延長します。
- サーバーがリースを続けることに同意しなければ、DHCP NACK メッセージで応答し、クライアントはリースされた IP アドレスの使用を停止します。
DHCP インタラクションでは、全ての通信が UDP ブロードキャストで行われます。
DHCP 中継代理があれば、異なるサブネットの IP アドレスの割り当ても一つの DHCP サーバーで統一管理できます。
- DHCP クライアントは DHCP 中継代理に DHCP リクエストパケットを送信し、DHCP 中継代理はこのブロードキャストパケットを受信した後、ユニキャストの形式で DHCP サーバーに送信します。
- サーバーはそのパケットを受信した後、DHCP 中継代理に応答を返し、DHCP 中継代理はこのパケットを DHCP クライアントにブロードキャストします。
したがって、DHCP サーバーは同じリンク上にいなくても、IP アドレスの統一的な割り当てと管理を実現できます。
NAT ネットワークアドレス変換#
ネットワークアドレス変換(英語:Network Address Translation、略称:NAT)、または IP 動的擬装(英語:IP Masquerade)は、IP データパケットがルーターやファイアウォールを通過する際に、送信元または目的の IP アドレスやポートを再書き込みする技術です。この技術は、複数のホストが一つの公有 IP アドレスを使用してインターネットにアクセスするプライベートネットワークで広く使用されています。
簡単に言えば、NAT は同じ会社、家庭、教室内のホストが外部と通信する際に、プライベート IP アドレスを公有 IP アドレスに変換します。
IP アドレス + ポート番号の組み合わせを変換することもできます。これにより、1 つのグローバル IP アドレスで済むようになります。この変換技術をネットワークアドレスとポート変換 NAPTと呼びます。
NAPT ルーターの変換テーブルは、アドレスとポートの組み合わせを正しく変換できます。
NAT/NAPT は独自の変換テーブルに依存しているため、以下の問題が発生します:
- 外部から NAT 内部のサーバーに対して、NAT 変換テーブルに変換記録がないため、積極的に接続を確立することができません。
- 変換テーブルの生成と変換操作は性能オーバーヘッドを引き起こします。
- 通信中に NAT ルーターが再起動すると、すべての TCP 接続がリセットされます。
解決策は主に二つあります。
-
第一の方法は IPv6 に切り替えることです。
-
NAT トラバーサル技術
NAT トラバーサル技術では、NAT デバイスの後ろにあるアプリケーションが能動的な立場にあり、NAT デバイスが外部に出すデータパケットを変更することを明確に知っているため、NAT デバイスの操作に協力し、マッピングを自ら確立します。これにより、以前のように NAT デバイスがマッピングを確立する必要がなくなります。
クライアントは NAT デバイスから公有 IP アドレスを取得し、自らポートマッピングエントリを確立し、このエントリを使用して外部と通信します。これにより、NAT デバイスが変換を行う必要がなくなります。
ICMP#
ICMP の正式名称はInternet Control Message Protocol、すなわちインターネット制御メッセージプロトコルです。
ICMP
の主な機能には、IP パケットがターゲットアドレスに成功裏に届いたかどうかを確認し、送信中に IP パケットが廃棄された理由を報告し、ネットワーク設定を改善することが含まれます。
ICMP は大きく二つのカテゴリに分けられます:
- 一つは診断用のクエリメッセージ、つまり「クエリメッセージタイプ」
- もう一つはエラーの原因を通知するエラーメッセージ、つまり「エラーメッセージタイプ」
IGMP#
IGMP はインターネットグループ管理プロトコルで、ホスト(マルチキャストメンバー)と最後のルーター間で動作します。
- IGMP メッセージはルーターにマルチキャストグループへの参加と退出を申請します。デフォルトでは、ルーターは接続されたホストにマルチキャストパケットを転送しません。ホストが IGMP を介してマルチキャストグループに参加する場合、ルーターは IGMP ルーターテーブルに記録します。ルーターはその後、マルチキャストパケットを対応するホストに転送します。
- IGMP メッセージは IP でカプセル化され、IP ヘッダーのプロトコル番号は 2 であり、TTL フィールドの値は通常 1 です。なぜなら、IGMP はホストと接続されたルーター間で動作するからです。
マルチキャストアドレスは機械の IP アドレスに使用されず、マルチキャストアドレスにはネットワーク番号とホスト番号がないため、DHCP とは関係ありません。マルチキャストアドレスは一般的に UDP プロトコルに使用され、機械が UDP マルチキャストデータを送信する際、ターゲットアドレスにはマルチキャストアドレスが指定され、マルチキャストグループ内の機械はすべてデータパケットを受信します。
マルチキャストグループに参加するか離れるかは、ソケットのインターフェースを介して実現され、ホスト IP は変更されません。
その他#
- OSPF(Open Shortest Path First、オープン最短経路優先):内部ゲートウェイプロトコル(Interior Gateway Protocol、IGP)の一種で、広く使用されている動的ルーティングプロトコルであり、リンク状態アルゴリズムに基づいており、リンクの帯域幅、遅延などの要素を考慮して最適な経路を選択します。
- RIP(Routing Information Protocol、ルーティング情報プロトコル):内部ゲートウェイプロトコル(Interior Gateway Protocol、IGP)の一種で、距離ベクトルアルゴリズムに基づく動的ルーティングプロトコルであり、固定のホップ数をメトリックとして使用し、ホップ数が最も少ない経路を最適な経路として選択します。
- BGP(Border Gateway Protocol、境界ゲートウェイプロトコル):ルーティング選択ドメイン間でネットワーク層の到達可能性情報(Network Layer Reachability Information、NLRI)を交換するためのルーティング選択プロトコルであり、高度な柔軟性と拡張性を持っています。