インターネット上の通信では、IPアドレスだけではどのアプリケーションに対してデータを届ければよいか判断できません。1台のコンピュータで複数のアプリケーションが同時に通信を行う場合、それぞれの通信を正しく区別する仕組みが必要です。

この課題を解決するのがポート番号とソケット通信です。ポート番号はアプリケーションを識別するための16ビットの数値であり、ソケットはアプリケーションがネットワーク通信を行うためのエンドポイント(通信の終点)を表します。

本記事では、ポート番号とソケット通信について以下の内容を解説します。

  • ポート番号の役割と3つの種類(ウェルノウンポート・登録済みポート・動的ポート)
  • ソケット通信の仕組みとソケットアドレスの概念
  • 5タプルによるコネクションの識別方法
  • netstat/ssコマンドでの接続状態確認の実践
  • ポート番号に関するセキュリティ上の注意点

この記事を読むことで、ポート番号とソケット通信の仕組みを理解し、コマンドで接続状態を確認できるようになります。

前提条件

本記事を理解するために、以下の知識があることを前提としています。

  • TCPとUDPの違いを把握している(TCPとUDPの違いを理解するを参照)
  • IPアドレスの基本概念を理解している
  • コマンドラインの基本操作ができる

実行環境

本記事で使用するコマンドは以下の環境で動作確認を行っています。

項目 環境
OS Windows 10/11、macOS 14+、Ubuntu 22.04/24.04
必要なツール netstat、ss(Linux)、PowerShell(Windows)
権限 一部のコマンドで管理者権限が必要

特別なソフトウェアのインストールは不要で、OSに標準搭載されているツールのみを使用します。

期待される学習成果

本記事を読み終えると、以下のことができるようになります。

  1. ポート番号の役割と3つの範囲(0-1023、1024-49151、49152-65535)を説明できる
  2. ソケット通信の仕組みとソケットアドレスを理解できる
  3. 5タプルによるコネクション識別の仕組みを説明できる
  4. netstat/ssコマンドで現在の接続状態を確認できる
  5. ポート番号に関するセキュリティ上の考慮点を理解できる

ポート番号とは

ポート番号は、コンピュータ上で動作する特定のアプリケーションやサービスを識別するための16ビットの数値です。IPアドレスがネットワーク上のコンピュータ(ホスト)を識別するのに対し、ポート番号はそのホスト上のアプリケーションを識別します。

以下の図は、IPアドレスとポート番号の関係を示しています。

flowchart LR
    subgraph "クライアント 192.168.1.10"
        C1[Webブラウザ<br/>:52341]
        C2[メールクライアント<br/>:52342]
    end
    
    subgraph "サーバー 203.0.113.50"
        S1[Webサーバー<br/>:80]
        S2[メールサーバー<br/>:25]
        S3[SSHサーバー<br/>:22]
    end
    
    C1 -->|HTTP| S1
    C2 -->|SMTP| S2

この例では、同じサーバー(203.0.113.50)上で複数のサービスが異なるポート番号で待ち受けています。クライアントは宛先ポート番号を指定することで、目的のサービスと通信できます。

ポート番号の表記方法

ポート番号はIPアドレスと組み合わせて、以下の形式で表記されます。

プロトコル 表記例 説明
IPv4 192.168.1.1:80 IPアドレスとポートをコロンで区切る
IPv6 [2001:db8::1]:80 IPv6アドレスを角括弧で囲む
URL http://example.com:8080 スキーム後にホスト名とポートを指定

ポート番号の3つの範囲

ポート番号は0から65535までの範囲を取りますが、IANA(Internet Assigned Numbers Authority)によって以下の3つの範囲に分類されています。

flowchart TB
    subgraph "ポート番号の範囲"
        W["ウェルノウンポート<br/>0 - 1023<br/>システム予約"]
        R["登録済みポート<br/>1024 - 49151<br/>アプリケーション登録"]
        D["動的/プライベートポート<br/>49152 - 65535<br/>一時的な使用"]
    end
    
    W --> R --> D

ウェルノウンポート(Well-Known Ports): 0-1023

ウェルノウンポートは、広く利用されている標準的なサービスに割り当てられたポート番号です。OSによっては、これらのポートを使用するために管理者権限(root権限)が必要です。

以下は代表的なウェルノウンポートの一覧です。

