澤原 雅隆
エンジニア
KLabGames事業本部
KLab株式会社
VyOSで作る
IPv4 Router/IPv6 Bridge
2
2020年4月 新卒入社
業務
アプリケーション開発 (Python, C#)
趣味
● プログラミング(C++, Goなど)
● 電子工作
● ネットワーク機器いじり
など...
澤原 雅隆
エンジニア
KLabGames事業本部
KLab株式会社
自己紹介
画像
3
はじめに
● 趣味で自宅のネット環境を弄って遊ぶ話です
IPv6対応のために
○ VyOSでルータを作ったり
○ Linuxカーネルを書き換えてみたりします
● お仕事の話は出てきません😎
4
自宅のネット回線、
快適ですか?
5
自宅のネット回線
● 朝から晩までは在宅勤務
● 退勤後はゲームや趣味の活動など
一日のほとんどは自宅のネット回線を使用
「安定した速い回線を使いたい!」
との思いから、光回線を契約しました
「光回線なら超快適なんでしょ?」と思いますよね……?
6
光回線で
10Mbpsしか出ない……
7
● 回線事業者の 網終端装置 がボトルネック
1Gbpsの装置に最大 2,200~6,400 セッションを収容
通信が集中し、1回線あたり10Mbps以下に
IPv4 PPPoE接続における輻輳問題
自宅 回線事業者網 ISP (プロバイダ)
光回線
Internet
Exchange
※2020年4月の状況。現在では、設備追加や10Gbps対応装置の利用等により
速度の低下が抑えられています
8
輻輳の回避策:IPv6 IPoE + IPv4 over IPv6
IPv6 IPoE接続… VNE事業者網 へ接続
IPv4接続はどうするか?
⇒ IPv6 IPoE接続の上に流す (IPv4 over IPv6)
自宅 回線事業者網 ISP (プロバイダ)
光回線
Internet
Exchange
網終端装置
(1Gbps対応)
ゲートウェイルータ
(100Gbps対応)
9
10
常時数百Mbpsで通信できる!
超快適!
11
ところで
12
IPv6対応、
大丈夫ですか?
13
実家暮らしのネット環境: IPv6導入前
従来は
● IPv4のみ利用
● 二重ルータ構成
○ 自分用にサブネットを用意
○ サブネット内は自由に遊べる
14
サブネットの切り方の違い (一般家庭の場合)
IPv6 アドレスは/64分しか貰えない場合がある
(契約内容による)
⇒ サブネットは一つしか作れない
IPv4 IPv6
付与される
グローバルIPアドレス
1個 264個 ~ 272個
(/64~/56)
使用するアドレス プライベートIPアドレス グローバルIPアドレス
NAT ゲートウェイで実施 使用しない
プレフィックス長 /8~/31 /56~/64
15
IPv6対応の方針
● 物理構成
○ 以前と同一
■ 二重ルーター構成
● 論理構成
○ IPv4
■ 従来通りサブネットを分け、NATする
○ IPv6
■ 単一サブネットとするため、ブリッジさせる
⇒ IPv4 Router/IPv6 Bridge を構築する
16
VyOSで作る
IPv4 Router/IPv6 Bridge
17
VyOSとは
● Linuxベースのソフトウェアルーター
● 業務用ネットワーク機器のように、CLIで設定できる
安定版の利用はサブスクリプション契約が必要
スナップショット版とソースコードは無償で利用可能
18
Linuxにおけるパケット転送処理
Netfilter
パケット転送用のフレームワーク
iptables/ebtables
Netfilterの設定用ツール
iptables → IPパケットのルーティング処理
ebtables → Ethernetブリッジのフォワーディング処理
19
brouteテーブル
Ethernetフレームをルーティング処理 or フォワーディング
処理のどちらに送るか条件付け
しかし、VyOSではbrouteテーブルの設定ができない……
broute
DROP
ACCEPT
フォワーディング
ルーティング
ebtables -t broute -P BROUTING DROP
ebtables -t broute -A BROUTING -p ipv6 -j ACCEPT
コマンド例
20
RouterとBridgeでポートを分けてみる
動作するが、接続ポート数が増える……
⇒仮想ポートを使って、実ポートを1つにまとめてみる
IPv6?
DROP
ACCEPT
フォワーディング
IPv4?
DROP
ACCEPT
ルーティング
21
仮想ポートを使ってまとめてみる
pseudo-ethernet (MACVLAN) を用いて
物理ポートから仮想ポートを2つ作成してみる
⇒なぜかIPv6 Bridge側でパケットが通らない
MACVLAN
MACVLAN
IPv6?
DROP
ACCEPT
フォワーディング
IPv4?
DROP
ACCEPT
ルーティング
22
LinuxカーネルのMACVLAN実装
宛先MACアドレスが一致する仮想ポートに対して転送する
⇒宛先MACアドレス一致しないと転送されない
static void macvlan_forward_source(struct sk_buff *skb,
struct macvlan_port *port,
const unsigned char *addr)
{
struct macvlan_source_entry *entry;
u32 idx = macvlan_eth_hash(addr);
struct hlist_head *h = &port->vlan_source_hash[idx];
hlist_for_each_entry_rcu(entry, h, hlist) { ←
for-eachマクロ
if (ether_addr_equal_64bits(entry->addr, addr)) ←
MACアドレスを比較
macvlan_forward_source_one(skb, entry->vlan); ←
仮想ポートへ転送
}
}
drivers/net/macvlan.c
23
何が起きていたのか
宛先MACアドレスと関係なく受信してほしい
⇒ MACVLANをPromiscuous modeに対応させてみる
PC
VyOS
(IPv6 Bridge) ルータ
「ルータ宛のパケットです」
「私宛ではないので無視します」
24
MACVLANのPromiscuous mode対応
{
struct macvlan_source_entry *entry;
struct macvlan_dev *promisc_entry;
u32 idx = macvlan_eth_hash(addr);
struct hlist_head *h = &port->vlan_source_hash[idx];
hlist_for_each_entry_rcu(entry, h, hlist) {
if (ether_addr_equal_64bits(entry->addr, addr)
&& !(entry->vlan->dev->flags & IFF_PROMISC)) ← promiscでないポート
macvlan_forward_source_one(skb, entry->vlan);
}
list_for_each_entry_rcu( ← Promiscuous modeな
ポート一覧をfor-each
promisc_entry, &port->vlan_promisc_list, promisc_list
) {
macvlan_forward_source_one(skb, promisc_entry);
← 無条件で転送
}
}
25
無事に通信できた!
パッチを当てたカーネルを使い、IPv6で通信できました。
26
おわりに
● 自宅ネット環境のIPv6化
○ VyOSでIPv4 Router/IPv6 Bridgeを構築した
○ MACVLANにPromiscuous modeを実装した
■ Linux kernelを書き換えた
● この発表は、KLab社内の技術共有メーリングリストへ
投稿した内容を基にしています
○ 業務内外問わず、技術情報を共有するML
○ 良い投稿は社内表彰の対象にも
○ 情報を共有をしよう!

VyOSで作るIPv4 Router/IPv6 Bridge