ip link add dev mgmt0 type vrf table 10
ip link set dev mgmt0 up
ip link set dev eth3 master mgmt0
ip link set dev eth3 up
ip route add default via 192.168.1.1 table 10
ip route add ::/0 via 2001:470:fe36:1::1 table 10
ip link add dev lb0 type vrf table 4
ip link set dev lb0 up
ip link set dev eth4 master lb0
ip link set dev eth4 up
ip route add default via 192.168.202.1 table 4
route delete default
route delete default
route delete default
route add default gw 192.168.22.1
route delete -host 192.168.1.1
route delete -host 192.168.202.1
ip route del ::/0 via 2001:470:fe36:1::1
ip route del ::/0 via 2001:470:fe36:face::1
ip route del 2001:470:fe36:1::1/64
route -6 add default gw 2001:470:fe36:face::1
sysctl -w net.ipv4.tcp_l3mdev_accept=1
sysctl -w net.ipv4.udp_l3mdev_accept=1
$ ip route show
default via 192.168.22.1 dev eth0
192.168.22.0/24 dev eth0 proto kernel scope link src 192.168.22.218 metric 100
192.168.52.0/24 dev eth1 proto kernel scope link src 192.168.52.218 metric 101
192.168.111.0/24 dev eth2 proto kernel scope link src 192.168.111.218 metric 102
$ ip route show table 10
default via 192.168.1.1 dev eth3
broadcast 192.168.1.0 dev eth3 proto kernel scope link src 192.168.1.218
local 192.168.1.218 dev eth3 proto kernel scope host src 192.168.1.218
broadcast 192.168.1.255 dev eth3 proto kernel scope link src 192.168.1.218
$ ip route show table 4
default via 192.168.202.1 dev eth4
broadcast 192.168.202.0 dev eth4 proto kernel scope link src 192.168.202.218
local 192.168.202.218 dev eth4 proto kernel scope host src 192.168.202.218
broadcast 192.168.202.255 dev eth4 proto kernel scope link src 192.168.202.218
$ ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2001:470:fe36:111::/64 dev eth2 proto kernel metric 102 pref medium
2001:470:fe36:cafe::/64 dev eth1 proto kernel metric 101 pref medium
2001:470:fe36:face::/64 dev eth0 proto kernel metric 100 pref medium
fe80::/64 dev eth0 proto kernel metric 1024 pref medium
fe80::/64 dev eth1 proto kernel metric 1024 pref medium
fe80::/64 dev eth2 proto kernel metric 1024 pref medium
fe80::/64 dev eth3 proto kernel metric 1024 pref medium
default via 2001:470:fe36:face::1 dev eth0 metric 1 pref medium
$ ip -6 route show table 10
anycast 2001:470:fe36:1:: dev eth3 proto kernel metric 0 pref medium
local 2001:470:fe36:1::218:1 dev eth3 proto kernel metric 0 pref medium
anycast fe80:: dev eth3 proto kernel metric 0 pref medium
local fe80::8785:99b6:f03b:cf5e dev eth3 proto kernel metric 0 pref medium
multicast ff00::/8 dev eth3 proto kernel metric 256 pref medium
default via 2001:470:fe36:1::1 dev eth3 metric 1024 pref medium
$ ip -d link show type vrf
7: mgmt0: mtu 65575 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 56:64:d2:f2:ee:55 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 1280 maxmtu 65575
vrf table 10 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
8: lb0: mtu 65575 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 2e:68:9e:22:5f:0e brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 1280 maxmtu 65575
vrf table 4 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
VRF しているインターフェースのルーティング情報が乗っていると削除して、正しいルーティング情報に直すので roure del したり route add しています。上記になっているのが、僕は一番美しいルーティングテーブルだと思っているのであります。
この辺り、nmcli だとちゃんとやってくれるのかなぁ?
$ traceroute -n 192.168.1.217
traceroute to 192.168.1.217 (192.168.1.217), 30 hops max, 60 byte packets
1 192.168.22.1 0.416 ms 0.460 ms 0.456 ms
2 192.168.1.217 0.659 ms 0.654 ms *
$ ip vrf exec mgmt0 traceroute -n 192.168.1.217
traceroute to 192.168.1.217 (192.168.1.217), 30 hops max, 60 byte packets
1 192.168.1.1 0.405 ms 0.323 ms 0.324 ms
2 192.168.1.217 0.665 ms 0.668 ms 0.687 ms
$ ip vrf exec mgmt0 ssh 192.168.1.217
>
# ip link set dev br0 up
# ip link set dev eth0 promisc on
# ip link set dev eth0 up
# ip link set dev eth0 master br0
# ifconfig eth0 0.0.0.0 up
# ifconfig eth0 inet6 del 2001:470:fe36:face::218:1/64 up
# route add default gw 192.168.22.1 dev br0
# ip route del ::/0 via 2001:470:fe36:face::1
# route -6 add default gw 2001:470:fe36:face::1 dev br0
上から順に説明すると、
docker network create で生成した br0 を UP します
eth0 のプロミスキャス・モードを有効化します
eth0 を UP します
eth0 と br0 をブリッジ化します
br0 に IPv4/IPv6 アドレスが付加されるので eth0 側から削除します
最後にルーティング情報を設定します
こんな感じでしょうか。
ロードバランサセグメント用の設定も書いておきます。
# docker network create LB-Segment \
-o "com.docker.network.bridge.name"="br4" \
--driver=bridge \
--subnet 192.168.202.0/24 \
--gateway 192.168.202.218
# ip link set dev br4 up
# ip link set dev eth4 promisc on
# ip link set dev eth4 up
# ip link set dev eth4 master br4
# ifconfig eth4 0.0.0.0 up
# ip link set dev lb0 up
# ip link set dev br4 master lb0
# ip link set dev br4 up
# ip route add default via 192.168.202.1 table 4
# ip link set eth0 promisc off
# ip link set eth0 down
# ip link set dev eth0 nomaster
# ip link delete br0 type bridge
# docker network rm Service-Segment
# ifconfig eth0 192.168.22.218/24
# ifconfig eth0 inet6 add 2001:470:fe36:face::218:1/64
# route add default gw 192.168.22.1 dev eth0
# ip route del ::/0 via 2001:470:fe36:face::1
# route -6 add default gw 2001:470:fe36:face::1 dev eth0
# ping -q -c 3 192.168.22.1 > /dev/null 2>&1
3. IPv4/IPv6 デアルスタク対応コンテナの起動
最後に Docker コンテナの使い方について書いておきます。何回も書いている通り bridge-utils を捨てて ip link set dev コマンドに移行したので Docker コンテナは IPv4/IPv6 のデアルスタクで動作させられます。
$ docker search almaLinux
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
almalinux The official build of AlmaLinux OS. 102 [OK]
<以下略>
$ docker pull almaLinux
Using default tag: latest
latest: Pulling from library/almalinux
<略>
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
almalinux latest acaca326f3b3 6 weeks ago 190MB
$ docker tag almalinux:latest almalinux8:1
$ docker image rm almalinux:latest
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
almalinux8 1 acaca326f3b3 6 weeks ago 190MB
$ docker run -it --name almalinux8 almalinux:1 /bin/bash
[root@b2db6f534790 /]#
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
039e8158c77b Access-Segment bridge local
622593f73c12 Service-Segment bridge local
9eb6f5610d75 bridge bridge local
d30c681a9f92 host host local
afbbadaba67f none null local
無事に作成できるとこんな感じでしょうか。
ifconfig -a したときには br0 と br1 に IP アドレスが付いていて、eth0 と eth1 には IP アドレスはついていない状態が正解です。
これで Docker ホストとコンテナで同一セグメントを利用する環境が整いました。次にコンテナを run してみましょうかねぇ;-)。
コンテナ内から Docker ホストに対して ping を打つのは、コンテナ起動ごとに MAC アドレスが書き換わるので、上位のルータに対して MAC アドレスの更新をする必要があるためです。ルータ側の MAC アドレス書き換えタイムアウトまで待っても良いですねぇ。根が短気な性分なものでして・・f(^^;;。
これで Service-Segment 側に指定した IP アドレスにウェブブラウザからアクセスすると、WordPress の初期設定画面が表示できると思います。
データベースは MySQL ですが 192.168.52.204 で動作している MySQL サーバへのアクセスは eth1 側を抜けていくので WordPress の初期設定画面で IP アドレス・ユーザ名・パスワードを設定するとアクセスできると思います。
あ。当然、 MySQL 側ではデータベースとアクセス用のアカウントを作成しておいてください。ここでは割愛しています。
ubuntu のネットワーク設定より Red Hat Linux 系のネットワーク設定のほうが楽と、いうか、個人的にも直感的に設定できるような状態ですしね(^^;;。今回は由緒正しく /etc/sysconfig/network-scripts/ 配下のファイルを用意して VRF の設定をしてみたいと思います。
ip link add dev mgmt0 type vrf table 10
ip link set dev mgmt0 up
ip link set dev eth2 master mgmt0
ip addr add dev eth2 192.168.1.217/24
ip link set dev eth2 up
ip route add default via 192.168.1.1 table 10
ip route add ::/0 via 2405:6580:aa40::1 table 10
route delete default
route delete default
route add default gw 192.168.22.1
ip route del ::/0 via 2405:6580:aa40::1
ip route del ::/0 via 2001:470:fe36:face::1
route -6 add default gw 2001:470:fe36:face::1
sysctl -w net.ipv4.tcp_l3mdev_accept=1
sysctl -w net.ipv4.udp_l3mdev_accept=1
# ip route show
default via 192.168.22.1 dev eth0
192.168.1.1 dev eth2 proto static scope link metric 102
192.168.22.0/24 dev eth0 proto kernel scope link src 192.168.22.217
192.168.52.0/24 dev eth1 proto kernel scope link src 192.168.52.217
# ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2405:6580:aa40::/64 dev eth2 proto kernel metric 102 pref medium
2001:470:fe36:face::/64 dev eth0 proto kernel metric 100 pref medium
2001:470:fe36:cafe::/64 dev eth1 proto kernel metric 101 pref medium
# ip route show table 10
default via 192.168.1.1 dev eth2
broadcast 192.168.1.0 dev eth2 proto kernel scope link src 192.168.1.217
local 192.168.1.217 dev eth2 proto kernel scope host src 192.168.1.217
broadcast 192.168.1.255 dev eth2 proto kernel scope link src 192.168.1.217
# ip -6 route show table 10
local 2405:6580:aa40::217:1 dev eth2 proto kernel metric 0 pref medium
local fe80::751c:3cc8:a2c0:2fcb dev eth2 proto kernel metric 0 pref medium
multicast ff00::/8 dev eth2 proto kernel metric 256 pref medium
default via 2405:6580:aa40::1 dev eth2 metric 1024 pref medium
# ip -d link show type vrf
6: mgmt0: mtu 65575 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 12:c4:f9:dc:1f:bf brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 1280 maxmtu 65575
vrf table 10 addrgenmode none numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
Linux 方面では ip route+ip rule でのポリシールーティングの運用となりますが、カーネルのバージョン 4.4 から VRF が利用できる。というので setfib と比較してどれくらい効果的に機能するのか試してみました。
Linux カーネルが 4.4 以上なディストリビューションには何があるのか調べてみると ubuntu-17.04 が対応しているようなので ISO イメージをダウンロードしてインストールし、実際に設定までしてみます。
僕自身 ubuntu はあまり使ったことが無いディストリビューションで Raspberry Pi の Volumio に続き二個目のインストール環境です。仕事でもデスクトップでも使ったことがありません;-)。
NIC が二個あるのでそれぞれの NIC を VRF にしてルーティングテーブルを二つ別々に持たせよう。などと思ってはいけません。
NIC が二個の場合、一個は default のルーティングテーブル(ip [-6] route list で表示されるルーティングテーブル)を参照するようにして、もう一個の NIC は別のルーティングテーブルを持ち、かつ参照する構成が良いです。ここ、ハマリ道というか思い違いの点ですね。
この点については下のほうに詳しく書きます。
では、設定を上から順に見ていきます。
0). /etc/network/interfaces にネットワークの設定のみ書く
lo の他にインターフェース二つ分を書き gateway の設定は書かない
ip link add dev mgmt type vrf table 10
ip link set dev mgmt up
type は vrf で table 番号は 10 を利用しました。複数個の VRF を生成する場合はこの番号を増やしていけば良いです。
4). VRF と NIC の結びつけ
作成した VRF インターフェースと NIC を結びつけます。つまりは、マネージメントポート用の VRF は mgmt として LAN-Zone の NIC と結びつける。と、いうことですね。
ip link set dev ens32 master mgmt up
リモートから ssh で作業していて dev で指定する NIC からアクセスしていた場合、このコマンドを投入した段階でネットワークが切れます。なので反対側の NIC からアクセスして作業するか、コンソールからコマンドを叩く必要があります。
起動時の /etc/rc.local 読み込み時には問題はないんですけどね。
ip route list もしくは ip -6 route list
default のルーティングテーブルを確認すときに利用
ip route list vrf mgmt もしくは ip -6 route list vrf mgmt
設定した VRF の mgmt のルーティングテーブルを確認
その他、インターフェースの確認として ip link や ip addr を利用します。
さて。最初のほうで『二個の NIC に VRF を二個用意してはいけません。』と書いていますが、例えば二個の NIC それぞれで VRF を利用した場合 /etc/resolv.conf を参照しないなど、問題点も多いです。
そりゃそうでしょうなぁ。どっちの NIC から出ていくかわからないですし、リゾルバは正しく動作してくれないんでしょうな。
例えば NIC が ens160 と ens32 の二つがあった場合以下のコマンドを打ったとします。
ip link set dev ens160 master vrf0
ip link set dev ens32 master vrf1
この場合、二つの NIC でそれぞれ個別のルーティングテーブルを持つことになるんですが、
ping -I vrf0 IP アドレス もしくは ping -I vrf1 IP アドレス
では到達性があります。しかし、以下のように pingすると到達性がありません。
ping -I vrf1 FQDN
ルーティングテーブルが VRF のみになると DNS を引きに行ってくれないんですね。なので、 NIC が二個の場合は一個の VRF を設定するのみで、もう一個の NIC は default な ip [-6] route list で表示してくれる経路が必要になります。
二個の NIC で二個の VRF を設定すると netstat -nr や ip route list では何も表示してくれなくなります。
ループバックに IP アドレスとか記載できるのかな? lo:1 とか書けるのかな?そこまで試していませんが。
FreeBSD の場合、 ipfw の fwd でも pf でも、バケットが届いた NIC から出ていく。って設定ができないんですね。
パケットが届いた NIC のゲートウェイアドレスに返す。って設定はできるようなんですけど、その場合はゲートウェイ経由で届いたパケットは送信元に戻っていくけど、同一セグメント上のコネクテッドな送信元には戻っていかない。まいったなぁ・・。
上記の構成図のうち Server1 が Linux (CentOS 6.9) の場合、以下のように /etc/rc.local に書くと良いです。
ip route add 192.168.22.0/24 dev eth0 tab 100
ip route add 2001:470:fe36:beef::/64 dev eth0 tab 110
ip route add 192.168.1.0/24 dev eth1 tab 120
ip route add 3ffe:6580:aa40::/64 dev eth1 tab 130
ip route add default via 192.168.22.1 dev eth0 tab 100
ip route add default via 2001:470:fe36:beef::1 dev eth0 tab 110
ip route add default via 192.168.1.1 dev eth1 tab 120
ip route add default via 3ffe:6580:aa40::ffff:1 dev eth1 tab 130
ip rule add from 192.168.22.10/32 tab 100 priority 1000
ip -6 rule add from 2001:470:fe36:beef::2:1/64 tab 110 priority 1100
ip rule add from 192.168.1.10/32 tab 120 priority 1200
ip -6 rule add from 3ffe:6580:aa40::2:1/64 tab 130 priority 1300
ip route flush cache
pass quick on lo0 all
pass quick on vmx0 all
pass quick on em0 all
#
# NIC vmx0 -> vmx0 (IPv4)
pass out quick on vmx0 from 192.168.22.20 to 192.168.22.1/24
pass in quick on vmx0 reply-to (vmx0 192.168.22.1) from any to 192.168.22.20
pass out on vmx0 route-to vmx0 from 192.168.22.20 to any
#pass out on vmx0 route-to (vmx0 192.168.22.1) from 192.168.22.20 to any
# NIC vmx0 -> vmx0 (IPv6)
pass out quick on vmx0 from 2001:470:fe36:beef::3:1 to 2001:470:fe36:beef::1/64
pass in quick on vmx0 reply-to (vmx0 2001:470:fe36:beef::1) from any to 2001:470:fe36:beef::3:1
#pass out on vmx0 route-to vmx0 from 2001:470:fe36:beef::3:1 to any
pass out on vmx0 route-to (vmx0 2001:470:fe36:beef::1) from 2001:470:fe36:beef::3:1 to any
#
# NIC em0 -> em0 (IPv4)
pass out quick on em0 from 192.168.1.20 to 192.168.1.1/24
pass in quick on em0 reply-to (em0 192.168.1.1) from any to 192.168.1.20
pass out on em0 route-to em0 from 192.168.1.20 to any
#pass out on em0 route-to (em0 192.168.1.1) from 192.168.1.20 to any
# NIC em0 -> em0 (IPv6)
pass out quick on em0 from 3ffe:6580:aa40::3:1 to 3ffe:6580:aa40::ffff:1/64
pass in quick on em0 reply-to (em0 3ffe:6580:aa40::/64) from any to 3ffe:6580:aa40::3:1
pass out on em0 route-to em0 from 3ffe:6580:aa40::3:1 to any
#pass out on em0 route-to (em0 3ffe:6580:aa40::ffff:1) from 3ffe:6580:aa40::3:1 to any
これで FreeBSD の場合は IPv4/IPv6 共にパケットが届いた NIC と出ていく NIC が一緒になるかと思います。グルっと回って反対側の NIC から出ていくことはなくなります。
僕は pf についていまいち解ってないのですが、 pass out on vmx0 route-to のオプションで (NIC Gateway) の設定があるのですが、この場合は vmx0 の 192.168.22.1 なゲートウェイアドレスに転送するよ。って設定ぽいですね。その場合、同一セグメント上の送信元、俗に言う、コネクテッドなホストには届かないんでないの? って気がするので (NIC Gateway) の記述ではなく () をはずして NIC のみを記載しています。
1).コネクテッドなホストと通信ができて、ゲートウェイの先のホストと通信ができない設定
pass out on em0 route-to em0 from 192.168.1.10 to any
pass out on em0 route-to em0 from 2405:6580:aa40::2:1 to any
2).ゲートウェイの先のホストと通信ができて、コネクテッドなホストと通信ができない設定
pass out on em0 route-to (em0 192.168.1.1) from 192.168.1.10 to any
pass out on em0 route-to (em0 3ffe:6580:aa40::ffff:1) from 3ffe:6580:aa40::2:1 to any
オプションに指定する速度に注意でしょうかね。そして Raspberry Pi 2 に電源を投入するとコンソールが流れ始めます。おぉ。無事に使えるねぇ。良かった良かった。なんてのはつかの間。表示されるだけで入力できないじゃーん。 orz
Volumio はシリアルコンソールの設定が完結してないのかい?などと思い、ここから先は、起動した Volumio のシリアルコンソールを有効化していきます。
Volumio は OS に Ubuntu を利用しているので /etc/default/grub 辺りか? などと思い眺めますが x86 アーキテクチャではないのでそんなファイルは無いようです。
ふむ。
コンソールを使うなら /etc/inittab に何かしらの設定が必要だべ。とか思い眺めると『あ。多分のこの辺りを有効にすると行けそうだね。』という行が現れます。この辺りは FreeBSD とかやっていると知らない OS (『そこはかとなく、良く解らない OS』と言ったほうが良いか;-) でもなんとかなります。
# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
上記の上の行をとりあえず 115200 にして設定してみした。
# Example how to put a getty on a serial line (for a terminal)
#
T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
設定完了。今度は kill -HUP 1 してもダメだったので再起動してしてみましょう。
お。コンソールに文字が表示され、おぉ。ログインプロンプトが出てきましたっ!! やった;-)。
これで Volumio でもシリアルコンソールが使えるようになりました。ハンダ当てて改造した甲斐が有りました。
今後はディスプレーも USB キーボードも必要なくなります。一件落着です;-)。
実は Raspberry Pi 2 を購入したあとに FreeBSD/arm と一緒に Volumio も試していたんです。このときはハイレゾに染まっていなかったのでフツーの音楽プレーヤーとして利用していたのですが、 USB の無線 LAN と Bluetooth ドングルが利用できなかったのでお蔵入りしていんですけどもね。