it

TCPのSYNとは?3ウェイハンドシェイクでの役割も!(同期:コネクション確立:SYN ACK:フラグ:初期シーケンス番号など)

当サイトでは記事内に広告を含みます

TCPのSYNとは?3ウェイハンドシェイクでの役割も!(同期:コネクション確立:SYN ACK:フラグ:初期シーケンス番号など)

インターネットを通じてデータをやり取りするとき、その裏側ではTCP(Transmission Control Protocol)という通信プロトコルが重要な役割を担っています。TCPはデータを確実に届けるための仕組みを持っており、その出発点となるのが「SYN」と呼ばれる概念です。

SYNとは何か、なぜ通信の最初にSYNが必要なのか、そして3ウェイハンドシェイクの中でどのように機能するのか、疑問に感じたことはないでしょうか。本記事では、TCPのSYNの意味から始まり、フラグの種類、初期シーケンス番号、SYN ACKのやり取りまで、ネットワーク初心者の方にも分かりやすく解説していきます。

TCPのSYNとは「同期」を意味するコネクション確立の第一歩

それではまず、TCPのSYNについて解説していきます。

SYN(Synchronize)とは、日本語で「同期」を意味する言葉で、TCPにおける通信開始の合図として使われるフラグです。TCPはコネクション型プロトコルであり、データを送り始める前に必ず「コネクションを確立する」というステップを踏みます。その最初の一手がSYNフラグを立てたパケットの送信なのです。

SYNを送ることで、送信側は相手に対して「これから通信を始めたい」という意思表示をします。と同時に、通信を正しく管理するための初期シーケンス番号(ISN:Initial Sequence Number)を相手に伝えるという重要な役割も担っています。

TCPのSYNは単なる「挨拶」ではなく、通信の同期を取るための初期シーケンス番号を交換する仕組みです。この番号のやり取りがあるからこそ、TCPはデータの順序管理や再送制御を実現できます。

SYNフラグとはTCPヘッダのビットフィールド

TCPパケットのヘッダには、通信の状態を示すための「コントロールビット」と呼ばれるフラグ群が含まれています。SYNはその中の1ビットを占めており、このビットが「1」の場合に「SYNフラグが立っている」と表現します。

以下の表は、TCPヘッダに含まれる主なフラグをまとめたものです。

フラグ名 略称 意味・役割
Synchronize SYN コネクション確立要求・同期
Acknowledgment ACK 受信確認・応答
Finish FIN コネクション終了要求
Reset RST コネクション強制リセット
Push PSH データを即時上位層へ渡す
Urgent URG 緊急データの存在を示す

SYNフラグはコネクション確立の場面でのみ使われる特別なフラグであり、通常のデータ転送中には使用されません。

初期シーケンス番号(ISN)の役割

SYNパケットには、初期シーケンス番号(ISN)が含まれています。シーケンス番号とは、TCPがデータをバイト単位で管理するための番号であり、送受信したデータの「どこまで届いたか」を追跡するために使われます。

ISNはランダムに生成される32ビットの数値です。なぜランダムにするかというと、過去の通信セッションの残留パケットによる誤接続を防ぐためで、セキュリティ上の理由も兼ねています。

例えばクライアントのISNが「1000」であれば、その後送られるデータは「1001番目のバイトから」という形で管理されていきます。この仕組みによって、パケットが順序通りに届かなくても正しく並べ直せるのです。

SYNとTCPの信頼性の関係

TCPが「信頼性のある通信」を実現できる理由のひとつは、このSYNによるコネクション確立フェーズにあります。お互いの初期シーケンス番号を交換し合うことで、双方向の同期が取れた状態でデータのやり取りが始められます。

これに対してUDP(User Datagram Protocol)はコネクションレス型であり、SYNのようなコネクション確立手順を持ちません。速度は速い一方、信頼性はTCPより低くなります。

3ウェイハンドシェイクの仕組みとSYNの流れ

続いては、3ウェイハンドシェイクの具体的な流れを確認していきます。

3ウェイハンドシェイク(Three-Way Handshake)とは、TCPコネクションを確立するための3段階のやり取りです。クライアントとサーバが3回メッセージを交わすことでコネクションが完成し、はじめてデータの送受信が可能になります。