ポート番号 プロトコル サービス 説明
20 TCP FTP(データ) ファイル転送のデータ通信用
21 TCP FTP(制御) ファイル転送の制御用
22 TCP SSH セキュアなリモートログイン
23 TCP Telnet 非暗号化リモートログイン(非推奨)
25 TCP SMTP メール送信
53 TCP/UDP DNS 名前解決
67/68 UDP DHCP IPアドレス自動割り当て
80 TCP HTTP Webサービス
110 TCP POP3 メール受信
143 TCP IMAP メール受信(サーバー保存)
443 TCP HTTPS 暗号化Webサービス
993 TCP IMAPS 暗号化IMAP
995 TCP POP3S 暗号化POP3

登録済みポート(Registered Ports): 1024-49151

登録済みポートは、特定のアプリケーションやサービスがIANAに登録して使用するポート番号です。一般ユーザー権限でも使用できます。

ポート番号 プロトコル サービス 説明
1433 TCP Microsoft SQL Server データベース
1521 TCP Oracle Database データベース
3000 TCP 開発サーバー Node.js開発でよく使用
3306 TCP MySQL/MariaDB データベース
3389 TCP RDP リモートデスクトップ
5432 TCP PostgreSQL データベース
5672 TCP AMQP メッセージキュー(RabbitMQ)
6379 TCP Redis インメモリデータストア
8080 TCP HTTP代替 開発用Webサーバー
8443 TCP HTTPS代替 開発用HTTPSサーバー
9200 TCP Elasticsearch 検索エンジン
27017 TCP MongoDB ドキュメントデータベース

動的ポート/プライベートポート(Dynamic/Private Ports): 49152-65535

動的ポートは、クライアントが一時的な通信を行う際に自動的に割り当てられるポート番号です。エフェメラルポート(Ephemeral Ports)とも呼ばれます。

クライアントがサーバーに接続する際、OSは利用可能な動的ポートの中から1つを自動的に割り当てます。この割り当ては通信ごとに行われ、通信が終了すると解放されます。

sequenceDiagram
    participant C as クライアント<br/>192.168.1.10
    participant S as Webサーバー<br/>203.0.113.50:80
    
    Note over C: 動的ポート52341を割り当て
    C->>S: SYN (192.168.1.10:52341 → 203.0.113.50:80)
    S->>C: SYN+ACK
    C->>S: ACK
    Note over C,S: HTTP通信
    C->>S: FIN
    S->>C: FIN+ACK
    Note over C: ポート52341を解放

OSによって動的ポートの範囲は異なる場合があります。

OS 動的ポート範囲 確認方法
Linux 32768-60999 cat /proc/sys/net/ipv4/ip_local_port_range
Windows 49152-65535 netsh int ipv4 show dynamicport tcp
macOS 49152-65535 sysctl net.inet.ip.portrange

ソケット通信の仕組み

ソケット(Socket)は、アプリケーションがネットワーク通信を行うためのAPIであり、通信の終点(エンドポイント)を抽象化した概念です。ソケットを使用することで、アプリケーションは低レベルのネットワークプロトコルの詳細を意識せずに通信できます。

ソケットの概念

ソケットは「通信の出入口」として機能し、以下の情報を持ちます。

  • プロトコルファミリ: IPv4(AF_INET)またはIPv6(AF_INET6)
  • ソケットタイプ: ストリーム型(SOCK_STREAM、TCP用)またはデータグラム型(SOCK_DGRAM、UDP用)
  • ローカルアドレス: 自身のIPアドレスとポート番号
  • リモートアドレス: 通信相手のIPアドレスとポート番号(接続後)
