0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Linuxで動かしながら学ぶtcp/ipネットワーク入門 輪読1

Last updated at Posted at 2024-06-15

Linuxで動かしながら学ぶtcp/ipネットワーク入門 輪読

「Linuxで動かしながら学ぶtcp/ipネットワーク入門」をdocker ubuntuを使って、動かしながら読み進めた備忘録。

Goal

この回では、ubuntu内で仮想的なネームスペースを二つ作って、互いに通信できるところまでを目標にします。この回では同一セグメント内での二つのdeviceでPingできるがGoalです。

macに実行環境構築

環境はmac環境でdocker ubuntu 20.04を使用。

% docker run -it --privileged ubuntu:20.04 bash

docker内のnamespace作成には、--prividegedでdocker containerをsysctrl権限付きで起動する必要があります。

参考 `docker run`せずに`docker pull`して、`docker container create --name learn-tcpip ubuntu:20.04`などとしてdownloadした\[repository:tag\](=image名?)を指定し、containerに好きな名前をつけるもよしです。
dockerのimage名とは[repository:tag]のこと? https://ja.stackoverflow.com/questions/32345/docker%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E5%90%8D%E3%81%A8%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E5%90%8D%E3%81%A3%E3%81%A6%E5%90%8C%E3%81%98%E3%82%82%E3%81%AE 
% docker create --name learn-tcpip ubuntu:20.04
f57fa4120e1e0dde140109a2cec6eed8f521b7f997cde5aa2fabbb440ff537a4

or

% docker container create --name learn-tcpip ubuntu:20.04
f57fa4120e1e0dde140109a2cec6eed8f521b7f997cde5aa2fabbb440ff537a4

containerを作成したら、停止中のcontainerリストを下記コマンドで表示して、containerを起動します。

% docker container ls -a
CONTAINER ID   IMAGE                                   COMMAND                   CREATED         STATUS                    PORTS     NAMES
f57fa4120e1e   ubuntu:20.04                            "bash"  
% docker container start f57fa4120e1e
f57fa4120e1e

docker containerの内部で実行していきます。

% docker container exec -it --privileged f57fa4120e1e bash
root@f57fa4120e1e:/#

interface接続までの流れ(物理的な接続)

Network Namespaceとは、独立したネットワークと思ってよく、ネットワークインターフェイスやルーティングテーブルを持ちます。
手順は下記。

  1. Namespaceを2つ作成, ns1, ns2とする
  2. Network interfaceを2つ作成、ns1-veth0、ns2-veth0とする
  3. interfaceをそれぞれnamespaceに接続する

一度daemonを切ると、namespaceは有効でないとエラーが表示されます。
このためnamespaceを削除して作り直します。

なお、今回使用したコマンドたちはこちらのリンク先にまとめてあります。dockerのcontainerが一旦停止するとnamespaceは無効化されますので、復旧などに。

daemonを再起動するとnamespaceは無効になるっぽい
root@f57fa4120e1e:/# ip netns list
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
Error: Peer netns reference is invalid.
helloworld
Error: Peer netns reference is invalid.
ns3
Error: Peer netns reference is invalid.
ns2
Error: Peer netns reference is invalid.
ns1
root@f57fa4120e1e:/# ip netns delete ns1
root@f57fa4120e1e:/# ip netns delete ns2
root@f57fa4120e1e:/# ip netns delete ns3
root@f57fa4120e1e:/# sudo ip netns add ns1
root@f57fa4120e1e:/# sudo ip netns add ns2
root@f57fa4120e1e:/# sudo ip netns add ns3

ns1-veth0ns2-veth0でvethのnetwork interfaceを作ります。
interfaceの実体はファイルである。すでにある場合はファイルが既にあるとエラーメッセージが出力されます。

root@f57fa4120e1e:/# sudo ip link add ns1-veth0 type veth peer name ns2-veth0 
root@f57fa4120e1e:/# sudo ip link show | grep veth
4: ns2-veth0@ns1-veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
6: ns1-veth0@ns2-veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
root@b

作成したinterfaceをnetwork namespaceの持ち物にします。

root@f57fa4120e1e:/# sudo ip link set ns1-veth0 netns ns1
root@f57fa4120e1e:/# sudo ip link set ns2-veth0 netns ns2

namespace内のinterfaceになるので、linkをshowしても何も表示されなくなります。
(スコープが区切られたみたいな感じ)

