Linuxネットワーク基礎
連載ナビ
この連載は「Linuxを使えるようになる」ではなく、「Linuxがどう動いているのか」を理解するための実践シリーズです。
今回は Linuxを理解する 〜 LFSで学ぶLinux内部構造 〜 の Part 6 / 第1回として、仕組みのつながりを意識しながら学びます。
- 前回: journalctlを理解する
- 次回: ipコマンド入門
—
ネットワークは「インターフェース・経路・ソケット」の3点で読める
Linuxのネットワークは奥が深そうに見えますが、状態把握に必要な視点は実は3つに絞れます。結論から言うと、
- インターフェース: このマシンはどのネットワークに、どのIPアドレスで参加しているか(
ip addrで確認) - 経路(ルーティングテーブル): 宛先ごとに、パケットをどこへ送り出すか(
ip routeで確認) - ソケット: どのプロセスが、どのポートで通信を待ち受け・実行しているか(
ssで確認)
の3点です。「つながらない」系のトラブルは、ほぼすべてこの3点のどこかに原因があります。逆に言えば、この3つのコマンドの出力が読めれば、疎通調査の最初の一手を迷わず打てるようになります。
アプリはネットワークに直接触れず、すべてカーネルが中継するから
なぜこの3点なのか。理由は、Linuxではアプリケーションがネットワークに直接触れることはなく、通信のすべてをカーネルのネットワークスタックが中継しているからです。
たとえば curl がHTTPリクエストを送るとき、内部では次のことが起きています。
1. curl はカーネルに socket() システムコールを発行し、通信の窓口(ソケット)を作る
2. connect() で宛先IPとポートを指定すると、カーネルがルーティングテーブルを引き、どのインターフェースから送るかを決める
3. カーネルがTCPのコネクション確立、パケットへの分割、IPヘッダの付与を行い、NIC(ネットワークカード)経由で送出する
つまりアプリが見ているのはソケットだけで、経路選択もパケット処理もカーネルの仕事です。だからこそ、調査するときは「アプリのログ」だけでなく、カーネルが持っている情報(インターフェース・経路・ソケットの状態)を直接見る必要があるのです。これはPart 1で見た「ユーザー空間とカーネル空間の分離」が、ネットワークにもそのまま当てはまっているということでもあります。
ip addr と ip route の出力を実際に読んでみる
自分のマシン(またはPart 1で作ったLinux VM)で実行してみましょう。まずインターフェースです。
ip addr
典型的な出力はこうなります(一部抜粋)。
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 ...
inet 127.0.0.1/8 scope host lo
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
inet 192.168.64.5/24 brd 192.168.64.255 scope global dynamic enp0s1
読み方のポイントは3つです。
loはループバックインターフェース。127.0.0.1(localhost)宛の通信は外に出ず、ここで折り返しますenp0s1などが実際のNICで、UP,LOWER_UPは「設定上有効かつリンクも確立している」という状態表示ですinet 192.168.64.5/24がIPアドレスとサブネット。/24は「先頭24ビットが同じ192.168.64.0〜255が同一ネットワーク」という意味です
次に経路です。
ip route
default via 192.168.64.1 dev enp0s1 proto dhcp
192.168.64.0/24 dev enp0s1 proto kernel scope link src 192.168.64.5
2行目は「同一ネットワーク宛は enp0s1 から直接送る」、1行目は「それ以外(default)はすべてゲートウェイ 192.168.64.1 に渡す」という意味です。インターネット宛の通信が成立するかどうかは、この default 行があるかにかかっています。
ss でソケットを見れば「誰が待ち受けているか」が分かる
3点目のソケットは ss コマンドで確認します。
sudo ss -ltnp
オプションは -l(LISTEN中のみ)、-t(TCP)、-n(ポートを数値表示)、-p(プロセス名表示)です。典型的な出力はこうです。
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=612,fd=3))
LISTEN 0 511 127.0.0.1:80 0.0.0.0:* users:(("nginx",pid=845,fd=6))
Local Address:Port の読み方が重要です。0.0.0.0:22 は「すべてのインターフェースの22番で待ち受け」、つまり外部からSSH接続できます。一方 127.0.0.1:80 は「ループバックの80番のみ」なので、同じマシンからしかアクセスできません。「サーバーは起動しているのに外から繋がらない」というトラブルの定番原因が、このbindアドレスの違いです。
疎通しないときの調査は、この3点を下から順に確認するのが定石です。
1. ip addr — そもそもIPアドレスが付いているか、インターフェースが UP か
2. ip route — 宛先への経路(特に default 行)があるか
3. ss -ltnp — 目的のプロセスが意図したアドレス・ポートで待ち受けているか
3つの視点を持てば、疎通調査は手順化できる
Linuxのネットワークは、カーネルがすべての通信を中継しており、その状態は「インターフェース(ip addr)・経路(ip route)・ソケット(ss)」の3点で観測できる——これが今回の結論です。
次回は、このうち ip コマンドをもう一歩掘り下げます。かつての標準だった ifconfig との関係と、ip addr / ip route / ip link の使い分けを整理していきます。
図解テキスト
app -> socket -> kernel net stack -> NIC -> network
(ss) (ip routeで経路決定) (ip addr / ip link)
疎通調査の順序:
1. ip addr … IPは付いているか / UPか
2. ip route … defaultルートはあるか
3. ss -ltnp … 誰がどのポートで待っているか
この回で実行するコマンド
上から順番に実行すれば、この回の内容を体験できます。
まずはそのままコピペして実行し、次に1行ずつ意味を確認してください。
ip addr
ip route
sudo ss -ltnp | head -n 40
ハンズオン手順
1. ターミナルを開いて、上のコマンドを1行ずつ実行する
2. ip addr の出力から、自分のIPアドレスとサブネット(/24 など)をメモする
3. ip route の default via の後ろにあるゲートウェイのIPをメモする
4. ss -ltnp の出力から、待ち受け中のプロセスを1つ選び、bindアドレスが 0.0.0.0 か 127.0.0.1 かを確認する
5. エラーが出たら、そのエラーメッセージをそのまま残す
チェックポイント
- コマンドが最後まで実行できた
- 自分のマシンの「IPアドレス・デフォルトゲートウェイ・LISTEN中のポート」を1つずつ言える
0.0.0.0:80と127.0.0.1:80の違いを説明できる- 次の回に進む前に、分からない単語を1つ調べた
今回理解できたこと
- アプリはソケット経由でカーネルに通信を依頼し、経路選択やパケット処理はカーネルが行う
- ネットワーク状態は「インターフェース・経路・ソケット」の3点で観測できる
- 疎通調査は
ip addr→ip route→ss -ltnpの順で手順化できる