LoginSignup
7
7

More than 5 years have passed since last update.

「ソースコードで体感するネットワークの仕組み」のサンプルコードを動かすためにVagrantを用いてネットワーク構成環境を整える

Posted at

Vagrantを用いて書籍のプログラムのネットワーク構成環境を整える

動機

ソースコードで体感するネットワークの仕組み ~手を動かしながら基礎からTCP/IPの実装までがわかるの本を読んでいるが、サンプルコード動かすのに、Vagrant用いて試行錯誤的にネットワーク構成してみた。


  • ホストOS .. macOS X
  • ゲストOS(複数台とも) .. ubuntu16.04

第2章 仮想IPホストプログラム

事前にサンプルプログラム1をダウンロードしておく。

Vagrantでは、NATのネットワーク(デフォルトのネットワークアドレスは10.0.2.0/24)がデフォルトで構成されていて、10.0.2.2がルータとして、すでに配置されているので、一番単純に構成するならば、

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.synced_folder ".", "/home/vagrant/test"
  config.vm.provider :virtualbox do |vb|
    # change 10.0.2.0/24 with what you want
    # See also https://www.virtualbox.org/manual/ch09.html#changenat
    vb.customize ['modifyvm', :id, '--natnet1', '192.168.111.0/24']
  end
end

となる。vb.customize ..の部分は、デフォルトの10.0.2.0/24ネットワークを変更しに行っている:

ゲストOS
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.111.2   0.0.0.0         UG    0      0        0 eth0
192.168.111.0   *               255.255.255.0   U     0      0        0 eth0
/MyEth.ini
IP-TTL=64
device=eth0
# ホストOS:  `ip a`のeth0ネットワークインターフェース。
vmac=08:00:27:16:16:86
vip=192.168.111.15
vmask=255.255.255.0
# `route | grep default` or `netstat -rn`でGenmaskが0.0.0.0のやつ or `ip route` のdefaultの行
gateway=192.168.111.2

で「とりあえずは」OK。(./MyEth.iniはサンプルプログラムの構成ファイル)
ゲスト側OS(ubuntu)で、ping 8.8.8.8をうつと、192.168.111.2を経由して、8.8.8.8(googleのDNS)に疎通する2

自力でroutingできるようにする

課題点

上で基本的にOKだと思うんだけど、複数台のゲストOSに対しては、この構成は本質的に問題がある。というのは、NATのネットワークはゲストOSごとにネットワークを構成するので、
ゲストOSは複数台構成しても同じIPアドレスになってしまっているから。http://zorinos.seesaa.net/article/450304938.html のNATの図が非常にわかりやすい。

やりたいこととしては、client PCでping 8.8.8.8すると、master PC(デフォルトゲートウェイとして機能)の192.168.111.2を経由して38.8.8.8に疎通させたい。
そのためには以下のような構成(内部ネットワーク)にする。

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "master" do |conf|
    conf.vm.box = "ubuntu/trusty64"
    conf.vm.network "private_network", ip: "192.168.111.2", virtualbox__intnet: "mynet"
  end


  config.vm.define "client" do |conf|
    conf.vm.box = "ubuntu/trusty64"
    conf.vm.network "private_network", ip: "192.168.111.100", virtualbox__intnet: "mynet"
    conf.vm.synced_folder ".", "/home/vagrant/test"
  end
end

Note) 複数のゲストOSにvirtualbox__intnetで同名を指定すると、内部ネットワークが構成できる。このネットワークはホストOS(MacOS X)から見えない。
ホストOS(macOS X)からifconfigしてもvboxnetのnetwork interfaceが見えないこことで確認可能だ。4