root@f57fa4120e1e:/# sudo ip link show | grep veth
root@f57fa4120e1e:/# 

namespaceを指定して、ip linkを表示します。

root@f57fa4120e1e:/# sudo ip netns exec ns1 ip link show | grep veth
6: ns1-veth0@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
root@f57fa4120e1e:/# sudo ip netns exec ns2 ip link show | grep veth
4: ns2-veth0@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

作成済みのnamespace ns1, ns2に対して、ip linkが作成されています。

これでveth interfaceは仮想的なLANケーブルの役割を担います。なので、二つのnamespaceはこの仮想的なLANケーブルで繋がっています。
これはLANケーブルで二つのコンピュータが接続されているのと同じような感じです。
veth interfaceにip addressを付与すれば通信ができます。

ここまでで以下のように接続ができました。LANケーブルでコンピュータ同士が接続されたように、仮想ネットワークネームスペースがインターフェースを通じて接続されています。

network1.png

これはLANケーブルでコンピュータを接続している状態です。ip addressを設定して通信ができるようになります。

interfaceにip addressを付与(論理的な設定)

各ネットワークスペースそれぞれでip addressを割り当てます。

root@f57fa4120e1e:/# sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
root@f57fa4120e1e:/# sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0

interfaceの状態を確認します。

root@f57fa4120e1e:/# sudo ip netns exec ns1 ip link show ns1-veth0 | grep state
6: ns1-veth0@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
root@f57fa4120e1e:/# sudo ip netns exec ns2 ip link show ns2-veth0 | grep state
4: ns2-veth0@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

network interfaceのSTATEの項目がDOWNになっています。明示的にUPにすることで通信ができます。

root@f57fa4120e1e:/# sudo ip netns exec ns1 ip link set ns1-veth0 up
root@f57fa4120e1e:/# sudo ip netns exec ns2 ip link set ns2-veth0 up

state UPになりました。

root@f57fa4120e1e:/# sudo ip netns exec ns1 ip link show ns1-veth0 | grep state
6: ns1-veth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
root@f57fa4120e1e:/# sudo ip netns exec ns2 ip link show ns2-veth0 | grep state
4: ns2-veth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
root@f57fa4120e1e:/# 

pingしてみむとす

ns1からns2のIPに向けてpingしてみむとす。

dockerにping install

docker imageにpingがないときは次のコマンドで入れましょう。

apt-get install iputils-ping net-tools

https://qiita.com/manabuishiirb/items/26de8c9740a1d2c7cfdd
 

root@b27d3bad4e97:/# 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.724 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.211 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.147 ms

--- 192.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2084ms
rtt min/avg/max/mdev = 0.147/0.360/0.724/0.258 ms

ns1からns2にpingを送信して返ってくることが確認できました。
これでPingの疎通ができました。

┗(`・∀・´)ヨッシャ!

物理的な配線を論理的に設定することで通信することができるってことです。

論理構成されたネットワークはこのようになってます。

network1.drawio.png

ここまででTCP/IPの実験環境の準備ができました。

ルータがいなくても通信できるのは、同じセグメント内同士だからです。
ルータは異なるセグメントと通信する為の機能です。
セグメントとは何か、ルータとは何かをよりよく理解するためにはIP Addressの設計をよく知ることが必要です。次のページではIP Addressについてみていきます。

IP Addressで理解するセグメント

先ほど、ip addressを付与した時のコマンドをもう一度見てみます。

root@f57fa4120e1e:/# sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
root@f57fa4120e1e:/# sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev ns2-veth0

1行目のコマンドでは、devでdevice名を指定し、ns1-veth0としました。
また、ip addressは192.0.2.1/24が値として割り当てられています。
2行目のコマンドについても同様です。まとめると次のような値の割り当てが行われています、

namespace name device ip address
ns1 ns1-veth0 192.0.2.1/24
ns2 ns2-veth0 192.0.2.2/24

ip addressは32bitの2進数表現を8bitで区切り、10進数に変換されたものです。
今回は、共通部分は192.0.2です。これがセグメントを表します。/24は32bitsのうち、何bitsをセグメントに割り当てるかを表します。ですから、この場合、残る8bitを10進数表現した1及び2が同一セグメント内におけるip addressを指します。

次の図のような構成でip addressを割り当てるコマンドだったのです。

ipaddress.png

今回は、ルータを使わず、同一セグメント内で通信できるネットワークを作りました。次はルータを使用して、異なるセグメント同士で通信できるネットワークを作ります。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?