メインコンテンツまでスキップ

Ubuntu22.04のnftablesでルーターを作る

· 約5分
hi120ki
Hiroki Akamatsu

R86Sという10Gbe SFP+ポートが2つ、2.5Gbe RJ45ポートが3つ付いたおもしろPCを購入したのでUbuntu22.04を入れてルーターにしていきます。

R86S本体

インターフェイス名を変更

Ubuntuインストール後、まずインターフェイス名を以下の記事を参考に変更します。

https://www.jagchanna.ca/renaming-a-network-interface-in-ubuntu-18-04-on-ibm-cloud/

ip aコマンドで初期のインターフェイス名ごとにMACアドレス値を確認して、/etc/udev/rules.d/70-persistent-net.rulesファイルでインターフェイス名を固定します。

/etc/udev/rules.d/70-persistent-net.rules

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:xx:xx:xx:xx:xx", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:xx:xx:xx:xx:xx", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:xx:xx:xx:xx:xx", NAME="eth2"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f4:xx:xx:xx:xx:xx", NAME="sfp0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f4:xx:xx:xx:xx:xx", NAME="sfp1"

ブリッジインターフェイスの設定

次にネットワーク設定のnetplanの設定ファイルを編集します。

今回はeth0をWANポートにして、他のポートについてはスイッチングハブのようにケーブルで繋げば設定されたサブネット(10.1.0.1/16)の中で互いに通信できるようにします。

そのためにまずはbridgeインターフェイスを作成し、WANポート以外のeth1, eth2, sfp0, sfp1を指定します。

こうすることでeth1, eth2, sfp0, sfp1に接続された機器は互いに通信でき、またルーターとなるR86Sは10.1.0.1を持つ機器のように認識されます。

/etc/netplan/00-installer-config.yaml

network:
ethernets:
eth0:
addresses:
- 192.168.0.10/24
routes:
- to: default
via: 192.168.0.1
nameservers:
addresses:
- 8.8.8.8
eth1:
dhcp4: no
eth2:
dhcp4: no
sfp0:
dhcp4: no
sfp1:
dhcp4: no
bridges:
br0:
interfaces: [eth1, eth2, sfp0, sfp1]
addresses: [10.1.0.1/16]
nameservers:
addresses:
- 8.8.8.8
version: 2

IPマスカレード(NAT)設定

Ubuntu22.04からフォワーディングやマスカレードを行うパケットフィルタリングツールがiptablesからnftablesに変更されました。

nftablesは初めから入っているためufw.serviceサービスを止めた後、以下のような設定ファイルを編集しnftables.serviceを起動します。

$ sudo systemctl stop ufw.service
$ sudo systemctl disable ufw.service

/etc/nftables.conf

#!/usr/sbin/nft -f

flush ruleset

define PORT_GLOBAL = eth0
define NET_PRIVATE = 10.1.0.0/16

table inet filter {
chain input {
type filter hook input priority 0;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
}
}

table ip nat {
chain prerouting {
type nat hook prerouting priority 0;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname $PORT_GLOBAL ip saddr $NET_PRIVATE masquerade
}
}
$ sudo systemctl enable nftables.service
$ sudo systemctl start nftables.service

これで10.1.0.0/16からの通信がeth0ポートでNATされるようになります。

DHCPサーバー

そして最後にDHCPサーバーをdocker composeで立ち上げます

docker-compose.yml

version: "3"

services:
dhcpd:
image: networkboot/dhcpd
restart: always
network_mode: host
command: br0
volumes:
- $PWD/data:/data

data/dhcpd.conf

default-lease-time 6000;
max-lease-time 72000;
option routers 10.1.0.1;
option subnet-mask 255.255.0.0;
option domain-name-servers 1.1.1.1, 8.8.8.8;

subnet 10.1.0.0 netmask 255.255.0.0 {
range 10.1.1.1 10.1.1.254;
}

このように設定ファイルを作り、docker-compose upコマンドを実行するとDHCPサーバーが立ち上がり、10.1.1.1~10.1.1.254のIPアドレスが割り振られるようになります。

速度測定

SFP+で接続したLAN内2台のPC間の速度を計測しました。

$ iperf3 -c 10.1.0.10
Connecting to host 10.1.0.10, port 5201
[ 5] local 10.1.0.11 port 56902 connected to 10.1.0.10 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 1.08 GBytes 9.30 Gbits/sec 166 1.80 MBytes
[ 5] 1.00-2.00 sec 1.09 GBytes 9.33 Gbits/sec 0 2.17 MBytes
[ 5] 2.00-3.00 sec 1.09 GBytes 9.35 Gbits/sec 0 2.42 MBytes
[ 5] 3.00-4.00 sec 1.09 GBytes 9.34 Gbits/sec 0 2.71 MBytes
[ 5] 4.00-5.00 sec 1.09 GBytes 9.35 Gbits/sec 0 2.96 MBytes
[ 5] 5.00-6.00 sec 1.09 GBytes 9.35 Gbits/sec 0 3.00 MBytes
[ 5] 6.00-7.00 sec 1.09 GBytes 9.36 Gbits/sec 0 3.00 MBytes
[ 5] 7.00-8.00 sec 1.09 GBytes 9.35 Gbits/sec 0 3.00 MBytes
[ 5] 8.00-9.00 sec 1.09 GBytes 9.35 Gbits/sec 0 3.00 MBytes
[ 5] 9.00-10.00 sec 1.09 GBytes 9.36 Gbits/sec 0 3.00 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 10.9 GBytes 9.35 Gbits/sec 166 sender
[ 5] 0.00-10.00 sec 10.9 GBytes 9.34 Gbits/sec receiver

iperf Done.

ワイヤーレートに近い値(9.3Gbps)となりました。