👏

N100のミニPCにVPPを入れてホームゲートウェイにした話

2024/01/22に公開

はじめに

自宅でネットワークとかの検証環境整備したいなーと日々思っていましたが,学生でルータを買うには値段とライセンスのハードルが高い.加えて,使いたいプロトコルに対応していない場合があったりして,選定が難しい.

そこで,噂のN100が使用されたPCをホームゲートウェイとして導入すれば色々なプロトコルを動作できるような環境が安く構築できると思い,HUNSNの2.5G×4ポートのN100 PCを購入しました.
PC上にLinuxを入れて,ソフトウェアルータとかを入れれば色々なプロトコルが動かせられるなーっと.

使用するN100 PC

このN100PCは,以下のスペックと外観のPCで,スマートな外観ではないですが,4つのポートと金属筐体が変態PCって感じで良いです.

  • CPU : Intel N100 (4 core 4 threads)
  • RAM : 8G
  • SSD : 128G

n100 pcくん

で,このN100 PCに,ソフトウェアルータやらを入れて行きたいと思います.

入れるのはVector Packet Processing (VPP)です.PCをルータとして動かしている記事を色々見たのですが(この記事とかこの記事),VPPが性能的にも拡張性も良さそうでした.OSはUbuntu22.04を使用し,ubuntu上にVPPを入れていきます.

ルータ構成

構成として以下のようにします.VPPにg1/0/0でWANと接続し,その他のインタフェースはLAN用にします.また,N100PCのUbuntuでネットワークに接続できるようにtap0を用意し,DHCPサーバとDNSサーバを運用します.

Vector Packet Processing (VPP)

DPDKで動く,OSSのソフトウェアルータです.高速で色々な企業で使用されています.

VPPの公式ページでは,VPPをHome Gatewayとして動かす記事が載っています.
バージョンや記事によって作り方が異なるのですが,以下2つの記事をベースに進めて行きます.

また,Qiitaのこの記事も参考にしています.

まず,VPPをインストールするために以下のコマンドを実行します.

curl -s https://packagecloud.io/install/repositories/fdio/release/script.deb.sh | sudo bash
sudo apt update -y
sudo apt install -y vpp vpp-plugin-core vpp-plugin-dpdk python3-vpp-api vpp-dbg vpp-dev

VPPの設定

VPPでは,VPPの設定に /etc/vpp/startup.confを記述する必要があります.
また,本記事では,VPP起動時に実行するVPPコマンドは/etc/vpp/startup.gateに記述します.

/etc/vpp/startup.conf

以下のように,VPPに関する設定を記述します.各項目の詳しい内容は,公式のドキュメントにかかれています.

unix {
  # backgroundで実行しない
  nodaemon
  log /var/log/vpp/vpp.log
  # すべてのメモリマップされたアドレス領域をダンプ
  full-coredump
  cli-listen /run/vpp/cli.sock

  # 起動時に実行するコンフィグ
  startup-config /etc/vpp/startup.gate
  # メインループ固定のスリープを追加する.
  poll-sleep-usec 100
  # 共有メモリセグメントの所有権を設定するために使用するグループID
  gid vpp
}

api-segment {
  gid vpp
}

dpdk {
   no-multi-seg
   no-tx-checksum-offload

   # このPCは2.5Gポートなので,TwoDotFiveGigabitEthernetという名前になるが,長くてめんどいので(),GigabitEthernetで統一
   dev 0000:01:00.0 {
      name GigabitEthernet1/0/0
   }
   dev 0000:02:00.0 {
      name GigabitEthernet2/0/0
   }
   dev 0000:03:00.0{
      name GigabitEthernet3/0/0
   }
   dev 0000:04:00.0{
      name GigabitEthernet4/0/0
   }
 }

plugins {
   plugin default { disable }
   plugin dhcp_plugin.so { enable }
   plugin dpdk_plugin.so { enable }
   plugin nat_plugin.so { enable }
   plugin ping_plugin.so { enable }
   plugin mactime_plugin.so { enable }
   plugin vmxnet3_plugin.so { enable }
 }

 
logging {
  default-log-level debug
}

/etc/vpp/startup.gate

このファイルに,初期に実行するコマンドを定義しています.WAN側のインタフェースとしてGigabitEthernet1/0/0を指定し,DHCPでWANからアドレスを取ってきます.