flowchart TB
    subgraph "アプリケーション層"
        APP[アプリケーション<br/>Webサーバー、クライアントなど]
    end
    
    subgraph "ソケットAPI"
        SOCK[ソケット<br/>通信の抽象化層]
        direction TB
        CREATE[socket&#40;&#41;]
        BIND[bind&#40;&#41;]
        LISTEN[listen&#40;&#41;]
        ACCEPT[accept&#40;&#41;]
        CONNECT[connect&#40;&#41;]
        SEND[send&#40;&#41;/recv&#40;&#41;]
        CLOSE[close&#40;&#41;]
    end
    
    subgraph "トランスポート層"
        TCP[TCP/UDP]
    end
    
    subgraph "ネットワーク層"
        IP[IP]
    end
    
    APP --> SOCK
    SOCK --> TCP --> IP

ソケットアドレス

ソケットアドレスは、IPアドレスとポート番号の組み合わせで表現されます。この組み合わせにより、ネットワーク上の特定のアプリケーションを一意に識別できます。

用語 説明
ソケットアドレス IPアドレス + ポート番号 192.168.1.10:52341
ローカルソケット 自身のソケットアドレス 送信元アドレス
リモートソケット 通信相手のソケットアドレス 宛先アドレス

TCPソケット通信の流れ

TCPソケット通信では、サーバーとクライアントで異なる手順を踏みます。

sequenceDiagram
    participant S as サーバー
    participant C as クライアント
    
    Note over S: socket() - ソケット作成
    Note over S: bind() - アドレス紐付け
    Note over S: listen() - 接続待ち開始
    
    Note over C: socket() - ソケット作成
    
    C->>S: connect() - 接続要求
    Note over S: accept() - 接続受け入れ
    
    Note over S,C: コネクション確立
    
    C->>S: send() - データ送信
    S->>C: recv() - データ受信
    S->>C: send() - レスポンス送信
    C->>S: recv() - レスポンス受信
    
    Note over C: close() - 接続終了
    Note over S: close() - 接続終了

サーバー側の処理

  1. socket(): ソケットを作成する
  2. bind(): ソケットにローカルアドレス(IPアドレスとポート番号)を紐付ける
  3. listen(): 接続待ち状態にする(バックログキューのサイズを指定)
  4. accept(): クライアントからの接続を受け入れ、通信用の新しいソケットを返す
  5. send()/recv(): データを送受信する
  6. close(): ソケットを閉じる

クライアント側の処理

  1. socket(): ソケットを作成する
  2. connect(): サーバーに接続を要求する(ローカルポートは自動割り当て)
  3. send()/recv(): データを送受信する
  4. close(): ソケットを閉じる

UDPソケット通信の流れ

UDPはコネクションレス型のため、TCPよりもシンプルな手順となります。

sequenceDiagram
    participant S as サーバー
    participant C as クライアント
    
    Note over S: socket() - ソケット作成
    Note over S: bind() - アドレス紐付け
    
    Note over C: socket() - ソケット作成
    
    C->>S: sendto() - データ送信
    Note over S: recvfrom() - データ受信
    S->>C: sendto() - レスポンス送信
    Note over C: recvfrom() - レスポンス受信
    
    Note over S,C: コネクション不要で送受信

UDPではconnect()やaccept()を使用せず、sendto()とrecvfrom()で宛先を指定してデータを送受信します。

5タプルによるコネクション識別

TCPコネクションは、5タプル(5-tuple)と呼ばれる5つの要素の組み合わせで一意に識別されます。

要素 説明
1. プロトコル TCP または UDP TCP
2. 送信元IPアドレス クライアントのIP 192.168.1.10
3. 送信元ポート番号 クライアントのポート 52341
4. 宛先IPアドレス サーバーのIP 203.0.113.50
5. 宛先ポート番号 サーバーのポート 80

この5タプルにより、同じクライアントから同じサーバーへの複数の接続を区別できます。

flowchart LR
    subgraph "クライアント 192.168.1.10"
        C1["ブラウザタブ1<br/>:52341"]
        C2["ブラウザタブ2<br/>:52342"]
        C3["ブラウザタブ3<br/>:52343"]
    end
    
    subgraph "サーバー 203.0.113.50"
        S["Webサーバー<br/>:80"]
    end
    
    C1 -->|"TCP (192.168.1.10:52341, 203.0.113.50:80)"| S
    C2 -->|"TCP (192.168.1.10:52342, 203.0.113.50:80)"| S
    C3 -->|"TCP (192.168.1.10:52343, 203.0.113.50:80)"| S

上の例では、3つのブラウザタブが同じWebサーバーに接続していますが、送信元ポート番号が異なるため、それぞれ別のコネクションとして識別されます。

サーバー側でのコネクション識別

1台のWebサーバーが複数のクライアントからの接続を処理する場合も、5タプルによって各コネクションを区別します。

flowchart RL
    subgraph "クライアントA<br/>192.168.1.10"
        CA[":52341"]
    end
    
    subgraph "クライアントB<br/>192.168.1.20"
        CB[":52341"]
    end
    
    subgraph "Webサーバー<br/>203.0.113.50:80"
        S["待受ソケット<br/>0.0.0.0:80"]
        S1["接続ソケット1<br/>クライアントA用"]
        S2["接続ソケット2<br/>クライアントB用"]
    end
    
    CA -->|"(192.168.1.10:52341, 203.0.113.50:80)"| S1
    CB -->|"(192.168.1.20:52341, 203.0.113.50:80)"| S2

クライアントAとクライアントBが同じポート番号(52341)を使用していても、送信元IPアドレスが異なるため、別のコネクションとして識別できます。

netstat/ssコマンドによる接続状態の確認

ネットワークの接続状態を確認するためのコマンドとして、netstat(Network Statistics)とss(Socket Statistics)があります。これらのコマンドを使用して、現在のポート使用状況やコネクションの状態を把握できます。

Linuxでの確認方法(ssコマンド)

ssコマンドは、Linuxでnetstatの後継として推奨されているツールです。netstatより高速に動作し、より詳細な情報を取得できます。

基本的な使用方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# TCP接続の一覧を表示
ss -t

# UDP接続の一覧を表示
ss -u

# リッスン状態のポートを表示
ss -l

# ポート番号を数値で表示(名前解決しない)
ss -n

# プロセス情報を表示(root権限が必要な場合あり)
ss -p

# よく使う組み合わせ:TCPのリッスンポートを数値で表示
ss -tlnp

出力例と読み方

1
2
3
4
5
$ ss -tlnp
State    Recv-Q  Send-Q   Local Address:Port    Peer Address:Port  Process
LISTEN   0       128      0.0.0.0:22            0.0.0.0:*          users:(("sshd",pid=1234,fd=3))
LISTEN   0       511      0.0.0.0:80            0.0.0.0:*          users:(("nginx",pid=5678,fd=6))
LISTEN   0       128      127.0.0.1:3306        0.0.0.0:*          users:(("mysqld",pid=9012,fd=22))
カラム 説明
State 接続状態(LISTEN、ESTABLISHEDなど)
Recv-Q 受信キューに溜まっているデータ量
Send-Q 送信キューに溜まっているデータ量
Local Address:Port ローカルのIPアドレスとポート番号
Peer Address:Port 接続先のIPアドレスとポート番号
Process プロセス名とPID

特定のポートや状態でフィルタリング

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 特定のポート番号でフィルタ
ss -tlnp sport = :80

# 特定の状態でフィルタ
ss -t state established

# ESTABLISHED状態の接続のみ表示
ss -tn state established

# 特定のIPアドレスへの接続をフィルタ
ss -tn dst 203.0.113.50

Windowsでの確認方法(netstatコマンド)

Windowsでは、netstatコマンドまたはPowerShellのGet-NetTCPConnectionコマンドレットを使用します。

netstatコマンド

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# すべての接続とリッスンポートを表示
netstat -a

# 数値で表示(名前解決しない)
netstat -n

# プロセスID(PID)を表示
netstat -o

# よく使う組み合わせ
netstat -ano

出力例

C:\> netstat -ano
Active Connections

  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       4
  TCP    192.168.1.10:52341     203.0.113.50:80        ESTABLISHED     12345
  TCP    192.168.1.10:52342     203.0.113.50:443       ESTABLISHED     12345

PowerShellでの確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# TCP接続の一覧を取得
Get-NetTCPConnection

# リッスン状態のポートのみ
Get-NetTCPConnection -State Listen

# 特定のポートでフィルタ
Get-NetTCPConnection -LocalPort 80

# プロセス名も含めて表示
Get-NetTCPConnection | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, @{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).ProcessName}}

macOSでの確認方法

macOSではnetstatまたはlsofコマンドを使用します。

1
2
3
4
5
6
7
8
# TCPのリッスンポートを表示
netstat -an -p tcp | grep LISTEN

# lsofでリッスンポートを表示
sudo lsof -iTCP -sTCP:LISTEN -n -P

# 特定のポートを使用しているプロセスを確認
sudo lsof -i :80

TCPコネクションの状態遷移

TCPコネクションは、確立から終了まで複数の状態を遷移します。netstatやssコマンドで表示されるState列は、この状態を示しています。

stateDiagram-v2
    [*] --> CLOSED
    CLOSED --> LISTEN: サーバーがlisten()
    CLOSED --> SYN_SENT: クライアントがconnect()
    
    LISTEN --> SYN_RECEIVED: SYNを受信
    SYN_SENT --> ESTABLISHED: SYN+ACKを受信
    SYN_RECEIVED --> ESTABLISHED: ACKを受信
    
    ESTABLISHED --> FIN_WAIT_1: close()でFIN送信
    ESTABLISHED --> CLOSE_WAIT: FINを受信
    
    FIN_WAIT_1 --> FIN_WAIT_2: ACKを受信
    FIN_WAIT_1 --> CLOSING: FINを受信
    FIN_WAIT_1 --> TIME_WAIT: FIN+ACKを受信
    
    FIN_WAIT_2 --> TIME_WAIT: FINを受信
    CLOSING --> TIME_WAIT: ACKを受信
    
    CLOSE_WAIT --> LAST_ACK: close()でFIN送信
    LAST_ACK --> CLOSED: ACKを受信
    
    TIME_WAIT --> CLOSED: 2MSL経過

主要な状態の説明

状態 説明
CLOSED 接続が存在しない初期状態
LISTEN サーバーが接続待ち状態
SYN_SENT クライアントがSYNを送信し、応答待ち
SYN_RECEIVED サーバーがSYNを受信し、SYN+ACKを送信済み
ESTABLISHED コネクションが確立し、データ通信可能
FIN_WAIT_1 アクティブクローズ側がFINを送信
FIN_WAIT_2 FINのACKを受信、相手のFIN待ち
CLOSE_WAIT パッシブクローズ側がFINを受信
LAST_ACK パッシブクローズ側がFINを送信、ACK待ち
TIME_WAIT アクティブクローズ側が最終ACKを送信後の待機状態
CLOSING 両側が同時にFINを送信した場合の状態

TIME_WAIT状態の重要性

TIME_WAIT状態は、コネクション終了後に一定時間(通常2MSL = 約60秒)維持されます。この状態が存在する理由は以下の通りです。

  1. 遅延パケットの処理: ネットワーク上に残っている古いパケットが新しいコネクションに影響しないようにする
  2. 最終ACKの再送: 最後のACKが失われた場合に、相手からのFIN再送に対応できるようにする

TIME_WAITが大量に発生している場合は、短時間に多くのコネクションを開閉していることを示し、サーバー設計の見直しが必要な場合があります。

ポート番号に関するセキュリティ上の考慮点

ポート番号の管理は、ネットワークセキュリティにおいて重要な要素です。

不要なポートの閉鎖

使用していないサービスのポートが開いていると、攻撃の入口となる可能性があります。

1
2
3
4
5
# 開いているポートを確認
ss -tlnp

# ファイアウォールで不要なポートをブロック(Linux iptables)
sudo iptables -A INPUT -p tcp --dport 23 -j DROP

ウェルノウンポートの保護

ウェルノウンポート(0-1023)の使用には管理者権限が必要なため、一般ユーザーが悪意のあるサービスを起動することを防げます。

ただし、アプリケーションを非特権ユーザーで実行する場合は、代替ポート(例:8080)を使用し、リバースプロキシやロードバランサーで80番ポートにマッピングする構成が推奨されます。

ポートスキャンへの対策

攻撃者はポートスキャンを使用して、開いているポートとサービスを特定しようとします。

1
2
3
4
5
# ファイアウォールでICMPを制限(ping応答を無効化)
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# 接続レート制限(同一IPからの接続を制限)
sudo iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 20 -j DROP

代表的なポートスキャン検出ツール

ツール名 説明
fail2ban 不正アクセスを検出してIPをブロック
portsentry ポートスキャンを検出してブロック
snort ネットワーク侵入検知システム

まとめ

本記事では、ポート番号とソケット通信の仕組みについて解説しました。

ポート番号のポイント

  • ポート番号は16ビット(0-65535)の数値で、アプリケーションを識別する
  • ウェルノウンポート(0-1023)は標準サービス用で管理者権限が必要
  • 登録済みポート(1024-49151)はアプリケーション用
  • 動的ポート(49152-65535)はクライアントの一時的な使用

ソケット通信のポイント

  • ソケットはネットワーク通信の抽象化層で、APIとして提供される
  • ソケットアドレスはIPアドレスとポート番号の組み合わせ
  • TCPコネクションは5タプル(プロトコル、送信元IP/ポート、宛先IP/ポート)で識別される
  • netstat/ssコマンドで現在の接続状態を確認できる

ポート番号とソケット通信の理解は、ネットワークプログラミングやトラブルシューティングにおいて不可欠です。次回は「ファイアウォールの仕組みと設定の基礎を理解する」で、ネットワークセキュリティの基礎について解説します。

参考リンク