この後、clientのPC(192.168.111.100)に対して、192.168.111.2をデフォルトゲートウェイとするために、masterのマシンを自力でrouterにする必要がある。
(clientのPCは複数台構成可能で、そうしたい場合は、Vagrantfileでclient0, client1として、ipアドレスを一意にした上で、clientの設定と同じように書けば良さそう。

clientVM
$ vagrant ssh client
$ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  10.0.2.2 (10.0.2.2)  0.298 ms  0.819 ms  0.553 ms
 2  192.168.150.1 (192.168.150.1)  58.173 ms  58.104 ms  59.045 ms
 ...
10  108.170.238.85 (108.170.238.85)  7.513 ms 72.14.236.129 (72.14.236.129)  7.435 ms 209.85.143.49 (209.85.143.49)  7.364 ms
11  google-public-dns-a.google.com (8.8.8.8)  7.398 ms  7.326 ms  7.916 ms

ということで10.0.2.2のrouterがdefault gatewayになっている。routeコマンドでもわかるけど。(VM同士はpingで疎通可能になっている)

今の状態から、sudo route add default gw 192.168.111.2 && sudo route del default gw 10.0.2.2としてdefault gatewayを変更しても、192.168.111.100のPC(master)には、routing設定がされていないため、routingできない。(つまり、ping 8.8.8.8が応答しない)

そこで、自力でmasterのPCをroutingできるようにしよう。

ルータ化する

とは言っても基本的には、http://maruchan-shiro123.hatenablog.com/entry/2015/04/05/181854 の通りにすれば良い。いくつか変更した点をば。

  • SNATの部分は、sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.111.0/24 -j MASQUERADEとして、sオプションを明示的にしるしたほうが良さそう。

  • client側のPCのデフォルトゲートウェイを変更する。つまり、

Vagrantfile
Vagrant.configure("2") do |config|
  # snip
  config.vm.define "client" do |conf|
    conf.vm.box = "ubuntu/trusty64"
    conf.vm.network "private_network", ip: "192.168.111.100", virtualbox__intnet: "mynet"
    conf.vm.synced_folder "../eth", "/home/vagrant/test"
    # see also https://www.vagrantup.com/docs/networking/public_network.html#default-router
    gw = "192.168.111.2"
    conf.vm.provision "shell",
      run: "always",
      inline: "route add default gw #{gw}"

    conf.vm.provision "shell",
      run: "always",
      inline: "eval `route -n | awk '{ if ($8 ==\"eth0\" && $2 != \"0.0.0.0\") print \"route del default gw \" $2; }'`"
  end
  # snip
end

と変更する。

Note) route add default gw ...とかはVMの再起動時に情報失われるので、run: "always"としている。


以上のように設定すると、clientでのping 8.8.8.8がgatewayの192.168.111.2を経由して通る。traceroute 8.8.8.8で確認すると、

traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  192.168.111.2 (192.168.111.2)  0.278 ms  0.209 ms  0.168 ms
 2  * * *
 3  * * *
 4  ... プロバイダのipアドレス
 ...
 11  google-public-dns-a.google.com (8.8.8.8)  18.878 ms  19.249 ms  12.319 ms

みたいな感じになる。5

Note)

2,3が* * *は、本当は、

 2  10.0.2.2 (10.0.2.2)  0.217 ms  0.178 ms  0.058 ms
 3  ルータ名 (192.168.10.221)  2.500 ms  2.952 ms  3.110 ms

みたいな感じなんだけど、フォワードの方向しかping許していないので、アスタリスク表示になる。

確認取れたので、

/MyEth.ini
IP-TTL=64
device=eth1
# `ip a`でeth1インタフェースを確認して所用のMACアドレスに変更する。
vmac=08:00:27:e0:6a:24
vip=192.168.111.100
vmask=255.255.255.0
gateway=192.168.111.2

でプログラムを動かすと良い。

第3章: UDP通信に対応させ、DHCPクライアント機能を実装しよう

これは、素直に

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  # If err, see also the issue #3083, https://github.com/hashicorp/vagrant/issues/3083
  config.vm.network :private_network, type: "dhcp", ip: "192.168.111.0"
  config.vm.synced_folder ".", "/home/vagrant/test"
end

で良いと思う6

sudo grep -R "DHCPOFFER" /var/log/*

すると、DHCP serverの在り処が192.168.111.2とわかる。
ホストOSでifconfigとすると、192.168.111.1となっているのがわかる。

macOSX
$ ifconfig
vboxnet0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    ether 0a:00:27:00:00:00
    inet 192.168.111.1 netmask 0xffffff00 broadcast 192.168.111.255

ゲストOSのデフォルトゲートウェイはrouteで確認すると、10.0.2.2となっている。

TODO) 今回は必要なかったが、ついでにDHCPサーバーを自力で構成するのもやってみたい

第4章: TCPの基本機能を追加しよう

これは、第2章のネットワーク構成と全く同じなので、そのままでよさそう。

感想

そもそも、ネットワーク自体しっかり理解していない部分も多かったので、結構時間がかかってしまったが、結果的には、自力でのネットワーク構築、nat, iptablesとかがわかって得るものが多いと感じた。


  1. http://gihyo.jp/book/2018/978-4-7741-9744-9/support#supportDownload にある 

  2. traceroute 8.8.8.8で詳細を確かめられる 

  3. この後、natネットワークのルータ10.0.2.2を経由する。その後、ホストOS(MAC OS X)の "en0: Wi-Fi (AirPort)"のネットワークのルータを経由する。 

  4. virtualbox__intnetなしだと、clientのネットワークがhostonly networkになるので、ホストOS(macOS X)からifconfigすると、vboxnetのネットワークインターフェースがあらわれると思います。 

  5. todo: iptablesの設定を変更すれば良さそう 

  6. 自分は途中で、A host only network interface you're attempting to configure via DHCPの文言のエラーが出てしまったので、https://github.com/hashicorp/vagrant/issues/3083 みて解決した 

7
7
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
7
7