| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

「TCP/IP」の版間の差分

提供: MyMemoWiki
ナビゲーションに移動 検索に移動
 
(同じ利用者による、間の72版が非表示)
1行目: 1行目:
 +
| [[Multipass]] | [[Ubuntu]] |
 
==TCP/IP==
 
==TCP/IP==
 
{{amazon|B085BG8CH5}}
 
{{amazon|B085BG8CH5}}
 +
 +
===ipコマンド===
 +
----
 +
====[https://atmarkit.itmedia.co.jp/ait/articles/1709/22/news019.html 基礎1]====
 +
*https://atmarkit.itmedia.co.jp/ait/articles/1709/22/news019.html から引用
 +
 +
<table  class="wikitable" ><tr><td>オブジェクト</td><td>別名(省略形)</td><td>意味</td></tr><tr><td>link</td><td>l</td><td>ネットワークデバイス</td></tr><tr><td>addr</td><td>a、address</td><td>ネットワークデバイスのIPアドレス</td></tr><tr><td>addrlabel</td><td>addrl</td><td>アドレスラベル</td></tr><tr><td>route</td><td>r</td><td>ルーティングテーブルのエントリー</td></tr><tr><td>rule</td><td>rul</td><td>ルーティングポリシーデータベースに登録されているルール</td></tr><tr><td>neigh</td><td>n、neighbour</td><td>近傍キャッシュエントリ(ARPまたはNDISCキャッシュエントリ)</td></tr><tr><td>ntable</td><td>nt、ntb</td><td>近傍キャッシュの管理テーブル</td></tr><tr><td>tunnel</td><td>t</td><td>IPトンネル</td></tr><tr><td>tuntap</td><td>tu</td><td>トンネルデバイス</td></tr><tr><td>maddr</td><td>m、ma、mad</td><td>マルチキャストアドレス</td></tr><tr><td>mroute</td><td>mr</td><td>マルチキャストルーティングのキャッシュエントリ</td></tr><tr><td>mrule</td><td>mru</td><td>マルチキャストルーティングポリシーデータベースに登録されているルール</td></tr><tr><td>monitor</td><td>mon</td><td>ネットリンクメッセージの監視</td></tr><tr><td>xfrm</td><td>x、xf</td><td>IPsecポリシー</td></tr><tr><td>netns</td><td>net</td><td>ネットワーク名前空間</td></tr><tr><td>l2tp</td><td>l2</td><td>L2TPv3(レイヤー2トンネリングプロトコル)</td></tr><tr><td>tcp_metrics</td><td>tcp_m、tcp_metrics、tcpm</td><td>TCPメトリック</td></tr><tr><td>token</td><td>tok</td><td>トークン</td></table>
 +
 +
====[https://atmarkit.itmedia.co.jp/ait/articles/1709/28/news029.html 基礎2]====
 +
====[https://atmarkit.itmedia.co.jp/ait/articles/1709/29/news019.html 基礎3]====
 +
====[https://atmarkit.itmedia.co.jp/ait/articles/1710/05/news012.html 応用]====
  
 
===ip address show===
 
===ip address show===
365行目: 377行目:
 
*ルーティング情報交換プロトコル:BGP(Border Gateway Protocol)やOSPF(Open Shortest Path First)
 
*ルーティング情報交換プロトコル:BGP(Border Gateway Protocol)やOSPF(Open Shortest Path First)
 
==イーサネット==
 
==イーサネット==
 +
*OSI参照モデルでは、データリンク層と物理層に対応、IPの下の階層
 +
*OSI参照モデルや、TCP/IPの階層構造を下から番号を振って呼ぶことがある例えば、IPなら下から3番目のためレイヤー3、イーサネットは一般的にレイヤー2と見做される
 +
*イーサネットはIPを含む上位プロトコルのデータを運ぶ
 +
*イーサネットではデータを運ぶ1単位をフレーム(Frame)という
 +
*フレームの送信元、送信先の管理に使われるのが、MACアドレスとなり、イーサネットのフレームを受信する機器ごとに付与される
 +
*MACアドレスは、48ビット空間(上位24ビットは製造ベンダー、下位24ビットはベンダーが一意になるよう割り振る)を持った整数値で、原則的には全世界で一意
 +
*MACアドレスの一意性は厳しくなく、仮想マシンのハイパーバイザーが動的に割り振ると、重複の可能性があるが、ブロードキャストドメインの中で重複しなければ問題ない
 +
===Network Namespaceの作成===
 +
<pre>
 +
$ sudo ip netns add ns1
 +
$ sudo ip netns add ns2
 +
</pre>
 +
*vethインターフェースの作成
 +
<pre>
 +
$ sudo ip link add ns1-veth0 type veth peer name ns2-veth0
 +
</pre>
 +
*インターフェースを所属させ、up
 +
<pre>
 +
$ sudo ip link set ns1-veth0 netns ns1
 +
$ sudo ip link set ns2-veth0 netns ns2
 +
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
 +
$ sudo ip netns exec ns2 ip link set ns2-veth0 up
 +
</pre>
 +
*IPアドレスの設定
 +
<pre>
 +
$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
 +
$ sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0
 +
</pre>
 +
*MACアドレスの設定
 +
<pre>
 +
$ sudo ip netns exec ns1 ip link set dev ns1-veth0 address 00:00:5E:00:53:01
 +
$ sudo ip netns exec ns2 ip link set dev ns2-veth0 address 00:00:5E:00:53:02
 +
</pre>
 +
*確認
 +
<pre>
 +
$ sudo ip netns exec ns1 ip link show | grep "link/ether"
 +
    link/ether 00:00:5e:00:53:01 brd ff:ff:ff:ff:ff:ff link-netns ns2
 +
$ sudo ip netns exec ns2 ip link show | grep "link/ether"
 +
    link/ether 00:00:5e:00:53:02 brd ff:ff:ff:ff:ff:ff link-netns ns1
 +
</pre>
 +
*別ターミナルから、パケットキャプチャ準備
 +
<pre>
 +
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on ns1-veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
 +
</pre>
 +
*ns1 から ns2 へping
 +
<pre>
 +
$ sudo ip netns exec ns1 ping -c 3 192.0.2.2
 +
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
 +
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.461 ms
 +
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.196 ms
 +
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.187 ms
 +
 +
--- 192.0.2.2 ping statistics ---
 +
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
 +
rtt min/avg/max/mdev = 0.187/0.281/0.461/0.127 ms
 +
</pre>
 +
*ダンプの内容を確認
 +
<pre>
 +
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on ns1-veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37038, seq 1, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37038, seq 1, length 64
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37038, seq 2, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37038, seq 2, length 64
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37038, seq 3, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37038, seq 3, length 64
 +
</pre>
 +
 +
*どうやって、MACアドレスを知るのか?一旦、MACアドレスのキャッシュをクリア
 +
<pre>
 +
$ sudo ip netns exec ns1 ip neigh flush all
 +
</pre>
 +
*icmp だけでなく、arpもダンプ対象に加える
 +
<pre>
 +
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp or arp
 +
</pre>
 +
*再度ping
 +
<pre>
 +
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp or arp
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on ns1-veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
 +
00:00:5e:00:53:01 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.0.2.2 tell 192.0.2.1, length 28
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype ARP (0x0806), length 42: Reply 192.0.2.2 is-at 00:00:5e:00:53:02, length 28
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37051, seq 1, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37051, seq 1, length 64
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37051, seq 2, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37051, seq 2, length 64
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37051, seq 3, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37051, seq 3, length 64
 +
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype ARP (0x0806), length 42: Request who-has 192.0.2.1 tell 192.0.2.2, length 28
 +
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype ARP (0x0806), length 42: Reply 192.0.2.1 is-at 00:00:5e:00:53:01, length 28
 +
</pre>
 +
==ブリッジ==
 +
*スイッチングハブを利用すると複数のネットワーク機器を同じブロードキャストドメインに接続できる
 +
*スイッチングハブを一般化した用語がブリッジ
 +
*ブリッジはデータリンク層でフレームを転送する
 +
*ブリッジは自身のどのポートにどのMACアドレスの機器が接続されているかMACアドレステーブルを用いて管理する
 +
*[[Linux]]にはブリッジの実装として、ネットワークブリッジという機能がある
 +
 +
*Network Namespaceを作成
 +
<pre>
 +
$ sudo ip netns add ns1
 +
$ sudo ip netns add ns2
 +
$ sudo ip netns add ns3
 +
$ sudo ip netns add bridge
 +
</pre>
 +
*veth作成
 +
<pre>
 +
$ sudo ip link add ns1-veth0 type veth peer name ns1-br0
 +
$ sudo ip link add ns2-veth0 type veth peer name ns2-br0
 +
$ sudo ip link add ns3-veth0 type veth peer name ns3-br0
 +
</pre>
 +
*所属させる
 +
<pre>
 +
$ sudo ip link set ns1-veth0 netns ns1
 +
$ sudo ip link set ns2-veth0 netns ns2
 +
$ sudo ip link set ns3-veth0 netns ns3
 +
$ sudo ip link set ns1-br0 netns bridge
 +
$ sudo ip link set ns2-br0 netns bridge
 +
$ sudo ip link set ns3-br0 netns bridge
 +
</pre>
 +
*up
 +
<pre>
 +
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
 +
$ sudo ip netns exec ns2 ip link set ns2-veth0 up
 +
$ sudo ip netns exec ns3 ip link set ns3-veth0 up
 +
$ sudo ip netns exec bridge ip link set ns1-br0 up
 +
$ sudo ip netns exec bridge ip link set ns3-br0 up
 +
$ sudo ip netns exec bridge ip link set ns3-br0 up
 +
</pre>
 +
*Ip
 +
<pre>
 +
$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
 +
$ sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0
 +
$ sudo ip netns exec ns3 ip address add 192.0.2.3/24 dev ns3-veth0
 +
</pre>
 +
*bridge
 +
<pre>
 +
$ sudo ip netns exec bridge ip link add dev br0 type bridge
 +
$ sudo ip netns exec bridge ip link set br0 up
 +
</pre>
 +
*ブリッジに接続
 +
<pre>
 +
$ sudo ip netns exec bridge ip link set ns1-br0 master br0
 +
$ sudo ip netns exec bridge ip link set ns2-br0 master br0
 +
$ sudo ip netns exec bridge ip link set ns3-br0 master br0
 +
</pre>
 +
*ping : ns1 -> ns2
 +
<pre>
 +
$ sudo ip netns exec ns1 ping -c 3 192.0.2.2
 +
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
 +
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.496 ms
 +
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.139 ms
 +
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.141 ms
 +
 +
--- 192.0.2.2 ping statistics ---
 +
3 packets transmitted, 3 received, 0% packet loss, time 2034ms
 +
rtt min/avg/max/mdev = 0.139/0.258/0.496/0.167 ms
 +
</pre>
 +
*ping : ns1 -> ns3
 +
*ネットワークブリッジを介して3つのNetwork Namespaceが同じセグメントにつながった
 +
<pre>
 +
$ sudo ip netns exec ns1 ping -c 3 192.0.2.3
 +
PING 192.0.2.3 (192.0.2.3) 56(84) bytes of data.
 +
64 bytes from 192.0.2.3: icmp_seq=1 ttl=64 time=0.262 ms
 +
64 bytes from 192.0.2.3: icmp_seq=2 ttl=64 time=0.138 ms
 +
64 bytes from 192.0.2.3: icmp_seq=3 ttl=64 time=0.138 ms
 +
 +
--- 192.0.2.3 ping statistics ---
 +
3 packets transmitted, 3 received, 0% packet loss, time 2035ms
 +
rtt min/avg/max/mdev = 0.138/0.179/0.262/0.058 ms
 +
</pre>
 +
===ブリッジの削除===
 +
<pre>
 +
# ip link set br100 down
 +
# brctl delbr br100
 +
</pre>
 +
 +
==トランスポート層プロトコル==
 +
===ポート===
 +
*OSが自動で割り当てるポートをエフェメラルポートという
 +
*0~1023(システムポート、またはウェルノウンポート)
 +
*1024~49151(ユーザポート、またはレジスタードポート)
 +
*49152~65535(ダイナミックポート、またはプライベートポート)
 +
===UDP===
 +
====nc(netcat)コマンド====
 +
----
 +
*ループバックアドレスを使って、UDPの54321番ポートで、ncコマンドが通信を待ち受け
 +
<pre>
 +
$ nc -ulnv 127.0.0.1 54321
 +
Bound on 127.0.0.1 54321
 +
</pre>
 +
*クライアントから接続してメッセージ
 +
<pre>
 +
$ nc -u 127.0.0.1 54321
 +
Hello World!
 +
</pre>
 +
 +
*サーバーで確認
 +
*54928 は、エフェメラルポート
 +
<pre>
 +
$ nc -ulnv 127.0.0.1 54321
 +
Bound on 127.0.0.1 54321
 +
Connection received on 127.0.0.1 54928
 +
Hello World!
 +
</pre>
 +
 +
*別ターミナルから、tcpdumpでやり取りを確認
 +
*パケットのペイロードはUDPダイアグラム
 +
<pre>
 +
$ sudo tcpdump -i lo -tnlA "udp and port 54321"
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
 +
IP 127.0.0.1.54928 > 127.0.0.1.54321: UDP, length 13
 +
E..)~.@.@..............1...(Hello World!
 +
</pre>
 +
===TCP===
 +
*UDP同様アプリケーションをポートで区別
 +
*データ到達確認
 +
*破棄された場合、再送
 +
*データ到着順が入れ替わっても正しく並べ替え
 +
*HTTPやSMTPなど数多くのプロトコルの下位プロトコル
 +
*TCPでデータをやり取りする単位をセグメントという
 +
*[https://milestone-of-se.nesuke.com/nw-basic/tcp-udp/tcp-format/ TCPパケットフォーマット]
 +
====TCPコネクションの確立====
 +
----
 +
*サーバー
 +
<pre>
 +
$ nc -lnv 127.0.0.1 54321
 +
Listening on 127.0.0.1 54321
 +
Connection received on 127.0.0.1 53332
 +
</pre>
 +
*キャプチャ
 +
<pre>
 +
sudo tcpdump -i lo -tnla "tcp and port 54321"
 +
</pre>
 +
*クライアント
 +
<pre>
 +
$ nc 127.0.0.1 54321
 +
</pre>
 +
*クライアント接続で以下のダンプ
 +
*TCPでやり取りを始める場合、以下のように3つのセグメントをやり取りする、このやり取りをスリーウェイハンドシェイクという
 +
*スリーウェイハンドシェイクが完了するとTCPコネクションが確立されたとみなされる
 +
*TCPセグメントを受信した側はACKの立ったセグメントを送り返すことで示す
 +
*送信側はACKセグメントが返ってこない場合、同じセグメントを何度か送り直す
 +
[[File:tcp_connection.png|200px]]
 +
*Flagsの後の[]に囲まれた内容、S:SYN (synchronize sequence numbers), .:ACK(Acknowledgement field sgnificant) を表す
 +
*シーケンス番号はTCPがデータの順序を管理するのに利用するフィールド
 +
<pre>
 +
$ sudo tcpdump -i lo -tnla "tcp and port 54321"
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
 +
IP 127.0.0.1.53332 > 127.0.0.1.54321: Flags [S], seq 478701324, win 65495, options [mss 65495,sackOK,TS val 3420633304 ecr 0,nop,wscale 7], length 0
 +
IP 127.0.0.1.54321 > 127.0.0.1.53332: Flags [S.], seq 795900871, ack 478701325, win 65483, options [mss 65495,sackOK,TS val 3420633304 ecr 3420633304,nop,wscale 7], length 0
 +
IP 127.0.0.1.53332 > 127.0.0.1.54321: Flags [.], ack 1, win 512, options [nop,nop,TS val 3420633304 ecr 3420633304], length 0
 +
</pre>
 +
 +
====通信====
 +
----
 +
*クライアントからメッセージ送信
 +
<pre>
 +
$ nc 127.0.0.1 54321
 +
Hello World
 +
</pre>
 +
*サーバー側
 +
<pre>
 +
$ nc -lnv 127.0.0.1 54321
 +
Listening on 127.0.0.1 54321
 +
Connection received on 127.0.0.1 53408
 +
Hello World
 +
</pre>
 +
*Dump
 +
*セグメントの末尾に送信文字列が含まれている
 +
*文字列を送っているセグメントには、Pというコントロールビットのフラグが立っている。これは、PSHで、Push Functionの略
 +
*サーバーからクライアントに送られているセグメントはデータを受け取ったことを伝えているackの後ろの数字は不足なく受け取れた最後のシーケンス番号(実際の値ではなく相対値)
 +
<pre>
 +
$ sudo tcpdump -i lo -tnlA "tcp and port 54321"
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
 +
IP 127.0.0.1.53408 > 127.0.0.1.54321: Flags [P.], seq 3792056963:3792056975, ack 4147605678, win 512, options [nop,nop,TS val 3677326932 ecr 3677294810], length 12
 +
E..@..@.@.!%...........1..2..7p......4.....
 +
./.T./..Hello World
 +
 +
IP 127.0.0.1.54321 > 127.0.0.1.53408: Flags [.], ack 12, win 512, options [nop,nop,TS val 3677326932 ecr 3677326932], length 0
 +
E..4..@.@.^..........1...7p...2......(.....
 +
./.T./.T
 +
</pre>
 +
==アプリケーション層プロトコル==
 +
*無数に存在
 +
*HTTP
 +
*DNS
 +
*DHCP
 +
*など
 +
===HTTP===
 +
----
 +
<pre>
 +
$ mkdir http-home
 +
$ cd http-home
 +
$ cat << 'EOF' > index.html
 +
> <!doctype html>
 +
> <html>
 +
>  <head>
 +
>    <title>Hello, World</title>
 +
>  </head>
 +
>  <body>
 +
>    <h1>Hello, World</h1>
 +
>  </body>
 +
> </html>
 +
> EOF
 +
</pre>
 +
====HTTPサーバー====
 +
[[Python]]のHTTPサーバーを起動
 +
<pre>
 +
$ sudo python3 -m http.server -b 127.0.0.1 80
 +
Serving HTTP on 127.0.0.1 port 80 (http://127.0.0.1:80/) ...
 +
</pre>
 +
 +
====ncコマンドをブラウザとしてアクセス====
 +
<pre>
 +
$ echo -en "GET / HTTP/1.0\r\n\r\n" | nc 127.0.0.1 80
 +
HTTP/1.0 200 OK
 +
Server: SimpleHTTP/0.6 Python/3.8.10
 +
Date: Wed, 13 Apr 2022 11:56:03 GMT
 +
Content-type: text/html
 +
Content-Length: 127
 +
Last-Modified: Tue, 22 Mar 2022 15:07:11 GMT
 +
 +
<!doctype html>
 +
<html>
 +
  <head>
 +
    <title>Hello, World</title>
 +
  </head>
 +
  <body>
 +
    <h1>Hello, World</h1>
 +
  </body>
 +
</html>
 +
</pre>
 +
===DNS===
 +
----
 +
*ドメイン名の解決はOSの中でリゾルバというプログラムが担当する
 +
*リゾルバが問い合わせるDNSのサーバーをネームサーバーという
 +
 +
*確認
 +
**tcpdumpを起動
 +
<pre>
 +
$ sudo tcpdump -tnl -i any "udp and port 53"
 +
</pre>
 +
*他のターミナルから
 +
<pre>
 +
$ dig +short @8.8.8.8 typea.info A
 +
160.16.110.88
 +
</pre>
 +
*tcpdumpの結果を確認
 +
<pre>
 +
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 +
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
 +
IP 127.0.0.1.46121 > 127.0.0.53.53: 57838+ [1au] NS? . (40)
 +
IP 192.168.122.243.55378 > 192.168.122.1.53: 22272+ [1au] NS? . (28)
 +
IP 192.168.122.1.53 > 192.168.122.243.55378: 22272 13/0/1 NS c.root-servers.net., NS m.root-servers.net., NS a.root-servers.net., NS d.root-servers.net., NS l.root-servers.net., NS i.root-servers.net., NS k.root-servers.net., NS f.root-servers.net., NS b.root-servers.net., NS e.root-servers.net., NS j.root-servers.net., NS h.root-servers.net., NS g.root-servers.net. (239)
 +
IP 127.0.0.53.53 > 127.0.0.1.46121: 57838 13/0/1 NS c.root-servers.net., NS m.root-servers.net., NS a.root-servers.net., NS d.root-servers.net., NS l.root-servers.net., NS i.root-servers.net., NS k.root-servers.net., NS f.root-servers.net., NS b.root-servers.net., NS e.root-servers.net., NS j.root-servers.net., NS h.root-servers.net., NS g.root-servers.net. (239)
 +
IP 192.168.122.243.55943 > 8.8.8.8.53: 4489+ [1au] A? typea.info. (51)
 +
IP 8.8.8.8.53 > 192.168.122.243.55943: 4489 1/0/1 A 160.16.110.88 (55)
 +
</pre>
 +
===DHCP===
 +
----
 +
<pre>
 +
$ sudo ip netns add server
 +
$ sudo ip netns add client
 +
$ sudo ip link add s-veth0 type veth peer name c-veth
 +
$ sudo ip link set s-veth0 netns server
 +
$ sudo ip link set c-veth netns client
 +
$ sudo ip netns exec server ip link set s-veth0 up
 +
$ sudo ip netns exec client ip link set c-veth up
 +
$ sudo ip netns exec server ip address add 192.0.2.254/24 dev s-veth0</pre>
 +
 +
*dhcp サーバーをserverで起動
 +
<pre>
 +
$ sudo ip netns exec server dnsmasq --dhcp-range=192.0.2.100,192.0.2.200,255.255.255.0 --interface=s-veth0 --port 0 --no-resolv --no-daemon
 +
</pre>
 +
 +
*別ターミナルからDHCPサーバーを利用する
 +
<pre>
 +
$ sudo ip netns exec client dhclient -d c-veth
 +
Internet Systems Consortium DHCP Client 4.4.1
 +
Copyright 2004-2018 Internet Systems Consortium.
 +
All rights reserved.
 +
For info, please visit https://www.isc.org/software/dhcp/
 +
 +
Listening on LPF/c-veth/fa:e0:8a:cb:c5:19
 +
Sending on  LPF/c-veth/fa:e0:8a:cb:c5:19
 +
Sending on  Socket/fallback
 +
DHCPDISCOVER on c-veth to 255.255.255.255 port 67 interval 3 (xid=0x47349475)
 +
DHCPDISCOVER on c-veth to 255.255.255.255 port 67 interval 6 (xid=0x47349475)
 +
DHCPOFFER of 192.0.2.131 from 192.0.2.254
 +
DHCPREQUEST for 192.0.2.131 on c-veth to 255.255.255.255 port 67 (xid=0x75943447)
 +
DHCPACK of 192.0.2.131 from 192.0.2.254 (xid=0x47349475)
 +
bound to 192.0.2.131 -- renewal in 1695 seconds.
 +
</pre>
 +
*一旦、DHCPクライアントを終了しIPアドレスを確認
 +
<pre>
 +
$ sudo ip netns exec client ip addr show | grep "inet"
 +
    inet 192.0.2.131/24 brd 192.0.2.255 scope global dynamic c-veth
 +
    inet6 fe80::f8e0:8aff:fecb:c519/64 scope link
 +
</pre>
 +
*ルーティングテーブルを確認
 +
<pre>
 +
$ sudo ip netns exec client ip route show
 +
default via 192.0.2.254 dev c-veth
 +
192.0.2.0/24 dev c-veth proto kernel scope link src 192.0.2.131
 +
</pre>

2022年10月22日 (土) 15:58時点における最新版

| Multipass | Ubuntu |

TCP/IP

ipコマンド


基礎1

オブジェクト別名(省略形)意味
linklネットワークデバイス
addra、addressネットワークデバイスのIPアドレス
addrlabeladdrlアドレスラベル
routerルーティングテーブルのエントリー
rulerulルーティングポリシーデータベースに登録されているルール
neighn、neighbour近傍キャッシュエントリ(ARPまたはNDISCキャッシュエントリ)
ntablent、ntb近傍キャッシュの管理テーブル
tunneltIPトンネル
tuntaptuトンネルデバイス
maddrm、ma、madマルチキャストアドレス
mroutemrマルチキャストルーティングのキャッシュエントリ
mrulemruマルチキャストルーティングポリシーデータベースに登録されているルール
monitormonネットリンクメッセージの監視
xfrmx、xfIPsecポリシー
netnsnetネットワーク名前空間
l2tpl2L2TPv3(レイヤー2トンネリングプロトコル)
tcp_metricstcp_m、tcp_metrics、tcpmTCPメトリック
tokentokトークン

基礎2

基礎3

応用

ip address show


  • inet の後がIPアドレス
  • lo,ens3 はネットワークインターフェース(NICや無線LANアダプタなどを抽象化)
  • IPアドレスはネットワークインターフェースに付与される
  • 127.0.0.1はループバックアドレスで、自分自身を表す
  • ループバックアドレスが付与されているインターフェースはループバックインターフェース
$ ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:97:68:97 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.243/24 brd 192.168.122.255 scope global dynamic ens3
       valid_lft 3189sec preferred_lft 3189sec
    inet6 fe80::5054:ff:fe97:6897/64 scope link 
       valid_lft forever preferred_lft forever

tcpdump パケットキャプチャ


  • -t : 時刻情報出力抑制
  • -n : IP逆引きしない
  • -i : 対象インターフェースを指定 anyで全て
  • icmp : icmp プロトコルに限定
$ sudo tcpdump -tn -i any icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
IP 192.168.122.243 > 8.8.8.8: ICMP echo request, id 2, seq 1, length 64
IP 8.8.8.8 > 192.168.122.243: ICMP echo reply, id 2, seq 1, length 64
IP 192.168.122.243 > 8.8.8.8: ICMP echo request, id 2, seq 2, length 64
IP 8.8.8.8 > 192.168.122.243: ICMP echo reply, id 2, seq 2, length 64

traceroute


  • パケット通過ルーター
  • TTL : 0-255と解釈される値が入りパケット送出時にノードが初期値を設定、ルーター追加ごとに1つづつ値が減る。経路で値が0になるとルーターにより破棄されるが、この時ルーターは、ICMPで時間切れメッセージを送信元に送る
  •  TTLにあえて小さな値を設定し、TTLを1つづつ増やしたパケットを送信、時間切れをおこした通知を組み立てる
  •  時間切れを通知しないルーター設定は、* となる
$ traceroute typea.info
traceroute to typea.info (160.16.110.88), 64 hops max
  1   192.168.122.1  0.343ms  0.288ms  0.301ms 
  2   192.168.0.1  0.694ms  0.492ms  0.487ms 
  3   210.173.146.32  4.710ms  4.013ms  3.784ms 
  4   210.173.145.69  3.968ms  4.044ms  4.072ms 
  5   210.173.150.97  3.557ms  4.091ms  3.896ms 
  6   210.171.224.113  9.550ms  7.866ms  8.150ms 
  7   *  *  * 
  8   *  *  * 
  9   *  *  * 
 10   *  *  * 
 11   160.16.110.88  11.148ms  12.124ms  12.150ms 

ip route show ルーティングテーブル


  • 複数のルーティングエントリから構成(それぞれの行)
  •  先頭に宛先のIPアドレス
  •  宛先に続くのがネクストホップ(パケットを次に渡す相手)
$ ip route show
default via 192.168.122.1 dev ens3 proto dhcp src 192.168.122.243 metric 100 
192.168.122.0/24 dev ens3 proto kernel scope link src 192.168.122.243 
192.168.122.1 dev ens3 proto dhcp scope link src 192.168.122.243 metric 100 

IPアドレス

  • 32bitの前半をネットワーク部(ネットワークアドレス)、後半をホスト部(ホストアドレス)
  • 192.0.2.1/24 24bitで分割 -> ネットワーク部 192.0.2.0、ホスト部 .1
  • ネットワーク部は、ネットワークセグメントを表す、同じなら同じセグメントに属する
  • 192.0.2.1/24 この書き方はCIDR表記と呼ばれる
  • サブネット表記では、255.255.255.0

Network Namespace

$ sudo ip netns add helloworld
$ ip netns list
helloworld
  • ip nets exec
    • 指定したNetwork Namespace環境でコマンドを実行
$ sudo ip netns exec helloworld ip address show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  • Network Namespaceでシェルも起動できる
$ sudo ip netns exec helloworld bash

ネットワークを作成して接続


2つのNetwork Namespaceを作成

Network01.png

$ sudo ip netns add ns1
$ sudo ip netns add ns2
  • 接続するには、veth(Virtual Ethernet Device)を作成
  • Nework Namespaceに所属させる
$ sudo ip link add ns1-veth0 type veth peer name ns2-veth0
$ sudo ip link set ns1-veth0 netns ns1
$ sudo ip link set ns2-veth0 netns ns2
  • 確認
$ sudo ip netns exec ns1 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: ns1-veth0@if3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether ca:f0:3b:a9:2a:eb brd ff:ff:ff:ff:ff:ff link-netns ns2

IPアドレスを付与

$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
$ sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0
  • 確認
$ sudo ip netns exec ns1 ip address show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: ns1-veth0@if3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether ca:f0:3b:a9:2a:eb brd ff:ff:ff:ff:ff:ff link-netns ns2
    inet 192.0.2.1/24 scope global ns1-veth0
       valid_lft forever preferred_lft forever

vethを有効化

$ sudo ip netns exec ns1 ip link set ns1-veth0 up
$ sudo ip netns exec ns2 ip link set ns2-veth0 up
  • 疎通
$ sudo ip netns exec ns1 ping 192.0.2.2 -c 3
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.334 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.101 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.091 ms

--- 192.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2051ms
rtt min/avg/max/mdev = 0.091/0.175/0.334/0.112 ms

ルーターを介したネットワーク


Network router.png

Network Namespaceの構成

$ sudo ip netns add ns1
$ sudo ip netns add router
$ sudo ip netns add route2
$ sudo ip netns add ns2
  • それぞれのNetwork Namespaceを繋ぐvethインターフェースを作成
$ sudo ip link add ns1-veth0 type veth peer name gw-veth0
$ sudo ip link add ns2-veth0 type veth peer name gw-veth1
  • vethをNetwork Namespaceに属させる
$ sudo ip link set ns1-veth0 netns ns1
$ sudo ip link set gw-veth0 netns router
$ sudo ip link set gw-veth1 netns router
$ sudo ip link set ns2-veth0 netns ns2
  • vethをup
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
$ sudo ip netns exec router ip link set gw-veth0 up
$ sudo ip netns exec router ip link set gw-veth1 up
$ sudo ip netns exec ns2 ip link set ns2-veth0 up
  • IPアドレスを付与
$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
$ sudo ip netns exec router ip address add 192.0.2.254/24 dev gw-veth0
$ sudo ip netns exec router ip address add 198.51.100.254/24 dev gw-veth1
$ sudo ip netns exec ns2 ip address add 198.51.100.1/24 dev ns2-veth0

セグメント内の通信

  • ns1 と ns2それぞれから、rouer にping
$ sudo ip netns exec ns1 ping -c 3 192.0.2.254
PING 192.0.2.254 (192.0.2.254) 56(84) bytes of data.
64 bytes from 192.0.2.254: icmp_seq=1 ttl=64 time=0.362 ms
64 bytes from 192.0.2.254: icmp_seq=2 ttl=64 time=0.102 ms
64 bytes from 192.0.2.254: icmp_seq=3 ttl=64 time=0.108 ms

--- 192.0.2.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2049ms
rtt min/avg/max/mdev = 0.102/0.190/0.362/0.121 ms
$ sudo ip netns exec ns2 ping -c 3 198.51.100.254
PING 198.51.100.254 (198.51.100.254) 56(84) bytes of data.
64 bytes from 198.51.100.254: icmp_seq=1 ttl=64 time=0.314 ms
64 bytes from 198.51.100.254: icmp_seq=2 ttl=64 time=0.106 ms
64 bytes from 198.51.100.254: icmp_seq=3 ttl=64 time=0.110 ms

--- 198.51.100.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2051ms
rtt min/avg/max/mdev = 0.106/0.176/0.314/0.097 ms
  • セグメントはこえられない
$ sudo ip netns exec ns1 ping -c 3 198.51.100.1
ping: connect: Network is unreachable

ルーティングテーブルの確認と設定

  • 確認
  • 自身のセグメントしか表示されない
$ sudo ip netns exec ns1 ip route show
192.0.2.0/24 dev ns1-veth0 proto kernel scope link src 192.0.2.1 
  • デフォルトルート(他の宛先に一致しない場合)を追加、routerに向ける
$ sudo ip netns exec ns1 ip route add default via 192.0.2.254
  • 追加された
$ sudo ip netns exec ns1 ip route show
default via 192.0.2.254 dev ns1-veth0 
192.0.2.0/24 dev ns1-veth0 proto kernel scope link src 192.0.2.1 
  • ns2にも同様に
$ sudo ip netns exec ns2 ip route add default via 198.51.100.254
  • ns1 から ns2 へ再度 ping
  • エラーとはならないが、パケットロス100%
$ sudo ip netns exec ns1 ping -c 3 198.51.100.1
PING 198.51.100.1 (198.51.100.1) 56(84) bytes of data.

--- 198.51.100.1 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2039ms
  • 以下の設定を実施
  • sysctlでカーネルパラメータを設定(net.ipv4.ip_forward = 1 ルーターとして動作するかを設定)
$ sudo ip netns exec router sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
  • ルーターを介した接続成功
$ sudo ip netns exec ns1 ping -c 3 198.51.100.1
PING 198.51.100.1 (198.51.100.1) 56(84) bytes of data.
64 bytes from 198.51.100.1: icmp_seq=1 ttl=63 time=0.208 ms
64 bytes from 198.51.100.1: icmp_seq=2 ttl=63 time=0.114 ms
64 bytes from 198.51.100.1: icmp_seq=3 ttl=63 time=0.134 ms

--- 198.51.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2032ms
rtt min/avg/max/mdev = 0.114/0.152/0.208/0.040 ms

ルーターを増やす

Network3.png

  •  これまでの設定を削除
$ sudo ip --all netns delete
$ sudo ip netns ls

Network Namespace作成

$ sudo ip netns add ns1
$ sudo ip netns add router1
$ sudo ip netns add router2
$ sudo ip netns add ns2
  • veth作成
$ sudo ip link add ns1-veth0 type veth peer name gw1-veth0
$ sudo ip link add gw1-veth1 type veth peer name gw2-veth0
$ sudo ip link add gw2-veth1 type veth peer name ns2-veth0
  • vethを所属させる
$ sudo ip link set ns1-veth0 netns ns1
$ sudo ip link set gw1-veth0 netns router1
$ sudo ip link set gw1-veth1 netns router1
$ sudo ip link set gw2-veth0 netns router2
$ sudo ip link set gw2-veth1 netns router2
$ sudo ip link set ns2-veth0 netns ns2
  • up
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
$ sudo ip netns exec router1 ip link set gw1-veth0 up
$ sudo ip netns exec router1 ip link set gw1-veth1 up
$ sudo ip netns exec router2 ip link set gw2-veth0 up
$ sudo ip netns exec router2 ip link set gw2-veth1 up
$ sudo ip netns exec ns2 ip link set ns2-veth0 up

IP設定

$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
$ sudo ip netns exec router1 ip address add 192.0.2.254/24 dev gw1-veth0
$ sudo ip netns exec router1 ip address add 203.0.113.1/24 dev gw1-veth1
$ sudo ip netns exec router2 ip address add 203.0.113.2/24 dev gw2-veth0
$ sudo ip netns exec router2 ip address add 198.51.100.254/24 dev gw2-veth1
$ sudo ip netns exec ns2 ip address add 198.51.100.1/24 dev ns2-veth0
  • ns1,ns2 のデフォルトルートをルーターに向ける
$ sudo ip netns exec ns1 ip route add default via 192.0.2.254
$ sudo ip netns exec ns2 ip route add default via 198.51.100.254
  • router1,route2のカーネルオプションを設定しルーターにする
$ sudo ip netns exec router1 sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
$ sudo ip netns exec router2 sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
  • ns1から、ns2へpingを流すと、router1からパケットを届けることができなかったメッセージが帰る
$ sudo ip netns exec ns1 ping -c 3 198.51.100.1
PING 198.51.100.1 (198.51.100.1) 56(84) bytes of data.
From 192.0.2.254 icmp_seq=1 Destination Net Unreachable
From 192.0.2.254 icmp_seq=2 Destination Net Unreachable
From 192.0.2.254 icmp_seq=3 Destination Net Unreachable

--- 198.51.100.1 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2025ms

ルーターにもルーティングエントリを追加

$ sudo ip netns exec router1 ip route add 198.51.100.0/24 via 203.0.113.2
$ sudo ip netns exec router2 ip route add 192.0.2.0/24 via 203.0.113.1
  • ns1から、ns2へpingが通るようになった
$ sudo ip netns exec ns1 ping -c 3 198.51.100.1
PING 198.51.100.1 (198.51.100.1) 56(84) bytes of data.
64 bytes from 198.51.100.1: icmp_seq=1 ttl=62 time=0.093 ms
64 bytes from 198.51.100.1: icmp_seq=2 ttl=62 time=0.158 ms
64 bytes from 198.51.100.1: icmp_seq=3 ttl=62 time=0.155 ms

--- 198.51.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2030ms
rtt min/avg/max/mdev = 0.093/0.135/0.158/0.029 ms

ルーティング

  • 手動でルーティングエントリを追加する方式:静的経路制御(スタティックルーティング)
  • ルーター同士が自律的に自身が知っているルーティング情報を教え合う方式:動的経路制御(ダイナミックルーティング)
  • ルーティング情報交換プロトコル:BGP(Border Gateway Protocol)やOSPF(Open Shortest Path First)

イーサネット

  • OSI参照モデルでは、データリンク層と物理層に対応、IPの下の階層
  • OSI参照モデルや、TCP/IPの階層構造を下から番号を振って呼ぶことがある例えば、IPなら下から3番目のためレイヤー3、イーサネットは一般的にレイヤー2と見做される
  • イーサネットはIPを含む上位プロトコルのデータを運ぶ
  • イーサネットではデータを運ぶ1単位をフレーム(Frame)という
  • フレームの送信元、送信先の管理に使われるのが、MACアドレスとなり、イーサネットのフレームを受信する機器ごとに付与される
  • MACアドレスは、48ビット空間(上位24ビットは製造ベンダー、下位24ビットはベンダーが一意になるよう割り振る)を持った整数値で、原則的には全世界で一意
  • MACアドレスの一意性は厳しくなく、仮想マシンのハイパーバイザーが動的に割り振ると、重複の可能性があるが、ブロードキャストドメインの中で重複しなければ問題ない

Network Namespaceの作成

$ sudo ip netns add ns1
$ sudo ip netns add ns2
  • vethインターフェースの作成
$ sudo ip link add ns1-veth0 type veth peer name ns2-veth0
  • インターフェースを所属させ、up
$ sudo ip link set ns1-veth0 netns ns1
$ sudo ip link set ns2-veth0 netns ns2
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
$ sudo ip netns exec ns2 ip link set ns2-veth0 up
  • IPアドレスの設定
$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
$ sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0
  • MACアドレスの設定
$ sudo ip netns exec ns1 ip link set dev ns1-veth0 address 00:00:5E:00:53:01
$ sudo ip netns exec ns2 ip link set dev ns2-veth0 address 00:00:5E:00:53:02
  • 確認
$ sudo ip netns exec ns1 ip link show | grep "link/ether"
    link/ether 00:00:5e:00:53:01 brd ff:ff:ff:ff:ff:ff link-netns ns2
$ sudo ip netns exec ns2 ip link show | grep "link/ether"
    link/ether 00:00:5e:00:53:02 brd ff:ff:ff:ff:ff:ff link-netns ns1
  • 別ターミナルから、パケットキャプチャ準備
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ns1-veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
  • ns1 から ns2 へping
$ sudo ip netns exec ns1 ping -c 3 192.0.2.2
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.461 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.196 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.187 ms

--- 192.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.187/0.281/0.461/0.127 ms
  • ダンプの内容を確認
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ns1-veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37038, seq 1, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37038, seq 1, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37038, seq 2, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37038, seq 2, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37038, seq 3, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37038, seq 3, length 64
  • どうやって、MACアドレスを知るのか?一旦、MACアドレスのキャッシュをクリア
$ sudo ip netns exec ns1 ip neigh flush all
  • icmp だけでなく、arpもダンプ対象に加える
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp or arp
  • 再度ping
$ sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0 icmp or arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ns1-veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
00:00:5e:00:53:01 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.0.2.2 tell 192.0.2.1, length 28
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype ARP (0x0806), length 42: Reply 192.0.2.2 is-at 00:00:5e:00:53:02, length 28
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37051, seq 1, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37051, seq 1, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37051, seq 2, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37051, seq 2, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 37051, seq 3, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 37051, seq 3, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype ARP (0x0806), length 42: Request who-has 192.0.2.1 tell 192.0.2.2, length 28
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype ARP (0x0806), length 42: Reply 192.0.2.1 is-at 00:00:5e:00:53:01, length 28

ブリッジ

  • スイッチングハブを利用すると複数のネットワーク機器を同じブロードキャストドメインに接続できる
  • スイッチングハブを一般化した用語がブリッジ
  • ブリッジはデータリンク層でフレームを転送する
  • ブリッジは自身のどのポートにどのMACアドレスの機器が接続されているかMACアドレステーブルを用いて管理する
  • Linuxにはブリッジの実装として、ネットワークブリッジという機能がある
  • Network Namespaceを作成
$ sudo ip netns add ns1
$ sudo ip netns add ns2
$ sudo ip netns add ns3
$ sudo ip netns add bridge
  • veth作成
$ sudo ip link add ns1-veth0 type veth peer name ns1-br0
$ sudo ip link add ns2-veth0 type veth peer name ns2-br0
$ sudo ip link add ns3-veth0 type veth peer name ns3-br0
  • 所属させる
$ sudo ip link set ns1-veth0 netns ns1
$ sudo ip link set ns2-veth0 netns ns2
$ sudo ip link set ns3-veth0 netns ns3
$ sudo ip link set ns1-br0 netns bridge
$ sudo ip link set ns2-br0 netns bridge
$ sudo ip link set ns3-br0 netns bridge
  • up
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
$ sudo ip netns exec ns2 ip link set ns2-veth0 up
$ sudo ip netns exec ns3 ip link set ns3-veth0 up
$ sudo ip netns exec bridge ip link set ns1-br0 up
$ sudo ip netns exec bridge ip link set ns3-br0 up
$ sudo ip netns exec bridge ip link set ns3-br0 up
  • Ip
$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
$ sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0
$ sudo ip netns exec ns3 ip address add 192.0.2.3/24 dev ns3-veth0
  • bridge
$ sudo ip netns exec bridge ip link add dev br0 type bridge
$ sudo ip netns exec bridge ip link set br0 up
  • ブリッジに接続
$ sudo ip netns exec bridge ip link set ns1-br0 master br0
$ sudo ip netns exec bridge ip link set ns2-br0 master br0
$ sudo ip netns exec bridge ip link set ns3-br0 master br0
  • ping : ns1 -> ns2
$ sudo ip netns exec ns1 ping -c 3 192.0.2.2
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.496 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.139 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.141 ms

--- 192.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2034ms
rtt min/avg/max/mdev = 0.139/0.258/0.496/0.167 ms
  • ping : ns1 -> ns3
  • ネットワークブリッジを介して3つのNetwork Namespaceが同じセグメントにつながった
$ sudo ip netns exec ns1 ping -c 3 192.0.2.3
PING 192.0.2.3 (192.0.2.3) 56(84) bytes of data.
64 bytes from 192.0.2.3: icmp_seq=1 ttl=64 time=0.262 ms
64 bytes from 192.0.2.3: icmp_seq=2 ttl=64 time=0.138 ms
64 bytes from 192.0.2.3: icmp_seq=3 ttl=64 time=0.138 ms

--- 192.0.2.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2035ms
rtt min/avg/max/mdev = 0.138/0.179/0.262/0.058 ms

ブリッジの削除

# ip link set br100 down
# brctl delbr br100

トランスポート層プロトコル

ポート

  • OSが自動で割り当てるポートをエフェメラルポートという
  • 0~1023(システムポート、またはウェルノウンポート)
  • 1024~49151(ユーザポート、またはレジスタードポート)
  • 49152~65535(ダイナミックポート、またはプライベートポート)

UDP

nc(netcat)コマンド


  • ループバックアドレスを使って、UDPの54321番ポートで、ncコマンドが通信を待ち受け
$ nc -ulnv 127.0.0.1 54321
Bound on 127.0.0.1 54321
  • クライアントから接続してメッセージ
$ nc -u 127.0.0.1 54321
Hello World!
  • サーバーで確認
  • 54928 は、エフェメラルポート
$ nc -ulnv 127.0.0.1 54321
Bound on 127.0.0.1 54321
Connection received on 127.0.0.1 54928
Hello World!
  • 別ターミナルから、tcpdumpでやり取りを確認
  • パケットのペイロードはUDPダイアグラム
$ sudo tcpdump -i lo -tnlA "udp and port 54321"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 127.0.0.1.54928 > 127.0.0.1.54321: UDP, length 13
E..)~.@.@..............1...(Hello World!

TCP

  • UDP同様アプリケーションをポートで区別
  • データ到達確認
  • 破棄された場合、再送
  • データ到着順が入れ替わっても正しく並べ替え
  • HTTPやSMTPなど数多くのプロトコルの下位プロトコル
  • TCPでデータをやり取りする単位をセグメントという
  • TCPパケットフォーマット

TCPコネクションの確立


  • サーバー
$ nc -lnv 127.0.0.1 54321
Listening on 127.0.0.1 54321
Connection received on 127.0.0.1 53332
  • キャプチャ
sudo tcpdump -i lo -tnla "tcp and port 54321"
  • クライアント
$ nc 127.0.0.1 54321
  • クライアント接続で以下のダンプ
  • TCPでやり取りを始める場合、以下のように3つのセグメントをやり取りする、このやり取りをスリーウェイハンドシェイクという
  • スリーウェイハンドシェイクが完了するとTCPコネクションが確立されたとみなされる
  • TCPセグメントを受信した側はACKの立ったセグメントを送り返すことで示す
  • 送信側はACKセグメントが返ってこない場合、同じセグメントを何度か送り直す

Tcp connection.png

  • Flagsの後の[]に囲まれた内容、S:SYN (synchronize sequence numbers), .:ACK(Acknowledgement field sgnificant) を表す
  • シーケンス番号はTCPがデータの順序を管理するのに利用するフィールド
$ sudo tcpdump -i lo -tnla "tcp and port 54321"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 127.0.0.1.53332 > 127.0.0.1.54321: Flags [S], seq 478701324, win 65495, options [mss 65495,sackOK,TS val 3420633304 ecr 0,nop,wscale 7], length 0
IP 127.0.0.1.54321 > 127.0.0.1.53332: Flags [S.], seq 795900871, ack 478701325, win 65483, options [mss 65495,sackOK,TS val 3420633304 ecr 3420633304,nop,wscale 7], length 0
IP 127.0.0.1.53332 > 127.0.0.1.54321: Flags [.], ack 1, win 512, options [nop,nop,TS val 3420633304 ecr 3420633304], length 0

通信


  • クライアントからメッセージ送信
$ nc 127.0.0.1 54321
Hello World
  • サーバー側
$ nc -lnv 127.0.0.1 54321
Listening on 127.0.0.1 54321
Connection received on 127.0.0.1 53408
Hello World
  • Dump
  • セグメントの末尾に送信文字列が含まれている
  • 文字列を送っているセグメントには、Pというコントロールビットのフラグが立っている。これは、PSHで、Push Functionの略
  • サーバーからクライアントに送られているセグメントはデータを受け取ったことを伝えているackの後ろの数字は不足なく受け取れた最後のシーケンス番号(実際の値ではなく相対値)
$ sudo tcpdump -i lo -tnlA "tcp and port 54321"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 127.0.0.1.53408 > 127.0.0.1.54321: Flags [P.], seq 3792056963:3792056975, ack 4147605678, win 512, options [nop,nop,TS val 3677326932 ecr 3677294810], length 12
E..@..@.@.!%...........1..2..7p......4.....
./.T./..Hello World

IP 127.0.0.1.54321 > 127.0.0.1.53408: Flags [.], ack 12, win 512, options [nop,nop,TS val 3677326932 ecr 3677326932], length 0
E..4..@.@.^..........1...7p...2......(.....
./.T./.T

アプリケーション層プロトコル

  • 無数に存在
  • HTTP
  • DNS
  • DHCP
  • など

HTTP


$ mkdir http-home
$ cd http-home
$ cat << 'EOF' > index.html
> <!doctype html>
> <html>
>   <head>
>     <title>Hello, World</title>
>   </head>
>   <body>
>     <h1>Hello, World</h1>
>   </body>
> </html>
> EOF

HTTPサーバー

PythonのHTTPサーバーを起動

$ sudo python3 -m http.server -b 127.0.0.1 80
Serving HTTP on 127.0.0.1 port 80 (http://127.0.0.1:80/) ...

ncコマンドをブラウザとしてアクセス

$ echo -en "GET / HTTP/1.0\r\n\r\n" | nc 127.0.0.1 80
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.8.10
Date: Wed, 13 Apr 2022 11:56:03 GMT
Content-type: text/html
Content-Length: 127
Last-Modified: Tue, 22 Mar 2022 15:07:11 GMT

<!doctype html>
<html>
  <head>
    <title>Hello, World</title>
  </head>
  <body>
    <h1>Hello, World</h1>
  </body>
</html>

DNS


  • ドメイン名の解決はOSの中でリゾルバというプログラムが担当する
  • リゾルバが問い合わせるDNSのサーバーをネームサーバーという
  • 確認
    • tcpdumpを起動
$ sudo tcpdump -tnl -i any "udp and port 53"
  • 他のターミナルから
$ dig +short @8.8.8.8 typea.info A
160.16.110.88
  • tcpdumpの結果を確認
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
IP 127.0.0.1.46121 > 127.0.0.53.53: 57838+ [1au] NS? . (40)
IP 192.168.122.243.55378 > 192.168.122.1.53: 22272+ [1au] NS? . (28)
IP 192.168.122.1.53 > 192.168.122.243.55378: 22272 13/0/1 NS c.root-servers.net., NS m.root-servers.net., NS a.root-servers.net., NS d.root-servers.net., NS l.root-servers.net., NS i.root-servers.net., NS k.root-servers.net., NS f.root-servers.net., NS b.root-servers.net., NS e.root-servers.net., NS j.root-servers.net., NS h.root-servers.net., NS g.root-servers.net. (239)
IP 127.0.0.53.53 > 127.0.0.1.46121: 57838 13/0/1 NS c.root-servers.net., NS m.root-servers.net., NS a.root-servers.net., NS d.root-servers.net., NS l.root-servers.net., NS i.root-servers.net., NS k.root-servers.net., NS f.root-servers.net., NS b.root-servers.net., NS e.root-servers.net., NS j.root-servers.net., NS h.root-servers.net., NS g.root-servers.net. (239)
IP 192.168.122.243.55943 > 8.8.8.8.53: 4489+ [1au] A? typea.info. (51)
IP 8.8.8.8.53 > 192.168.122.243.55943: 4489 1/0/1 A 160.16.110.88 (55)

DHCP


$ sudo ip netns add server
$ sudo ip netns add client
$ sudo ip link add s-veth0 type veth peer name c-veth
$ sudo ip link set s-veth0 netns server
$ sudo ip link set c-veth netns client
$ sudo ip netns exec server ip link set s-veth0 up
$ sudo ip netns exec client ip link set c-veth up
$ sudo ip netns exec server ip address add 192.0.2.254/24 dev s-veth0
  • dhcp サーバーをserverで起動
$ sudo ip netns exec server dnsmasq --dhcp-range=192.0.2.100,192.0.2.200,255.255.255.0 --interface=s-veth0 --port 0 --no-resolv --no-daemon
  • 別ターミナルからDHCPサーバーを利用する
$ sudo ip netns exec client dhclient -d c-veth
Internet Systems Consortium DHCP Client 4.4.1
Copyright 2004-2018 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/c-veth/fa:e0:8a:cb:c5:19
Sending on   LPF/c-veth/fa:e0:8a:cb:c5:19
Sending on   Socket/fallback
DHCPDISCOVER on c-veth to 255.255.255.255 port 67 interval 3 (xid=0x47349475)
DHCPDISCOVER on c-veth to 255.255.255.255 port 67 interval 6 (xid=0x47349475)
DHCPOFFER of 192.0.2.131 from 192.0.2.254
DHCPREQUEST for 192.0.2.131 on c-veth to 255.255.255.255 port 67 (xid=0x75943447)
DHCPACK of 192.0.2.131 from 192.0.2.254 (xid=0x47349475)
bound to 192.0.2.131 -- renewal in 1695 seconds.
  • 一旦、DHCPクライアントを終了しIPアドレスを確認
$ sudo ip netns exec client ip addr show | grep "inet"
    inet 192.0.2.131/24 brd 192.0.2.255 scope global dynamic c-veth
    inet6 fe80::f8e0:8aff:fecb:c519/64 scope link 
  • ルーティングテーブルを確認
$ sudo ip netns exec client ip route show
default via 192.0.2.254 dev c-veth 
192.0.2.0/24 dev c-veth proto kernel scope link src 192.0.2.131