内部のLANでL2 Bridgeを構築するので,WANとルーティングするためのインターフェースとしてbvi0を定義し,LANのインターフェースとともにL2 Bridgeにセットします.

DPDKでVPPを実行するとインターフェースがホスト(実行しているUbuntu)から見えなくなりインターネットにアクセスできないので,ホストがアクセスできるインターネットとしてtap0を定義します.

comment { Define variables }
define LOCAL_PRE 24
define LOCAL_GATE 192.168.10.1
define LOCAL_HOST 192.168.10.2
define HOSTNAME vpp-homegate

comment { WAN interface }
set int state GigabitEthernet1/0/0 up
comment { DHCPを用いてアドレスを取得 }
set dhcp client intfc GigabitEthernet1/0/0 hostname $(HOSTNAME)

comment { BVI interface }
bvi create instance 0
set int l2 bridge bvi0 1 bvi
set int ip address bvi0 $(LOCAL_GATE)/$(LOCAL_PRE)
set int state bvi0 up

comment { LAN interfaces }
set int l2 bridge GigabitEthernet2/0/0 1
set int state GigabitEthernet2/0/0 up
set int l2 bridge GigabitEthernet3/0/0 1
set int state GigabitEthernet3/0/0 up
set int l2 bridge GigabitEthernet4/0/0 1
set int state GigabitEthernet4/0/0 up

comment { Host-stack interface }
create tap host-if-name tap0 host-ip4-addr $(LOCAL_HOST)/$(LOCAL_PRE) host-ip4-gw $(LOCAL_GATE)
set int l2 bridge tap0 1
set int state tap0 up

comment { Configure NAT44 }
nat44 forwarding enable
nat44 plugin enable sessions 63000
nat44 add interface address GigabitEthernet1/0/0
set interface nat44 in bvi0 out GigabitEthernet1/0/0

bind9

DNSのキャッシュサーバとして,bind9を使用します.DNSサーバとしてはdnsmasqも有名ですが,後々の拡張性としてbind9のほうが優秀かと思いbind9にしました.

以下のコマンドでインストールします.

sudo apt install -y bind9 bind9utils

VPPくんはどうやらDHCPからDNSサーバ情報がとれないっぽいので,bind9では静的に設定します.forwardersがそのDNSサーバで,構築する環境によって変わります.

acl internal-network {
        192.168.0.0/16;
};

options {
        directory "/var/cache/bind";

        allow-query { localhost; internal-network; };
        forwarders {
                10.0.111.1;
                8.8.8.8;
        };

        recursion yes;
        dnssec-validation auto;

        listen-on-v6 { any; };
};

isc-dhcp-server

DHCPサーバとして,isc-dhcp-serverを使用します.

以下のコマンドでインストールします.

sudo apt install -y isc-dhcp-server

/etc/default/isc-dhcp-server

isc-dhcp-serverで使用するインターフェースを指定します.

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="tap0"
INTERFACESv6=""

/etc/dhcp/dhcpd.conf

配布するアドレスの情報を記述します.

subnet 192.168.10.0 netmask 255.255.255.0 {
  range 192.168.10.129 192.168.10.254;
  option subnet-mask 255.255.255.0; 
  option routers 192.168.10.1;
  option domain-name-servers 192.168.10.2;
}

/etc/systemd/resolved.conf

自分の環境では,この設定ではホスト側から名前解決ができませんでした.ホストで127.0.0.53に問い合わせるのですが,そのアドレスに明示的にBindさせても動かないんですよね.
なので,resolved.confに参照するアドレスを記述するようにしました.

[Resolve]
DNS=192.168.10.2

serviceの設定

この環境では,PC起動時にvppの起動順の問題(?)でisc-dhcp-serverが起動に失敗することがありました.
本当は依存関係を整理すべきですが,restartさせることで解決します.isc-dhcp-server.serviceの[Service]セクションに以下の行を追記します.

Restart=on-failure
RestartSec=3

その後,daemonをリロードして実行します.

sudo systemctl daemon-reload
sudo systemctl restart isc-dhcp-server

以上です.

おわりに

DHCPサーバやDNSサーバは,コンテナ化して整備したいですね.他にもFRRといったサービスを入れて,拡張していきたいです.

Discussion