ebtablesの勉強

## 概要
Linuxのebtablesの勉強。
filterのほか、brouteの動作検証をする。

## 環境
* OSXでmultipass上でubuntuを起動させ、linux namespaceで以下のような環境を構築する。

![bridge.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630941/854702b7-8791-20ef-cf76-b8ff06047919.png)

* ubuntuは22.04とする。なお、ebtablesはbrouteルールを用いるためバージョンアップをする。

https://stackoverflow.com/questions/63439723/error-in-installation-of-openstack-in-ubuntu

* bridge-utilsをインストールしておく。

## ブリッジの作成
linux namespaceでブリッジを作成する。

<pre>sudo ip netns add moon
sudo ip netns add sun
sudo ip netns add sun-lan

sudo ip link add sunlan-veth0 type veth peer name sun-veth0
sudo ip link add sun-veth1 type veth peer name moon-veth1
sudo ip link set sunlan-veth0 netns sun-lan
sudo ip link set sun-veth0  netns sun
sudo ip link set sun-veth1 netns sun
sudo ip link set moon-veth1 netns moon

sudo ip netns exec sun-lan ip link set sunlan-veth0 up
sudo ip netns exec sun ip link set sun-veth1 up
sudo ip netns exec sun ip link set sun-veth0 up
sudo ip netns exec moon ip link set moon-veth1 up
sudo ip netns exec sun sysctl net.ipv4.ip_forward=1

sudo ip netns exec sun-lan ip addr add 192.168.0.11/16 dev sunlan-veth0 
sudo ip netns exec moon ip addr add 192.168.0.12/16  dev moon-veth1</pre>

ブリッジインタフェースの作成。

<pre>sudo ip netns exec sun brctl addbr br0
sudo ip netns exec sun ip addr add 192.168.0.1/16 dev br0
sudo ip netns exec sun brctl addif br0 sun-veth0
sudo ip netns exec sun brctl addif br0 sun-veth1
sudo ip netns exec sun ip link set dev sun-veth0 promisc on
sudo ip netns exec sun ip link set dev sun-veth1 promisc on
sudo ip netns exec sun ip link set sun-veth0 up
sudo ip netns exec sun ip link set sun-veth1 up
sudo ip netns exec sun ip link set br0 up</pre>

sun-lanからping導通可能なことを確認。

<pre>ubuntu@ipip:~$ sudo ip netns exec sun-lan ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=64 time=0.053 ms
^C
--- 192.168.0.12 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1086ms
rtt min/avg/max/mdev = 0.039/0.046/0.053/0.007 ms
ubuntu@ipip:~$ sudo ip netns exec sun-lan ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=0.047 ms
^C
--- 192.168.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1074ms
rtt min/avg/max/mdev = 0.047/0.059/0.072/0.012 ms
ubuntu@ipip:~$ sudo ip netns exec sun ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=64 time=0.068 ms
^C
--- 192.168.0.12 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1060ms
rtt min/avg/max/mdev = 0.025/0.046/0.068/0.021 ms</pre>

## ebtablesの検証(FORWARD)
FORWARDルールの検証を例として行う。

初期状態のebtablesのルール。
<pre>ubuntu@ipip:~$ sudo ip netns exec sun ebtables -L
Bridge table: filter

Bridge chain: INPUT, entries: 0, policy: ACCEPT

Bridge chain: FORWARD, entries: 0, policy: ACCEPT

Bridge chain: OUTPUT, entries: 0, policy: ACCEPT</pre>

FORWARDのデフォルトポリシーをDROPにする
<pre>ubuntu@ipip:~$ sudo ip netns exec sun ebtables -P FORWARD DROP
ubuntu@ipip:~$ sudo ip netns exec sun ebtables -L
Bridge table: filter

Bridge chain: INPUT, entries: 0, policy: ACCEPT

Bridge chain: FORWARD, entries: 0, policy: DROP

Bridge chain: OUTPUT, entries: 0, policy: ACCEPT</pre>

sun-lanからping導通しなくなる
<pre>ubuntu@ipip:~$ sudo ip netns exec sun-lan ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
^C
--- 192.168.0.12 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1047ms</pre>

