# Linuxで動かしながら学ぶTCP/IPネットワーク入門
# Info
- 書名: Linuxで動かしながら学ぶTCP/IPネットワーク入門
- 著者:
- 読んだ時期: 2021.08
# Motivation
ネットワークの基礎を学ぶため。
# Contents
# 2. TCP/IPとは
- TCP/IPはプロトコルの総称
- 通信の階層構造
- アプリケーション層
- トランスポート層
- インターネット層
- リンク層
- IPによって運ばれる本体はPacket、送り状のような情報が含まれているのがHeader
ip addr showで自分のコンピュータのIPアドレスを確認できるtcpdumpとpingでエコーの送受信確認traceroute- いくつかのルータを経由している。この論理的な距離のことをホップ数という。
ip route show: ルーティングテーブル- ルーティング
- 他のノードからパケットを受け取る
- 受け取ったパケットのヘッダにある送信先のIPアドレスを取得
- ルーティングテーブルからそのIPアドレスに一致する宛先を検索
- 一致した宛先に対応するネクストホップを取得
- 取得したネクストホップにパケットを渡す
# 3. Network Namespace
- システムからNetwork的に独立しているかのように扱える環境。
sudo ip netns add NAMEで作成できる- 実験環境的に使える
- name space の作成
- virtual ethernetインタフェースを作成(この時点ではまだシステム上にある)
- vethインタフェースをNetwork Namespaceに所属させる
- 所属させたインターフェスをUPにする
- IPアドレスを各インタフェースに付与
- ルーティング
- 同じセグメントに属するIPアドレス同士はルータがなくても通信可能
- IPアドレスを32bitとすると、前半24bitがネットワーク部、後半8bitがホスト部で、ネットワーク部が同じIPアドレス同士は同一のセグメントに属する。IPアドレスの末尾の"/24"がこの境界を示す。あるいはbitマスク(サブネットマスク)とのANDを取ることで取り出す。
# 4. イーサネット
- Frame: Dataを送る単位
- MAC(Media Access Control address)
- イーサネットのフレームを送受信するネットワーク機器ごとにユニークなID(実際にはブロードキャストドメインでUniqueならOK)
- 送信先のIPアドレスを所有しているイーサネットのMACアドレスが何故分かるのか
- ARP(Address Resolution Protocol)を使用しているため
- ARP request: ex) Request who-has 192.0.2.2 tell 192.0.2.1
- IPv6ではまた別の仕組みが使われる。これはv4の話。
- ブロードキャストドメインの範囲: ネットワークのセグメントと同じ
- あるブロードキャストドメインに複数のネットワーク機器をつなげる->Bridge
- portとMACアドレスの対応関係はMACアドレステーブルに記録されている
bridge fdb show br br0 | grep -i 00:00:5eなど
# 5. トランスポート層のプロトコル
通信するアプリケーションを区別する
- UDP
- UDPはコネクションレス型で、送ったら送りっぱなしのプロトコル。経路上でパケットが破棄されても関知しない。
- Ethernet Header > IP Header > UDP Header + Data
- UDP Headerの中に、source port, destination portがある
- アプリケーションが”入って待っている”ポート番号をどう決めるか
- 送信元がサーバーの場合
- from: アプリケーションが通信しようとしているプロトコルによって決まる
- to: 送信元の(エフェメラル)ポート番号をそのまま送信先に使う。
- 送信元がクライアントの場合
- from: OSが自動で選ぶ(Ephemeral Port)
- to: アプリケーションに対応したポートへ。
- 送信元がサーバーの場合
- TCP
- TCPはコネクション型で、破棄されて相手に届かなかった場合は同じデータを再送する(再送制御)
- 通信を始めるときに3つのセグメントをやり取りする(Three way handshake)
- Control Bit: 特にSYNとACKがThree Way Handshakeでやり取りされる
- SYN: Synchronize Sequence Numbers
- お互いのシーケンス番号を同期
- ACK: Acknowledge Field Significant
- データがちゃんと届いたらこのフラグが立ったセグメントを送る
- PSH: PuSH Function
- TCPを処理するプロトコルスタックでデータがバッファにずっとあるままだと、アプリケーション側からするとずっとデータがやってこないように見えて不都合。PSHを使うことでバッファにあるデータを今すぐに処理してほしいことを示す。
- SYN: Synchronize Sequence Numbers
- tcpdumpで表示されるシーケンス番号は実際の値ではなく、相対的な値に変換されている。初期値を他者から予測されにくいようにすることでセクションを乗っ取る攻撃に対処している
# 6. アプリケーション層のプロトコル
- HTTP
- ncコマンドを使って実施した一連の動作を文字列として表現したのがフォーマットURL
- curlでも同じことができる
- DNS
- ドメイン名をIPアドレスにする。DNSでこれをすることを名前解決という。
- DHCP
- Dynamic Host Configuration Protocol (初見)
- TCP/IPを使うのに必要な設定を自動化
# 7. NAT (Network Address Translation)
- Global addressは32bitの空間なので限りが出てきた。多数のプライベートアドレスで少数のグローバルアドレスを共有できるようにする仕組みがこれ。
- LinuxでNATを設定するには
iptablesを使う - Destination NAT: Portを空けるに対応するやつ。インターネットを起点とした通信を実現。
# 8. Socket Programming
Pythonの標準ライブラリsocketでソケットプログラミングの概要をやる Pythonによらず大体のAPIで共通している
client側
- socket()
- socketを作成。通信の種類等をマクロで指定(Enum型?)
- connect()
- 通信したいサーバーとポートを指定して接続を開く
- send() / recv()
- バイト列を送受信する
- close()
- 接続を閉じる
- socket()
server側
- socket()
- socketを作成。通信の種類等をマクロで指定(Enum型?)
- bind()
- 接続を待ち受けるIPアドレスとポート番号を指定する
- listen()
- 接続の待ち受けを開始する
- accept()
- 接続してきたクライアントを処理する
- send() / recv()
- バイト列を送受信する
- close()
- 接続を閉じる
- socket()
ssコマンドでソケットの状態を確認できるbinaryベースのプロトコルではバイトオーダーが問題になる。TCP/IPではビッグエンディアンに統一。ホストバイトオーダーとネットワークバイトオーダーが異なる場合は変換が必要になる。Pythonだと
struct.unpack, struct.packが使える。まとめと感想 TCP/IPが何なのかが分かった。ハンズオンで何度も仮想のネットワーク環境をセットアップしたので、最小限の構成が身にしみて理解できた。 ソケットプログラミングは非常に大事だと思うので、より進んだことを勉強したい。自作していきたい。