VPCのVGWに複数のVPNコネクションを作るときの注意点

AWSVPCVPNの話。
VPCVPN接続するには様々なやり方があるが、ここではVirtual Private Gateway略称VGW)という仮想的なコネクタAWSのルータのお化けのようなものの機能の一部)を使ってVPN接続する場合のみを話題にする。

はじめに

1つのVPCの1つのVGWにつき10本までという制限があるが、VGWとのコネクションは複数作ることができる。たとえば拠点Aが東京、拠点Bが長野だったとしても、それぞれの拠点からVPCに対してVPN接続できますよ、ということ。詳しい内容は世にあふれるAWS専門の技術ブログに任せるとして、ここで陥ったトラブルについて簡単に解説したい。

一応読み物として面白いように、トラブルを追った流れに沿って書いておく。

トラブルが発生したときの構成

1つのVPCの1つのVGWに対して、Direct Connectと呼ばれる専用線接続と、別のVPCに作ったVyattaインスタンスをCustomer Gateway機器に見立てたVPC間接続、合計2本のVPN接続を作るつもりだった。

ただ鬼ルールがあり、Direct Connectに関しては諸般の事情で触れることができない。Configurationやログなどは一切チェックできないし、どのような手順でいつ接続するかも概要しか分からない状態。さらに、Direct Connectについては自由に使える検証環境もなし。

トラブルの概要

VyattaによるVPC間接続だけであればうまく繋がっていたが、Direct Connectが追加されたと思われる時点でVyatta側のVPN接続が切れた。
検証時は何らかのトラブル発生時もVPN再接続またはVyatta再起動で回復していたので、同じように再起動してみたがどうやっても繋がらなくなった。

ログを見るとIPsecが途中で切られていることしか分からず、AWS Management Console上もBGPがupしかかったと思ったらDOWNするという流れしか分からない。Vyatta上でもshowコマンドで分かるのは、vtiはup状態であるがBGPの経路交換ができないことだけ。見事になにかがおかしいことしか分かってない、つまり全然なにも分からない。

検証(読み飛ばし推奨)

だいたい以下のような予想を立てて可能性を潰していった。

  1. Vyattaの設定間違え -> それまで普通に繋がっていたので可能性は低いが、自分で調べたり専門の人に問い合わせたりしたけど異常なし
  2. Direct Connect側でちょっと普通はないような操作をしていたため、VPNの接続先になっているVPC(VGW)固有の異常 -> AWSに問い合わせ
  3. Vyattaインスタンスに何らかの不具合がある -> 切り分け用に新しいインスタンスを立てて同じ設定を入れて試したが事象変わらず

なんとなく2番目がもっとも気になったので、問い合わせする一方でいろいろ作業していた。たとえば切り分け用のインスタンスを立てて、接続先IPアドレス以外は同じ設定を流し、切り分け用のVPCとVGWを作り、VPN接続してみたら、それは繋がった。
これはVGWなんじゃないかなあ……と疑いを深めたことが今考えれば一番の敗因。

そのうち自分は完全に深みにハマってしまったのだが、外から手伝ってくれた人があっさり全然違う環境で事象を再現させて解決してくれた。

解決した

AWSにはRoute Tablesというルータ的な役割を持つ機能があるが、インスタンスもそれぞれRouting Tableを持っていたりして、さらにVyatta自身ももちろんソフトウェアルータなので経路情報を持てる、つまり経路情報がいろんなところに分散されているということが問題を難しくしていただけで、要するに経路の問題だった。
自分で気づけなかったのが大変悔しくてさっきから無言で屈伸運動をしている。

分かる人にはこれだけで分かると思うので下のスクショを見てください。BGPのUPDATEメッセージのNLRI部分。
f:id:yuripop:20140411215938p:plain

0.0.0.0/0(デフォルトルート)が渡ってきてるのが分かると思う。VGWに対して広報された情報を経路交換しているので、つまりこの場合だと、Direct Connect側の設定がRoute Table~VGWの機能を介してVyatta側に渡されている。

するとこの情報がVyattaのRouting Tableに書き込まれる。しかも、見た限りでは書き込まれた経路情報の優先度が一番上にくるらしい。(他のルータは実装が違うかもしれないが未調査、今のところVyattaでだけ確認している)ひたすらshow ip routeしていると多分簡単に確認できる通り、こんな感じのルートが書き込まれている。

B>* 0.0.0.0/0 [20/0] via 169.254.252.30, vti1, 00:00:01

結果、IPsec接続のためにAWSが指定したアドレスまでパケットが辿りつけなくなり(vtiあたりでループする)、そのうちタイムアウトして対向側ではIPsecが切れたと認識され、IPsecの中でやり取りしているBGPのメッセージが完結しないうちにIPsec再接続が始まり、その繰り返し。

対策としては、以下のどちらか。

  • 0.0.0.0/0をBGPでadvertiseしないようにすること(※既にされている場合はRoute Tablesからも削除すること)
  • IPsec接続に使うアドレスをVyatta(自分)のStatic Routeとして指定しておくこと

深みにハマっていた自分としては拍子抜けするほどありふれたトラブルだったが、どちらでも解決可能であることまで確認した。

ちなみに非常に巧妙な罠だなと思うのは、AWSからVPN接続用のConfiguration Fileをダウンロードすると、0.0.0.0/0がデフォルトでadvertiseされる設定になっている、という点です。説明をよく読まずにそのまま流すと罠にハマるし、自分以外が罠にハマっただけで自分も引きずられることがあるので本当に注意したい。
まあ確かに接続先が1箇所だけなら何も悪さはしないのだが、ルート設計はちゃんとしたほうがいいと思います。

追伸:今はVPC Peeringという技術が登場したので、VPC間接続したいときはそっちを使ったほうが無難。