OpenStack管理下にあるVMのNIC間でip_forwardを行う

構成

以下のような構成を想定して、vm0eth1eth2の間でルータのようにIPフォワードをさせたい場合に必要となる設定メモ。

ちょっと事情があってserverXDefaultGateway10.0.1.1serverYDefaultGateway10.0.2.1に向けて、相互に通信させたかったのです。

-----------+---------------------------------------------------------- ext-net
           |
           |
      +----+----+
      | router0 |
      +----+----+
           |
           |.129
-----------+------+--------------------------------------------------- demo-net0 (10.0.0.0/24)
                  |.135
                  |
------------------|-----+-------------------+------------------------- demo-net1 (10.0.1.0/24)
                  |     |.1                 |.100
                  |     |                   |
------------------|-----|-----+-------------|---------------+--------- demo-net2 (10.0.2.0/24)
                  |     |     |.1           |               |.101
                  |     |     |             |               |
              +---+-----+-----+---+   +-----+-----+   +-----+-----+
              |  eth0  eth1  eth2 |   |    eth0   |   |    eth0   |
              |                   |   |           |   |           |
              |        vm0        |   |  serverX  |   |  serverY  |
              |                   |   |           |   |           |
              +-------------------+   +-----------+   +-----------+

できない...

実は...デフォルトの設定ではできないんです。SecurityGroupでごにょごにょすれば行けるのかとも思いましたが、残念ならができません。

そこで、調べてみました。

nova boot仮想マシンを起動させると、computeノード上で起動しているneutronのagentが、computeノードのiptablesに以下のような設定を投入します。

Chain neutron-linuxbri-s7780e5de-2 (1 references)
num  target     prot opt source               destination
1    RETURN     all  --  10.0.1.1             anywhere             MAC FA:16:3E:69:AD:2E /* Allow traffic from defined IP/MAC pairs. */
2    DROP       all  --  anywhere             anywhere             /* Drop traffic without an IP/MAC allow rule. */

Chain neutron-linuxbri-sbcd24cc0-d (1 references)
num  target     prot opt source               destination
1    RETURN     all  --  10.0.2.1             anywhere             MAC FA:16:3E:92:84:F1 /* Allow traffic from defined IP/MAC pairs. */
2    DROP       all  --  anywhere             anywhere             /* Drop traffic without an IP/MAC allow rule. */

Neutronでは、IP Spoofing対策の1つとして、仮想マシン自身に割り当てられているIPアドレス以外は、FORWARD時に落とすという仕組みを、上記の設定を投入することで実現しているようです。

そして、このチェーンは、以下のようにChain FORWARDに登録されます。 ちなみに、チェーン名の末尾に付与されているIDは、それぞれのtapデバイス名に由来しているので、環境により異なります。

Chain FORWARD (policy ACCEPT)
  |
  +- neutron-filter-top
  |     |
  |     +- neutron-linuxbri-local
  |
  +- neutron-linuxbri-FORWARD
        |
        +- neutron-linuxbri-sg-chain
              |
              +- neutron-linuxbri-ibcd24cc0-d
              |
              +- neutron-linuxbri-obcd24cc0-d
              |     |
              |     +- neutron-linuxbri-sbcd24cc0-d   <-- これ
              |
              +- neutron-linuxbri-i7780e5de-2
              |
              +- neutron-linuxbri-o7780e5de-2
              |     |
              |     +- neutron-linuxbri-s7780e5de-2   <-- これ
              |
              +- neutron-linuxbri-i8a0e0062-b
              |
              +- neutron-linuxbri-o8a0e0062-b
                    |
                    +- neutron-linuxbri-s8a0e0062-b

考えた対策

computeノード上で...

  1. iptables -F を実行してポリシー全消し -> まあだめだよね
  2. neutron-linuxbri-s* のルールを削除する -> まぁだめだよね
  3. iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPTを突っ込む -> まぁだめだよね
  4. sysctl -w net.bridge.bridge-nf-call-iptables=0 でブリッジにiptablesを見せない -> 本末転倒

どれも、まぁだめだよね...

手詰まり...かと思いきや、実はちゃんと設定できました。

この機能をNeutronは提供していた

IPフォワードしてもらうために向けられてくるネットワークアドレスレンジを、neutron-linuxbri-s*チェーンに追加してやる方法ないかな...いろいろ調べてみると、ネットワークレンジを--allowed-address-pairsでポートに追加してやれば良さそうという結論に至りました。

$ neutron port-update 7780e5de-222a-4805-accc-77a380732cf3 \
--allowed-address-pairs \
type=dict \
list=true \
ip_address=10.0.2.0/24

$ neutron port-update bcd24cc0-d1d9-4016-a512-f0b12075f1c0 \
--allowed-address-pairs \
type=dict \
list=true \
ip_address=10.0.1.0/24

これを実行すると、neutron-linuxbri-s*チェーンの設定に、以下のようなポリシーが追加となります。

Chain neutron-linuxbri-s7780e5de-2 (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1      112  9408 RETURN     all  --  any    any     10.0.2.0/24          anywhere             MAC FA:16:3E:69:AD:2E /* Allow traffic from defined IP/MAC pairs.     */
2        0     0 RETURN     all  --  any    any     10.0.1.1             anywhere             MAC FA:16:3E:69:AD:2E /* Allow traffic from defined IP/MAC pairs.     */
3        0     0 DROP       all  --  any    any     anywhere             anywhere             /* Drop traffic without an IP/MAC allow rule. */

Chain neutron-linuxbri-sbcd24cc0-d (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1      230 19320 RETURN     all  --  any    any     10.0.1.0/24          anywhere             MAC FA:16:3E:92:84:F1 /* Allow traffic from defined IP/MAC pairs.     */
2        0     0 RETURN     all  --  any    any     10.0.2.1             anywhere             MAC FA:16:3E:92:84:F1 /* Allow traffic from defined IP/MAC pairs.     */
3        0     0 DROP       all  --  any    any     anywhere             anywhere             /* Drop traffic without an IP/MAC allow rule. */

ということで、これでcomputeノード上のVMで、ip_fowardを有効化してあげれば、ちゃんとIPフォワードしてくれました。

この機能、Havanaから実装されてるのね。知らんかった。