ステップ1:クライアントがSYNを送信する

まず最初に、クライアントがSYNフラグを立てたパケットをサーバへ送信します。このパケットには、クライアントが決定した初期シーケンス番号(例:ISN=100)が含まれています。

この段階でクライアントは「SYN-SENT」という状態に移行し、サーバからの返答を待ちます。サーバがこのSYNを受け取ると、「誰かが接続を要求してきた」と認識します。

ステップ2:サーバがSYN-ACKを返す

SYNを受け取ったサーバは、SYNフラグとACKフラグの両方を立てたパケット(SYN-ACK)を返送します。このパケットには次の2つの情報が含まれています。

情報 内容
ACK番号 クライアントのISN+1(受信確認)
サーバのISN サーバ独自の初期シーケンス番号(例:300)

ACK番号に「ISN+1」を入れることで、「あなたのSYNは確かに受け取りました」という確認を意味します。このステップでサーバは「SYN-RECEIVED」という状態になります。

ステップ3:クライアントがACKを返してコネクション確立

最後に、クライアントがサーバのSYN-ACKに対してACKパケットを送り返します。このACKにはサーバのISN+1の値が入っており、「サーバのSYNも受け取りました」という意味になります。

この3回目のやり取りが完了した時点で、クライアントとサーバの双方がコネクション確立(ESTABLISHED)状態になります。以降はデータの送受信が可能です。

3ウェイハンドシェイクのまとめ: ① クライアント → サーバ:SYN(ISN=100) ② サーバ → クライアント:SYN-ACK(ACK=101, ISN=300) ③ クライアント → サーバ:ACK(ACK=301) この3ステップでコネクションが確立されます。

Pythonで学ぶSYNパケットの実装例

続いては、実際のコードを通じてSYNの仕組みを確認していきます。

PythonのScapyライブラリを使うと、TCPパケットを自分で作成・送信することができます。以下の例では、SYNパケットを構築する方法を示します。ネットワークの動作を学ぶうえで、コードレベルで理解することは非常に有効です。

ScapyでSYNパケットを作成する

ScapyはPythonの強力なパケット操作ライブラリです。以下はSYNパケットを生成するサンプルコードです。

 from scapy.all import IP, TCP, send
送信先IPアドレスとポートを設定(ここでは架空の例)
target_ip = "192.168.1.100"
target_port = 80

SYNパケットを構築する
flags="S" がSYNフラグを意味する
syn_packet = IP(dst=target_ip) / TCP(dport=target_port, flags="S", seq=1000)

パケットの内容を表示
syn_packet.show()

実際に送信する場合(環境に注意)
send(syn_packet)
出力結果:
###[ IP ]###
dst = 192.168.1.100
###[ TCP ]###
dport = http
flags = S
seq = 1000

このコードで注目すべきはflags=”S”という部分です。ScapyではSYNフラグを”S”という文字で表現します。SYN-ACKであれば”SA”、ACKのみなら”A”となります。

3ウェイハンドシェイクのシミュレーション

次に、3ウェイハンドシェイクの流れをシミュレートするコード例を示します。実際の通信ではなく、パケットのシーケンス番号とACK番号の変化を確認するための学習用コードです。

 # 3ウェイハンドシェイクのシーケンス番号の変化をシミュレート
ステップ1:クライアントがSYNを送信
client_isn = 500  # クライアントの初期シーケンス番号(ISN)
print("ステップ1: クライアント → サーバ")
print(f"  SYNパケット送信: seq={client_isn}, flags=SYN")

ステップ2:サーバがSYN-ACKを返す
server_isn = 900  # サーバの初期シーケンス番号
server_ack = client_isn + 1  # クライアントのISN+1
print("ステップ2: サーバ → クライアント")
print(f"  SYN-ACKパケット送信: seq={server_isn}, ack={server_ack}, flags=SYN-ACK")

ステップ3:クライアントがACKを返す
client_ack = server_isn + 1  # サーバのISN+1
print("ステップ3: クライアント → サーバ")
print(f"  ACKパケット送信: ack={client_ack}, flags=ACK")

print("コネクション確立完了(ESTABLISHED)")

