gretap を作る
GRE Tap でイーサネット・フレームを転送するVPNを作ってみたい。
wg0 でL2-VPNはできると思う。
wg に L2-VPN機能がないので、 wg 上に ip bridge で gre tap を構成すればいい。
wireguardではL2はサポートされていなので、WG上にGRETAPでL2転送をかけてみたらいいと思う。ただし、iPhoneのiOSではgreを使えないので、どんな手段を用いてもリモートからGoogle Homeを呼び出しはできないと思う。iphoneでL2TPをするならwigreguardは使えない
もっとかんたんに、L2トンネルを使うのなら、softether や OpenVPNを使うしかない。
GRE tap を体験するために、Linux仮想マシンを作る。
仮想マシンをつくると流石に重いので、LXCを使ってコンテナを使うことにする。
netnsがあるので、netns でやれば良いわけですが。netnsあまり使ってないので、lxc でやります。
docker でやってもいいですが、dockerはデフォルトでネットワークがついてきたり、モジュールがなかったりして面倒なので、フルで仮想マシンとして動作するLXCでやることにしました。
ホスト・マシン
今回、すべての構成をUbuntu/DebianのLXCでやっています。
ホストマシンには、Ubuntu 20.04 を使いました。LXCをインストールして使えるようにしておきます。
sudo snap install lxd sudo lxd init
インストールしたら、ストレージを設定して コンテナが作成できるように設定します。それで準備完了です。
実験する4台の接続
ざっとみて4台いるわけですよ。
m01 と m02 の間をGRETAPで接続します。
c01 から c02 へ GRETAPのトンネル経由で抜けるように作っていきます。
トンネルをどの経路の上に作るかがポイントです。
GRETAPをwg0の上に作ればwireguardをつかったL2とんね、IPSecを使えばIPsec上にL2トンネル。どこの経路で作るかで呼び方は代わると思う。
今回は、単純に ブリッジでm01/m02 を接続して、ブリッジを経由したGREトンネルを作りたいと思う。
詳細な接続
具体的に作るには、複雑な構成になる。
今回作ったネットワーク構成を詳細に書き込むとこんな感じ。
veth0/brige がややこしい。vethでは、veth ペアを作る。verthは両端がペアで作られる。今回は。片方をLXCへ、もう一方をブリッジに入れる。
疎通テスト用にIPも多めに割振ってるのでちょっとややこしい。
ブリッジとvethの接続について
br0 の接続
次のように作った、このbr0 の接続について。
vethを使ってbr0へ
br0 をホスト側に作成、vethペアを2本作成、そしてbr0に突っ込む
veth のペアの一方はLXCへ
verhを作ったら、もう一方をホスト側の制御から外し、LXC制御を渡す。LXC側にアサインしたら、ホスト側からは見えなくなる。
ブリッジは、vethペア作成、LXCのコンテナへ突っ込む、ブリッジへ接続する。この繰り返しで作っていく。
コンテナ間のブリッジbr0/br1/br2
コンテナ間のブリッジは、ホスト側に作るので、ホスト側から見える。
次の図の、br1 はホスト側に存在する。
lxc コンテナ作成・起動
コンテナのネットワークは自分で作っていくので、ネットワークを持たないコンテナを作る。「ネットワークなしコンテナ」を作成すると、LXCから注意が出るが、意図した動作なので、注意は無視しておく。
lxc launch ubuntu:20.04 m01; lxc launch ubuntu:20.04 m02; lxc launch ubuntu:20.04 c01; lxc launch ubuntu:20.04 c02; # lxc restart m01 # lxc restart m02 # lxc restart c01 # lxc restart c02
br0 を作成
sudo ip link add name veth1 type veth peer name veth1-br sudo ip link add name veth2 type veth peer name veth2-br sudo ip link add br0 type bridge sudo ip link set veth1-br master br0 sudo ip link set veth2-br master br0 lxc config device add m01 eth0 nic nictype=physical parent=veth1 lxc config device add m02 eth0 nic nictype=physical parent=veth2
br1 を作成
sudo ip link add name veth10 type veth peer name veth10-br sudo ip link add name veth11 type veth peer name veth11-br lxc config device add m01 eth1 nic nictype=physical parent=veth10 lxc config device add c01 eth0 nic nictype=physical parent=veth11 sudo ip link add br1 type bridge sudo ip link set veth10-br master br1 sudo ip link set veth11-br master br1
br2 を作成
sudo ip link add name veth20 type veth peer name veth20-br sudo ip link add name veth21 type veth peer name veth21-br lxc config device add m02 eth1 nic nictype=physical parent=veth20 lxc config device add c02 eth0 nic nictype=physical parent=veth21 sudo ip link add br2 type bridge sudo ip link set veth20-br master br2 sudo ip link set veth21-br master br2
アドレスをわり付け
sudo ip addr add 10.1.0.254/24 dev br0 lxc exec m01 -- ip addr add 10.1.0.1/24 dev eth0 lxc exec m02 -- ip addr add 10.1.0.2/24 dev eth0 sudo ip addr add 172.16.101.254/24 dev br1 lxc exec c01 -- ip addr add 172.16.101.2/24 dev eth0 sudo ip addr add 172.16.102.254/24 dev br2 lxc exec c02 -- ip addr add 172.16.102.2/24 dev eth0
リンクアップ(忘れがち。忘れると動かないので注意)
sudo ip link set br0 up sudo ip link set veth1-br up sudo ip link set veth2-br up sudo ip link set br1 up sudo ip link set veth10-br up sudo ip link set veth11-br up sudo ip link set br2 up sudo ip link set veth20-br up sudo ip link set veth21-br up lxc exec m01 ip link set eth0 up lxc exec m01 ip link set eth1 up lxc exec m02 ip link set eth0 up lxc exec m02 ip link set eth1 up lxc exec c01 ip link set eth0 up lxc exec c02 ip link set eth0 up
up を忘れると、通信できない。通信できず、経路が悪いのか設定が悪いのか分からずに、嵌まり込むので注意する。事前にしっかりとlink up しておく。 とくにvethでは両端をUPしていくので注意。
vethのup はめんどくさいけど、漏れなくダブりなく設定を頑張る。
ブリッジに入れたnic間の通信許可
sudo sysctl net.bridge.bridge-nf-call-iptables=0
ブリッジ・インタフェースは、iptablesで制御されてしまうので、それを外しバカ・ハブ(ダムハブ)として動作させる.この処理はなくても動くと思う。
コンテナ内部 ブリッジ br-gre01 作成
lxc exec m01 ip link add br-gre01 type bridge lxc exec m01 ip link set eth1 master br-gre01 lxc exec m01 ip link set br-gre01 up lxc exec m01 ip addr add 172.16.101.1/24 dev br-gre01
gretap を作ったらブリッジに入れて共有するので作っておく。
コンテナ内部 ブリッジ br-gre02 作成
lxc exec m02 ip link add br-gre02 type bridge lxc exec m02 ip link set br-gre02 up lxc exec m02 ip link set eth1 master br-gre02 lxc exec m02 ip addr add 172.16.102.1/24 dev br-gre02
gretap を作ったらブリッジに入れて共有するので作っておく。
動作チェック
ping -c 1 10.1.0.254 ping -c 1 172.16.101.254 ping -c 1 172.16.102.254 lxc exec m01 -- ping -c 1 10.1.0.254 lxc exec m01 -- ping -c 1 172.16.101.254 lxc exec m01 -- ping -c 1 172.16.101.2 lxc exec m02 -- ping -c 1 10.1.0.254 lxc exec m02 -- ping -c 1 172.16.102.254 lxc exec m02 -- ping -c 1 172.16.102.2
ここまでで、通信経路と仮想デバイス接続が間違ってないか確認する。
ネットワークとコンテナが間違ってる通信ができない。そのときは、一つずつミスを探してやり直し。
連続したlxc exec -- command
を、複数行をまとめてコピペすると動かないので注意する。
greptap を作って通信する。
gre を作成 して ブリッジに入れる
lxc exec m01 -- ip link add name gre01 type gretap remote 10.1.0.2 lxc exec m02 -- ip link add name gre02 type gretap remote 10.1.0.1 lxc exec m01 -- ip link set gre01 master br-gre01 lxc exec m02 -- ip link set gre02 master br-gre02 lxc exec m01 -- ip link set gre01 up lxc exec m02 -- ip link set gre02 up lxc exec m01 -- ip link set gre01 mtu 1450 lxc exec m02 -- ip link set gre02 mtu 1450
gre0
は予約されているので、別名にした。
ここも、lxc exec -- command
に注意する。複数行をまとめてコピペすると、改行が --
で吸収されてしまう。なので、まとめてコピペせずに1行ずつやる
gre 経由の通信を確認
sudo ip addr add 172.16.101.253/24 dev br2 lxc exec m02 -- ip addr add 172.16.101.3/24 dev br-gre02 lxc exec c02 -- ip addr add 172.16.101.4/24 dev eth0
疎通を確認
lxc exec m01 -- ping -c 1 172.16.101.253 lxc exec m01 -- ping -c 1 172.16.101.3 lxc exec m01 -- ping -c 1 172.16.101.4 lxc exec c01 -- ping -c 1 172.16.101.253 lxc exec c01 -- ping -c 1 172.16.101.3 lxc exec c01 -- ping -c 1 172.16.101.4
c01 と c02 が通信できたらイーサネットフレームが転送されている。pingの応答が来たら成功。
DHCP がgretap 経由で転送されているか確認
pingの他にも dhcp などを試してパケットを確認しておく
ホスト側からブリッジの通信を見つつ
sudo tcpdump -i br2
別のターミナルを立ち上げてDHCPパケットを流して見る。
lxc exec c01 -- dhclient -4 -v eth0 lxc exec c01 -- dhclient -6 -v eth0
tcpdump でパケットが確認できたら無事にGRETAPできていると言える。
ubuntuを使った理由はここで、tcpdump は最初からインストール済みでコンテナが作成される。
ARPの確認
arp キャッシュを見てみる。ip neigh で隣接しているMACアドレスが分かる。ここに出てきていてればOKである。
takuya@raspi-ubuntu:~$ lxc exec c01 -- ip neigh 172.16.101.254 dev eth0 lladdr 3e:0a:df:7d:f4:52 STALE 172.16.101.1 dev eth0 lladdr 16:9a:f2:ba:c1:f0 STALE 172.16.101.253 dev eth0 lladdr 3e:0a:df:7d:f4:52 STALE 172.16.101.4 dev eth0 lladdr f6:ca:27:f5:91:cc STALE 172.16.101.3 dev eth0 lladdr c6:2c:d0:0e:4e:1b STALE
ARPが抜けてるか確認
tcpdump -i br1 arp
lxc exec m02 tcpdump -i br-gre02 arp
ARPが抜けてない場合は、arptablesをオフにする必要があるかもしれない。
mDNSが使えるかチェック
mDNSは、ubuntuなら最初から稼働しているはずなのでチェックしておく
lxc exec c01 -- ping c02.local
ubuntu 以外だと、avahi-daemon
を入れる必要があり、仮想マシンを外部ネットワークへ接続する必要があるので、ubuntu 以外をコンテナに使うとめんどくさいんだよね。
wireguardの場合
veth1-br0-verth1
の部分が、wg0 の wireguardネットワークになるだけで動くはずである。まだ試してない。
今回使ったもの
- snap lxc
- ubuntu 20.04
です。
openwrt でやる場合
WRTで実験するなら、opkg install kmod-gre
でgreを足してやる必要がある。kmod-gre を足すと、デフォルトで gretap0 が生えてくる
参考資料
- https://blog.kamijin-fanta.info/2018/12/netns/
- https://qiita.com/TSA2019/items/a28fbb8f4a04bb3931b6
- https://yabe.jp/gadgets/edgerouter-x-s1-l2-vpn-with-softether/
- https://www.kanadas.com/program/2013/02/2_gre.html
- https://qiita.com/homihomu/items/804847373a1a7e27bbf7
- https://trema.hatenablog.jp/entry/20120420/1334928361
- https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/configuring-a-gretap-tunnel-to-transfer-ethernet-frames-over-ipv4_configuring-ip-tunnels