Vagrantで仮想的なWANみたいなのを作る
研究の検証用環境として以下のような環境をVMのみで一つのホストPC上に構築したかった. Vagrantで一応できたので手順とかをメモしておく.
ストーリー
それぞれ 192.168.10.100 (Node A) と 172.168.10.100 (Node B) のVMはネットワークのセグメントが異なるので直接アクセスできない. Node AがNode Bにアクセスしたい場合はNode BのGlobal IPを指定してアクセスするようにさせる.
Node Aは100.100.100.100にNATで変換され,Node Bは100.100.100.200に変更されるとする.
Node AがNode BのGlobal IPである100.100.100.200にパケットを投げるとデフォルトゲートウェイを介してRouter VMに届き,Router VMがiptablesを用いてパケットの送信元,宛先IPを変換することでNode Bにパケットを転送したい.
Vagrantfile
まず各VMの設定をVagrantfileに書いておく
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| # The most common configuration options are documented and commented below. # For a complete reference, please see the online documentation at # https://docs.vagrantup.com. # Every Vagrant development environment requires a box. You can search for # boxes at https://vagrantcloud.com/search. config.vm.box = "bento/ubuntu-18.04" # Network A config.vm.define :proxyA do |proxyA| proxyA.vm.hostname = "proxyA" proxyA.vm.network :private_network, ip: "192.168.10.100", virtual__intnet: "intnetA" end config.vm.define :peerA do |peerA| peerA.vm.hostname = "peerA" peerA.vm.network :private_network, ip: "192.168.10.101", virtual__intnet: "intnetA" end # Internal router config.vm.define "router" do |router| router.vm.hostname = "router" router.vm.network :private_network, ip: "192.168.10.10", virtua__intnet: "intnetA" router.vm.network :private_network, ip: "172.168.10.10", virtua__intnet: "intnetB" end # Network B config.vm.define :proxyB do |proxyB| proxyB.vm.hostname = "proxyB" proxyB.vm.network :private_network, ip: "172.168.10.100", virtual__intnet: "intnetB" end config.vm.define :peerB do |peerB| peerB.vm.hostname = "peerB" peerB.vm.network :private_network, ip: "172.168.10.101", virtual__intnet: "intnetB" end end
名前は変わっているが Proxy A, Proxy BがそれぞれNode A, Node Bにあたる. 今回はPeer* のマシンは関係ないので無視
各Nodeでデフォルトゲートウェイを設定
VMを立ち上げたら vagrant ssh
で各NodeのVMにログインしてデフォルトゲートウェイを設定しておく
# Node A sudo route add default gw 192.168.10.10 dev eth1 # Node B sudo route add default gw 172.168.10.10 dev eth1
各NodeのVMには上記のVagrantfileで割り当てた静的なIPがeth1に割り当てられているはずなのでそれに合わせてデフォルトゲートウェイを設定する
設定した後に 各NodeのVMから ping 100.100.100.200
のような存在しない,アクセスできないはずのアドレスにpingを打ち,
Router側で sudo tcpdump -i any icmp
と叩くことで各VMからのpingを観測できるはず
Router VM上でiptablesを設定する
まずパケットの転送を許可する設定を行う
vi /etc/sysctl.conf
でファイルを開き
#net.ipv4.ip_forward=1
のコメントアウトを外す. その後に sudo sysctl -p
で有効化する.これでVMを再起動してもパケットの転送設定はOnのまま
次に iptables に変換テーブルを追加する
sudo iptables -t nat -A PREROUTING -d 100.100.100.200 -i eth1 -j DNAT --to-destination 172.168.10.100 sudo iptables -t nat -A POSTROUTING -o eth1 -s 192.168.10.100 -j MASQUERADE sudo iptables -t nat -A PREROUTING -d 100.100.100.100 -i eth2 -j DNAT --to-destination 192.168.10.100 sudo iptables -t nat -A POSTROUTING -o eth2 -s 172.168.10.100 -j MASQUERADE
1行目はeth1に流れてくる100.100.100.200が宛先となっているパケットを172.168.10.100に変換する. 2行目はNode Aへの返信のパケットを逆変換して届けるための設定 3, 4行目はそれぞれNode Bからのパケット用に書き換えたもの.
これで上記の図のパケット転送がうまくいくはず