仙石浩明の日記

2006年4月3日

IPv6 (2)

IPv6ブリッジ機能付きルーター (ブルータ) を使えば、 NAT 内の LAN でそのまま IPv6 を使えるわけで、 IPv6 の敷居は一気に下がる。

つまり、ほとんどの OS がすでに IPv6 をサポートしているので、 ルータが IPv6 を素通し (ブリッジ) しさえすれば、 LAN 内で IPv6 を意識せずに使える。

今まで通り IP を (NAT 経由したプライベートアドレスで) 使いながら、IPv6 のオイシイところ (end-to-end 通信ができる) だけを ツマミ食いできるわけで、 今度こそ (^^;) IPv6 が普及するのではないかと...

Linux でブルータを実現するには、 まずブリッジ機能をカーネルに組み込んでおく。

# brctl show br0
bridge name     bridge id               STP enabled     interfaces
br0             8000.00022Axxxxxx       no              eth0
                                                        eth1

このままだと IP までブリッジしてしまうので、 IP に対してはルータとして機能し、 IPv6 に対してだけブリッジさせるために、ebtables を使う。

# ebtables -t broute -L
Bridge table: broute

Bridge chain: BROUTING, entries: 3, policy: DROP      …… (3)
-j mark --set-mark 0x0 --mark-target CONTINUE         …… (0)
-p IPv6 -i eth0 -j mark --set-mark 0x600              …… (1)
-p IPv6 -i eth1 -j mark --set-mark 0x601              …… (2)

上記設定の意味は、

(0) まず全パケットに対し 0x0 のマークをつける。
    で、
(1) eth0 から入ってきた (LAN内から外へ出ていく)
    IPv6 パケットは、0x600 のマークをつけてブリッジする。
(2) 逆に eth1 から入ってきた (外から入ってきた)
    IPv6 パケットは、0x601 のマークをつけてブリッジする。
(3) それ以外 (IP パケットや PPPoE パケット) はブリッジしない (DROP)
    つまり IP に対してはルータとして機能する

さらに ip6tables を使ってフィルタリングする。

ip6tables -P FORWARD DROP                                       …… (*)
ip6tables -I FORWARD -j incoming -m mark --mark 0x601/0xffff    …… (2)
ip6tables -I FORWARD -j ACCEPT -m mark --mark 0x600/0xffff      …… (1)
(1) 0x600 のマークがついているパケットは、素通し (ACCEPT) する。
(2) 0x601 のマークがついているパケットは、incoming チェインへ渡す。

incoming チェインで ACCEPT されなかったパケットは、
(*) FORWARD チェインのポリシーに従って、DROP される。

ebtables でマーク付して ip6tables でそのマークに基づいて フィルタリングするという、 まわりくどい方法をとっているのは、 ebtables はあくまで L2 のフィルタなので IPv6 アドレスに基づいたフィルタリングができず、 逆に ip6tables は L3 のフィルタなので eth0/eth1 はまとめてブリッジインタフェース br0 としてしか見えず、 どちらの物理インタフェースから入ってきたパケットか 判別できないため。

ちなみに iptables だと、 L3 フィルタといいながら physdev モジュールがあるので、 ブリッジのどちら側から入ってきたか判別できたりする。 ip6tables の機能拡張に期待したいところ。

Filed under: IPv6,システム構築・運用 — hiroaki_sengoku @ 07:20

5件のコメント »

  1. 約8年も前の記事に今更コメントするのも恐縮ですが…。
    しかし ebtables でググるとこのページが現時点でかなり高い順位でヒットするために記す次第です。

    リンク層での forward とネットワーク層での forward とを混同していないでしょうか。
    ebtables で FORWARD と判定されたパケットは、その後 ip6tables の filter テーブルを通りません。(というか ip6tables の俎上にも乗りません。)言い換えると、ネットワーク層はリンク層での forward に何ら関与しません。
    よって、当ページの例では IPv6 フィルタリングできません。

    コメント by tak — 2014年2月28日 @ 11:30

  2. 何年経ってもコメントは歓迎します。

    おっしゃる通り、ebtables で FORWARD と判定されたパケットは Link Layer のみで Network Layer は通りませんし、iptables は network level フィルタなので、iptables の俎上に乗らないのが自然な感じがします。

    ところが Linux の実装では、Link Layer のみを通るパケットも network level フィルタリングが行われます。

    Packet flow in Netfilter

    どのような構成でフィルタリングできなかったのか、教えていただけると幸いです。

    コメント by hiroaki_sengoku — 2014年3月3日 @ 00:44

  3. 私が体験したのは、記憶が曖昧ですが、CentOS6.なんぼで
    # iptables -P FORWARD DROP #まだルールを組み立てていないので DROP 仮設置
    # brctl addbr br0 #とりあえず bridge(でもまだ通らないよね、DROP してるから。)
    # brctl addif br0 eth0
    # brctl addif br0 eth1
    結果: 通ってる。(・3・)あるぇ~?

    このとき iptables で DROP しているのは L3 forward である(はず)ことに気付き、L2 forward は iptables を通らない、と結論付けておしまいにしたのですが…

    ご返信を受けて CentOS 6.5 にて今一度検証してみました。
    DHCP を有効にしたルータにブリッジマシンの eth0 を繋ぎ、eth0 と eth1 とを bridge します(br0)。
    上記の通り、iptables/ip6tables の FORWARD は -P で DROP です。
    eth1 側で適当なクライアントを立ち上げ、
    結果: 通ってる。(・3・)あるぇ~?
    IPv4 は完全にスパスパ抜けちゃっています。
    IPv6 も ND 通っちゃってます。それ以上のことは確かめていませんが。
    iptables/ip6tables とも、FORWARD のカウンタは 0 のままです。

    コメント by tak — 2014年3月4日 @ 23:27

  4. 大事な事を忘れていたので再検証しました。
    # echo 1 > /proc/sys/net/ipv4/ip_forward
    駄目だ、やっぱり通る…
    ここでふと思いつき、/etc/sysctl.conf に目を通してみると

    # Disable netfilter on bridges.
    net.bridge.bridge-nf-call-ip6tables = 0
    net.bridge.bridge-nf-call-iptables = 0
    net.bridge.bridge-nf-call-arptables = 0

    …こいつらかorz

    先生の仰る通り、ちゃんと(?)L2 forward パケットが iptables を通るようになりました。

    大変失礼致しました。お詫び申し上げます。

    コメント by tak — 2014年3月5日 @ 00:56

  5. このブログを書いた 2006年当時の ebtables には、IP アドレス/ポートに基づいてフィルタリングを行う機能が含まれていなかったので、ブリッジするパケットも iptables/ip6tables を経由させて、IP アドレス/ポートに基づくフィルタリングは iptables/ip6tables に任せる仕様だったのだと思います。

    ところが、その後 ebtables でも IP アドレス/ポートに基づくフィルタリングが可能になり (–ip-destination-port など)、ブリッジするパケットを iptables/ip6tables を経由させる必要性が薄れたのですが、カーネルの挙動をいきなり変えるわけにもいかず、net.bridge.bridge-nf-call-iptables 等で制御できるようにしたのでしょうね。

    コメント by hiroaki_sengoku — 2014年3月5日 @ 10:28

この投稿へのコメントの RSS フィード。

コメントする