sunのbr0発はFOWWARD関係ないので転送される
<pre>ubuntu@ipip:~$ sudo ip netns exec sun ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=64 time=0.048 ms
^C
--- 192.168.0.12 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 0.048/0.049/0.051/0.001 ms</pre>

ipv4を転送許可する。
<pre>ubuntu@ipip:~$ sudo ip netns exec sun ebtables -A FORWARD -p IPv4 -j ACCEPT
ubuntu@ipip:~$ sudo ip netns exec sun ebtables -L
Bridge table: filter

Bridge chain: INPUT, entries: 0, policy: ACCEPT

Bridge chain: FORWARD, entries: 1, policy: DROP
-p IPv4 -j ACCEPT

Bridge chain: OUTPUT, entries: 0, policy: ACCEPT</pre>

導通しない。
<pre>ubuntu@ipip:~$ sudo ip netns exec sun-lan ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
^C
--- 192.168.0.12 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5357ms</pre>

ARPを許可すると転送する。
<pre>ubuntu@ipip:~$ sudo ip netns exec sun ebtables -A FORWARD -p ARP -j ACCEPT
ubuntu@ipip:~$ sudo ip netns exec sun-lan ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 192.168.0.1: icmp_seq=3 ttl=64 time=0.054 ms
^C
--- 192.168.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2073ms
rtt min/avg/max/mdev = 0.048/0.066/0.098/0.022 ms</pre>

## ebatalesの検証(broute)
ebtablesにはブリッジするか、ルータするか、の判断を行うbrouteテーブルがある。

 DROPとACCEPTはbrouteテーブル内では特別な意味を持っており、DROPはルーティングされ、ACCEPTはブリッジされる。

検証として上記ebtalesのFORWARDで転送可能となっている状態でbrouterテーブルのルールを追加する。

DROPルールを追加し、ルーティングになるようにする（この状態ではsunにはルーティング設定がないので転送されない）。
brouteルールにヒットしていることが表示からわかる（--Lcオプション）。

<pre>ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -L --Lc
Bridge table: broute

Bridge chain: BROUTING, entries: 0, policy: ACCEPT
ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -A BROUTING -p IPv4 -j DROP
ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -L --Lc
Bridge table: broute

Bridge chain: BROUTING, entries: 1, policy: ACCEPT
-p IPv4 -j DROP , pcnt = 0 -- bcnt = 0
ubuntu@primary:~$ sudo ip netns exec sun-lan ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
^C
--- 192.168.0.12 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2137ms

ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -L --Lc
Bridge table: broute

Bridge chain: BROUTING, entries: 1, policy: ACCEPT
-p IPv4 -j DROP , pcnt = 3 -- bcnt = 252</pre>

ここでDROPルールを削除してACCEPTルールに変更する。
ACCPETされ、ブリッジ転送になりebtablesのFORWARDルールで許可されているので転送に成功する。

<pre>ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -D BROUTING -p IPv4 -j DROP
ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -A BROUTING -p IPv4 -j ACCEPT
ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -L --Lc
Bridge table: broute

Bridge chain: BROUTING, entries: 1, policy: ACCEPT
-p IPv4 -j ACCEPT , pcnt = 0 -- bcnt = 0
ubuntu@primary:~$ sudo ip netns exec sun-lan ping 192.168.0.12
PING 192.168.0.12 (192.168.0.12) 56(84) bytes of data.
64 bytes from 192.168.0.12: icmp_seq=1 ttl=64 time=0.096 ms
64 bytes from 192.168.0.12: icmp_seq=2 ttl=64 time=0.111 ms
64 bytes from 192.168.0.12: icmp_seq=3 ttl=64 time=0.121 ms
^C
--- 192.168.0.12 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2071ms
rtt min/avg/max/mdev = 0.096/0.109/0.121/0.010 ms
ubuntu@primary:~$ sudo ip netns exec sun ebtables -t broute -L --Lc
Bridge table: broute

Bridge chain: BROUTING, entries: 1, policy: ACCEPT
-p IPv4 -j ACCEPT , pcnt = 6 -- bcnt = 504</pre>


## 参考
https://ebtables.netfilter.org/examples/basic.html#ex_config

https://man.plustar.jp/manpage/man8/ebtables-legacy.8.html

https://ebtables.netfilter.org/br_fw_ia/br_fw_ia.html