出力結果:
ステップ1: クライアント → サーバ
SYNパケット送信: seq=500, flags=SYN
ステップ2: サーバ → クライアント
SYN-ACKパケット送信: seq=900, ack=501, flags=SYN-ACK
ステップ3: クライアント → サーバ
ACKパケット送信: ack=901, flags=ACK
コネクション確立完了(ESTABLISHED)

出力結果を見ると、シーケンス番号とACK番号がステップごとに連動して変化していることが分かります。この連動こそがTCPの同期(SYN)の本質です。

SYNフラッド攻撃との関係

SYNの仕組みを理解すると、セキュリティの観点からも重要な知識が得られます。SYNフラッド攻撃(SYN Flood Attack)とは、大量のSYNパケットをサーバに送りつけ、サーバを半開き状態(SYN-RECEIVED)に追い込むDoS攻撃の一種です。

サーバは3ウェイハンドシェイクの第2ステップを終えた後、クライアントからのACKを待ちます。攻撃者はACKを送らずにSYNだけを大量に送ることで、サーバのリソースを枯渇させます。対策としては、SYN Cookieというテクニックがよく用いられます。

SYNに関連するTCPの状態遷移と重要な関連概念

続いては、SYNを軸にしたTCPの状態遷移と関連する重要な概念を確認していきます。

TCPの通信はステートフルであり、コネクションは複数の「状態」を経て確立・終了します。SYNはその状態遷移の起点となる存在です。

TCPの状態遷移図(コネクション確立フェーズ)

以下の表は、3ウェイハンドシェイク中のクライアントとサーバの状態遷移をまとめたものです。

フェーズ クライアントの状態 サーバの状態 送受信されるパケット
接続前 CLOSED LISTEN なし
ステップ1 SYN-SENT LISTEN SYN
ステップ2 SYN-SENT SYN-RECEIVED SYN-ACK
ステップ3 ESTABLISHED ESTABLISHED ACK

サーバはコネクションを受け付けるために、あらかじめ「LISTEN」状態で待機しています。クライアントからSYNが届いて初めて状態が変化していきます。

SYNとACKの組み合わせによる制御

SYNとACKはそれぞれ独立したフラグですが、SYN-ACKのように組み合わせて使うことでより複雑な制御が可能になります。コネクション確立時には必ずSYN-ACKが登場しますが、コネクション確立後はACKのみが頻繁に使われます。

また、SYNパケットにはデータペイロードを含めることができません。これはコネクション確立の純粋性を保つためで、データのやり取りはあくまでESTABLISHED状態になってから始まります。

MSS(最大セグメントサイズ)とSYNの関係

MSS(Maximum Segment Size)とは、TCPセグメントのデータ部分の最大サイズを指します。このMSSは、3ウェイハンドシェイクのSYNパケットやSYN-ACKパケットの中で「TCPオプション」として通知されます。

つまりSYNパケットは初期シーケンス番号を伝えるだけでなく、MSSなどの通信パラメータを相手に知らせる役割も持っています。通信効率を最大化するためにも、このパラメータ交換は欠かせません。

SYNパケットで交換される主な情報 ・初期シーケンス番号(ISN) ・MSS(最大セグメントサイズ) ・ウィンドウサイズ ・タイムスタンプオプション これらの情報がコネクション確立時に決まることで、効率的なデータ転送が可能になります。

まとめ

本記事では、TCPのSYNとは何かというテーマを中心に、3ウェイハンドシェイクの仕組み、SYN ACKのやり取り、初期シーケンス番号(ISN)の役割、フラグの種類、そしてPythonによるコード例まで幅広く解説しました。

SYNは単なる通信開始の合図ではなく、双方のシーケンス番号を同期させることでTCPの信頼性を支える重要な仕組みです。3ウェイハンドシェイクはその象徴的な手続きであり、ネットワークエンジニアやWeb開発者にとっても基礎中の基礎といえる知識でしょう。

SYNフラッドのようなセキュリティの話題とも直結しているため、ネットワークセキュリティを学ぶ入り口としても非常に価値のあるトピックです。TCPのコネクション確立の流れを理解することで、トラブルシューティングやパケットキャプチャの読み解きにも自信が持てるようになるはずです。