前回、VyOSのrolling releaseのvagrant boxを作りました。
今回はこれを使って、VyOSで色々やってみたいと思います。
目次
普通のルータ
構成はこんな感じです。
vagrantでサクッと環境を作ります。Vagrantfileはこんな感じ。
Vagrant.configure("2") do |config| config.vagrant.plugins = ["vagrant-vyos"] config.vm.define "vyos" do |c| c.vm.hostname = "vyos" c.vm.box = "kun432/vyos" c.vm.network "private_network", ip: "172.16.0.10" c.vm.network "private_network", ip: "192.168.0.10" end config.vm.define "webserver" do |c| c.vm.hostname = "webserver" c.vm.box = "centos/7" c.vm.network "private_network", ip: "172.16.0.5" c.vm.provider "virtualbox" do |v| v.gui = false v.cpus = 1 v.memory = 512 end c.vm.provision :shell, :inline => <<-EOT yum install -y httpd curl tcpdump wireshark systemctl enable httpd systemctl start httpd echo Hello > /var/www/html/index.html EOT c.vm.provision :shell, :run => "always", :inline => <<-EOT ip route delete default via 10.0.2.2 EOT end (1..2).each do |n| config.vm.define "client-#{n}" do |c| c.vm.box = "centos/7" c.vm.hostname = "client-#{n}" c.vm.network "private_network", ip: "192.168.0.2#{n}" c.vm.provider "virtualbox" do |v| v.gui = false v.cpus = 1 v.memory = 512 end c.vm.provision :shell, :inline => <<-EOT yum install -y httpd curl tcpdump wireshark EOT c.vm.provision :shell, :run => "always", :inline => <<-EOT ip route delete default via 10.0.2.2 EOT end end end
ちなみに、vagrantの場合、デフォルトでNATインタフェース(10.0.2.15)が作成され、デフォルトゲートウェイはホストマシン(10.0.2.2)に向きます。経路がない通信はすべてホストマシンに向くのですが、経路がないプライベートネットワークへもこちらを抜けてホストマシン経由で疎通ができてしまいます。なので起動時にデフォルトルートを削除しています。
vagrant upします。
$ vagrant up
clientからwebserverへの疎通を確認します。
[vagrant@client-1 ~]$ ping -c 3 172.16.0.5 connect: ネットワークに届きません
clientは172.16.0.0/24への経路を知らないので当然ですね。
[vagrant@client-1 ~]$ ip route 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100 192.168.0.0/24 dev eth1 proto kernel scope link src 192.168.0.21 metric 101
webserverからも同じです。
[vagrant@webserver ~]$ ping -c 3 192.168.0.21 connect: ネットワークに届きません [vagrant@webserver ~]$ ip route 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 101 172.16.0.0/24 dev eth1 proto kernel scope link src 172.16.0.5 metric 100
client-1/2にデフォルトルートを追加しましょう。vyosに向けます。
[vagrant@client-1 ~]$ sudo ip route add default via 192.168.0.10
webserverにもデフォルトルートを追加しましょう。こちらもvyosに向けます。
[vagrant@client-1 ~]$ sudo ip route add default via 172.16.0.10
clientからwebserverにpingが通るようになりました。
[vagrant@client-1 ~]$ ping -c 3 172.16.0.5 PING 172.16.0.5 (172.16.0.5) 56(84) bytes of data. 64 bytes from 172.16.0.5: icmp_seq=1 ttl=63 time=0.875 ms 64 bytes from 172.16.0.5: icmp_seq=2 ttl=63 time=1.06 ms 64 bytes from 172.16.0.5: icmp_seq=3 ttl=63 time=0.907 ms --- 172.16.0.5 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 0.875/0.948/1.063/0.085 ms
逆も同じですね。
[vagrant@webserver ~]$ ping -c 3 192.168.0.21 PING 192.168.0.21 (192.168.0.21) 56(84) bytes of data. 64 bytes from 192.168.0.21: icmp_seq=1 ttl=63 time=0.911 ms 64 bytes from 192.168.0.21: icmp_seq=2 ttl=63 time=1.28 ms 64 bytes from 192.168.0.21: icmp_seq=3 ttl=63 time=0.868 ms --- 192.168.0.21 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2004ms rtt min/avg/max/mdev = 0.868/1.019/1.280/0.188 ms
vyosの設定を見てみましょう。
vagrant@vyos:~$ show configuration
interfaces { ethernet eth0 { address dhcp hw-id 08:00:27:71:88:48 } ethernet eth1 { address 172.16.0.10/24 } ethernet eth2 { address 192.168.0.10/24 } loopback lo { } } service { ssh { } } system { config-management { commit-revisions 100 } host-name vyos login { user vagrant { authentication { encrypted-password **************** public-keys vagrant { key **************** type ssh-rsa } } } user vyos { authentication { encrypted-password **************** plaintext-password **************** } } } name-servers-dhcp eth0 ntp { server 0.pool.ntp.org { } server 1.pool.ntp.org { } server 2.pool.ntp.org { } } syslog { global { facility all { level info } facility protocols { level debug } } } }
これがデフォルトの設定です。vyosで/proc/sys/net/ipv4/ip_forwardを見てみると、パケット転送が有効になっているのでルータとして動作しているわけですね。
vagrant@vyos:~$ cat /proc/sys/net/ipv4/ip_forward 1
もう一つ。webserverではapacheを動作させています。clientからwebserverへHTTPでアクセスしてみます。webserverでapacheのログをtail -fで流しながら・・・
[vagrant@webserver ~]$ sudo tail -f /var/log/httpd/access_log
clientからアクセスします。
[vagrant@client-1 ~]$ curl http://172.16.0.5/index.html Hello
[vagrant@client-2 ~]$ curl http://172.16.0.5/index.html Hello
ログが流れてますね。
192.168.0.21 - - [03/Nov/2020:13:08:56 +0000] "GET /index.html HTTP/1.1" 200 6 "-" "curl/7.29.0" 192.168.0.22 - - [03/Nov/2020:13:08:59 +0000] "GET /index.html HTTP/1.1" 200 6 "-" "curl/7.29.0"
見てわかるようにclient-1/2のそれぞれのIPが出ていますね。単純なルーティングのみなので、clinet-1/2それぞれが見えています。
IPマスカレード
ブロードバンドルータっぽく、中から外ヘはIPマスカレードを使うように設定してみましょう。
vagrant@vyos:~$ config [edit] vagrant@vyos# set nat source rule 99 translation address masquerade [edit] vagrant@vyos# set nat source rule 99 source address 192.168.0.0/24 [edit] vagrant@vyos# set nat source rule 99 outbound-interface eth1 [edit] vagrant@vyos# show nat +source { + rule 99 { + outbound-interface eth1 + source { + address 192.168.0.0/24 + } + translation { + address masquerade + } + } +} [edit] vagrant@vyos# commit [edit] vagrant@vyos# save Saving configuration to '/config/config.boot'... Done [edit]
client側ネットワーク(192.168.0.0/24)からwebserver側ネットワークのインタフェース(eth1)を抜けていくところでIPマスカレードを有効にしました。
再度クライアント2台からwebserverにHTTPでアクセスしてみます。
[vagrant@client-1 ~]$ curl http://172.16.0.5/index.html Hello
[vagrant@client-2 ~]$ curl http://172.16.0.5/index.html Hello
apacheのログはこうなります。
172.16.0.10 - - [03/Nov/2020:13:23:15 +0000] "GET /index.html HTTP/1.1" 200 6 "-" "curl/7.29.0" 172.16.0.10 - - [03/Nov/2020:13:23:18 +0000] "GET /index.html HTTP/1.1" 200 6 "-" "curl/7.29.0"
IPマスカレードしているので、接続元IPアドレスはvyosのeth1のIPになりますね。
再度webserver側のルーティングを見てみましょう。
[vagrant@webserver ~]$ ip route default via 172.16.0.10 dev eth1 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 101 172.16.0.0/24 dev eth1 proto kernel scope link src 172.16.0.5 metric 100
apacheに接続に来ていたIPアドレスは、webserverのネットワークと同じです。ということは、デフォルトルートでvyosに向けているルーティング設定は不要ですね。
[vagrant@webserver ~]$ sudo ip route delete default via 172.16.0.10
IPマスカレードの動作も見てみましょう。webserver側でパケットキャプチャします。
[vagrant@webserver ~]$ sudo tcpdump -i eth1 -t -n port 80 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
client側からncでアクセスします。このまま繋ぎっぱなしにしておきます。
[vagrant@client-1 ~]$ nc 172.16.0.5 80
パケットキャプチャを見ると、vyosのポート60254から接続が来ていますね。
IP 172.16.0.10.60254 > 172.16.0.5.http: Flags [S], seq 379868689, win 29200, options [mss 1460,sackOK,TS val 7021583 ecr 0,nop,wscale 6], length 0 IP 172.16.0.5.http > 172.16.0.10.60254: Flags [S.], seq 1024265950, ack 379868690, win 28960, options [mss 1460,sackOK,TS val 4223987 ecr 7021583,nop,wscale 6], length 0 IP 172.16.0.10.60254 > 172.16.0.5.http: Flags [.], ack 1, win 457, options [nop,nop,TS val 7021586 ecr 4223987], length 0
vyos上でconntrackテーブルの状態を見ると、ポート番号はそのままでIPアドレスが書き換えられてwebserverにアクセスしているのがわかりますね。
vagrant@vyos:~$ show conntrack table ipv4 TCP state codes: SS - SYN SENT, SR - SYN RECEIVED, ES - ESTABLISHED, FW - FIN WAIT, CW - CLOSE WAIT, LA - LAST ACK, TW - TIME WAIT, CL - CLOSE, LI - LISTEN CONN ID Source Destination Protocol TIMEOUT (snip) 3948837384 192.168.0.21:60254 172.16.0.5:80 tcp [6] ES 431993
もう一つクライアントからアクセスしてみます。
[vagrant@client-2 ~]$ nc 172.16.0.5 80
今度はポート44516からの接続になっています。
IP 172.16.0.10.44516 > 172.16.0.5.http: Flags [S], seq 1819970686, win 29200, options [mss 1460,sackOK,TS val 6728037 ecr 0,nop,wscale 6], length 0 IP 172.16.0.5.http > 172.16.0.10.44516: Flags [S.], seq 4195455960, ack 1819970687, win 28960, options [mss 1460,sackOK,TS val 4272447 ecr 6728037,nop,wscale 6], length 0 IP 172.16.0.10.44516 > 172.16.0.5.http: Flags [.], ack 1, win 457, options [nop,nop,TS val 6728038 ecr 4272447], length 0
vyos上のconntrackテーブルでも、client-2はポート44516を使っていますね。おそらくvyos上でポートがあいていればclientからのポートをそのまま使うのだと思います。
vagrant@vyos:~$ show conntrack table ipv4 TCP state codes: SS - SYN SENT, SR - SYN RECEIVED, ES - ESTABLISHED, FW - FIN WAIT, CW - CLOSE WAIT, LA - LAST ACK, TW - TIME WAIT, CL - CLOSE, LI - LISTEN CONN ID Source Destination Protocol TIMEOUT (snip) 3812069659 192.168.0.22:44516 172.16.0.5:80 tcp [6] ES 431993 (snip) 3948837384 192.168.0.21:60254 172.16.0.5:80 tcp [6] CW 57
ではclient-1/2が同じポートで接続してきたときはどうなるかやってみましょう。ポート番号の解決をしないように-nnをつけてキャプチャします。
[vagrant@webserver ~]$ sudo tcpdump -t -nn -i eth1 tcp port 80
client-1から接続元ポートに30000を指定して、ncで接続したままにしておきます。
[vagrant@client-1 ~]$ nc -p 30000 172.16.0.5 80
webserver側ではポート30000で接続に来ています。
IP 172.16.0.10.30000 > 172.16.0.5.80: Flags [S], seq 348967703, win 29200, options [mss 1460,sackOK,TS val 8512851 ecr 0,nop,wscale 6], length 0 IP 172.16.0.5.80 > 172.16.0.10.30000: Flags [S.], seq 1102876751, ack 348967704, win 28960, options [mss 1460,sackOK,TS val 5715245 ecr 8512851,nop,wscale 6], length 0 IP 172.16.0.10.30000 > 172.16.0.5.80: Flags [.], ack 1, win 457, options [nop,nop,TS val 8512853 ecr 5715245], length 0
vyos上でもclient-1はポート30000ですね。
vagrant@vyos:~$ show conntrack table ipv4 (snip) CONN ID Source Destination Protocol TIMEOUT (snip) 3152290531 192.168.0.21:30000 172.16.0.5:80 tcp [6] ES 431995
client-2からも同様に接続元ポートに30000を指定して、ncを実行します。
[vagrant@client-2 ~]$ nc -p 30000 172.16.0.5 80
webserver側ではポート番号が違いますね。今回は1026になっています。
IP 172.16.0.10.1026 > 172.16.0.5.80: Flags [S], seq 3554536492, win 29200, options [mss 1460,sackOK,TS val 8177731 ecr 0,nop,wscale 6], length 0 IP 172.16.0.5.80 > 172.16.0.10.1026: Flags [S.], seq 974909399, ack 3554536493, win 28960, options [mss 1460,sackOK,TS val 5722138 ecr 8177731,nop,wscale 6], length 0 IP 172.16.0.10.1026 > 172.16.0.5.80: Flags [.], ack 1, win 457, options [nop,nop,TS val 8177733 ecr 5722138], length 0
vyos上でみると、client-2からも30000で接続を受けていますが、ポートが空いていない場合は書き換わるということですね。
vagrant@vyos:~$ show conntrack table ipv4 (snip) CONN ID Source Destination Protocol TIMEOUT (snip) 3152290531 192.168.0.21:30000 172.16.0.5:80 tcp [6] ES 431990 2513951838 192.168.0.22:30000 172.16.0.5:80 tcp [6] ES 431996
冗長化
vyosではActive/Standby構成による冗長化も行えます。こういう構成にします。
IPアドレスなどもちょっと変わりますので、一旦vyosだけ削除しましょう。
$ vagrant destroy vyos -f
削除したら、Vagrantfileの以下の部分を書き換えます。
config.vm.define "vyos" do |c| c.vm.hostname = "vyos" c.vm.box = "kun432/vyos" c.vm.network "private_network", ip: "172.16.0.10" c.vm.network "private_network", ip: "192.168.0.10" end
こういうふうに2台立ち上がる設定にします。
(1..2).each do |n| config.vm.define "vyos-#{n}" do |c| c.vm.hostname = "vyos-#{n}" c.vm.box = "kun432/vyos" c.vm.network "private_network", ip: "172.16.0.1#{n}" c.vm.network "private_network", ip: "192.168.0.1#{n}" end end
2台あげましょう
$ vagrant up vyos-{1,2}
それぞれログインします。
$ vagrant ssh vyos-1
$ vagrant ssh vyos-2
ここからは2台ともに同じコマンドを実行していきます。まず最初のNATの設定を入れましょう。
vagrant@vyos:~$ config vagrant@vyos# set nat source rule 99 translation address masquerade vagrant@vyos# set nat source rule 99 source address 192.168.0.0/24 vagrant@vyos# set nat source rule 99 outbound-interface eth1 vagrant@vyos# commit vagrant@vyos# save
ではクラスタの設定です。configモードに移ります。
vagrant@vyos:~$ config
最初にクラスタで冗長化するインタフェースを指定します。
vagrant@vyos# set cluster interface eth1 vagrant@vyos# set cluster interface eth2
次にクラスタ間のハートビートの設定を行います。keepalive-interval がお互いがUPの場合にチェックを行う間隔、dead-intervalが片方がDOWNした場合のチェックを行う間隔です。pre-shared-secretは両系で同じに設定します。
vagrant@vyos# set cluster keepalive-interval 200 vagrant@vyos# set cluster dead-interval 1000 vagrant@vyos# set cluster pre-shared-secret password
クラスタに所属するグループの設定です。primary/secondaryがActive/Standbyの設定です。auto-failbackをtrueにすると、クラスタがstandby側に切り替わったあとactive側が復旧した場合に自動で切り替わります。servceがVIPの設定ですね。
vagrant@vyos# set cluster group VyOS-Cluster vagrant@vyos# set cluster group VyOS-Cluster auto-failback false vagrant@vyos# set cluster group VyOS-Cluster primary vyos-1 vagrant@vyos# set cluster group VyOS-Cluster secondary vyos-2 vagrant@vyos# set cluster group VyOS-Cluster service 172.16.0.10/24/eth1 vagrant@vyos# set cluster group VyOS-Cluster service 192.168.0.10/24/eth2
commitするとクラスタが有効化されます。saveもお忘れなく。
vagrant@vyos-1# commit [ cluster ] Stopping clustering... Done Starting clustering... Done [edit] vagrant@vyos-1# save Saving configuration to '/config/config.boot'... Done [edit]
ではクラスタ状態を見てみましょう。1系から。
vagrant@vyos-1:~$ show cluster status === Status report on primary node vyos-1 === Primary vyos-1 (this node): Active Secondary vyos-2: Active (standby) Resources [172.16.0.10/24/eth1 192.168.0.10/24/eth2]: Active on primary vyos-1 (this node)
ちゃんとクラスタとして動いていて、1系がActiveになってますね。インタフェースを見てみましょう。
(snip) 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:8d:00:a2 brd ff:ff:ff:ff:ff:ff inet 172.16.0.11/24 brd 172.16.0.255 scope global eth1 valid_lft forever preferred_lft forever inet 172.16.0.10/24 brd 172.16.0.255 scope global secondary eth1 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe8d:a2/64 scope link valid_lft forever preferred_lft forever 4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:41:0d:10 brd ff:ff:ff:ff:ff:ff inet 192.168.0.11/24 brd 192.168.0.255 scope global eth2 valid_lft forever preferred_lft forever inet 192.168.0.10/24 brd 192.168.0.255 scope global secondary eth2 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe41:d10/64 scope link valid_lft forever preferred_lft forever (snip)
VIPがeth1/2それぞれで上がっていますね。
次に2系。
vagrant@vyos-2:~$ show cluster status === Status report on secondary node vyos-2 === Primary vyos-1: Active Secondary vyos-2 (this node): Active (standby) Resources [172.16.0.10/24/eth1 192.168.0.10/24/eth2]: Active on primary vyos-1
2系はstandbyですね。もちろんこちらにはVIPは上がっていません。
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:2d:dc:17 brd ff:ff:ff:ff:ff:ff inet 172.16.0.12/24 brd 172.16.0.255 scope global eth1 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe2d:dc17/64 scope link valid_lft forever preferred_lft forever 4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:5b:4d:f8 brd ff:ff:ff:ff:ff:ff inet 192.168.0.12/24 brd 192.168.0.255 scope global eth2 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe5b:4df8/64 scope link valid_lft forever preferred_lft forever
それでは、クラスタが切り替わっても動作することを確認してみましょう。VIPで使っている..*.10はwebserver/clientそれぞれのデフォルトルートで指定していました。webserverとclientで事前にarpを見てみます。
[vagrant@webserver ~]$ ip neigh 172.16.0.10 dev eth1 lladdr 08:00:27:8d:00:a2 STALE 172.16.0.11 dev eth1 lladdr 08:00:27:8d:00:a2 STALE
[vagrant@client-1 ~]$ ip neigh 192.168.0.10 dev eth1 lladdr 08:00:27:41:0d:10 STALE 192.168.0.11 dev eth1 lladdr 08:00:27:41:0d:10 STALE
両方とも1系を見ています。
では切り替えましょう。force cluster active/standbyでクラスタを切り替えることができます。2系がActになるようにしてみましょう。
vagrant@vyos-2:~$ force cluster active Requesting to take over cluster resources
クラスタ状態を見てみます。
vagrant@vyos-2:~$ show cluster status === Status report on secondary node vyos-2 === Primary vyos-1: Active (standby) Secondary vyos-2 (this node): Active Resources [172.16.0.10/24/eth1 192.168.0.10/24/eth2]: Active on secondary vyos-2 (this node)
vagrant@vyos-1:~$ show cluster status === Status report on primary node vyos-1 === Primary vyos-1 (this node): Active (standby) Secondary vyos-2: Active Resources [172.16.0.10/24/eth1 192.168.0.10/24/eth2]: Active on secondary vyos-2
2系がActiveに切り替わりました。VIPも2系で上がっています。
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:2d:dc:17 brd ff:ff:ff:ff:ff:ff inet 172.16.0.12/24 brd 172.16.0.255 scope global eth1 valid_lft forever preferred_lft forever inet 172.16.0.10/24 brd 172.16.0.255 scope global secondary eth1 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe2d:dc17/64 scope link valid_lft forever preferred_lft forever 4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:5b:4d:f8 brd ff:ff:ff:ff:ff:ff inet 192.168.0.12/24 brd 192.168.0.255 scope global eth2 valid_lft forever preferred_lft forever inet 192.168.0.10/24 brd 192.168.0.255 scope global secondary eth2 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe5b:4df8/64 scope link valid_lft forever preferred_lft forever
arpも確認してみます。
[vagrant@webserver ~]$ ip neigh 172.16.0.10 dev eth1 lladdr 08:00:27:2d:dc:17 STALE 172.16.0.11 dev eth1 lladdr 08:00:27:8d:00:a2 STALE 172.16.0.12 dev eth1 lladdr 08:00:27:2d:dc:17 REACHABLE
[vagrant@client-1 ~]$ ip neigh 192.168.0.10 dev eth1 lladdr 08:00:27:5b:4d:f8 STALE 192.168.0.11 dev eth1 lladdr 08:00:27:41:0d:10 STALE 192.168.0.12 dev eth1 lladdr 08:00:27:5b:4d:f8 STALE
VIPに紐付いているMACアドレスが更新されて2系と同じになっていますね!
次回
- conntrack-syncを使ったクラスタ間のconntrackテーブルの同期
- DNAT+ファイアウォールルールで外部→内部へのアクセス