2011/12/20に掲載された記事です
本稿では、SEILのVPNパススルー機能について解説します。
VPNパススルー機能の位置づけ
VPNパススルー機能は、NAT/NAPT配下のPCとインターネット上のホストとの間でVPN通信を可能にするための技術の一つです。
手法としては次の2つに大別できます。
- VPN通信をおこなうホストでNATの存在を仮定して工夫する方法(IPsec/IKE NAT Traversal)
- NAT をおこなうルータで、VPN通信の存在を仮定して工夫する方法(VPNパススルー)
通信の中継点で動作するのがVPNパススルー | v [VPN Client] ----------- [NAT] --------------- [VPN Server] ^ ^ | | +--------通信の両端で動作するのが NAT-T--------+
前者については、VPNソフトやネットワーク機器(SEIL含む)においてIPsec NAT-T機能として実装されており、後者についてはNAT/NAPT機器(SEIL 含む)の VPNパススルー機能として実装されています。
したがって、SEILをNAT装置として利用している環境で配下のホストに VPN通信を許したい場合は次のいずれかの手法を選択することになります。
- NAT Traversal 対応のVPNソフトを利用する
- SEIL は特別な処理はしないので、通信できるかどうかは VPNソフト次第です。
- SEILのVPNパススルー機能を利用する
- SEILのVPNパススルー機能で対応可能な通信でなければ利用できません。
機能的には前者のほうが有利なのですが、利用する機器を選べなかったり、利用する機器を特定できないのであれば後者を利用するしか手はありません。
(きちんとした実装であれば)これらの機能が衝突することはありませんので、両方の方式を同時利用しても構いません。
とはいえ、実装依存の部分ではありますので、NAT対応機能があるVPNソフトでは設定変更が必要となる可能性があります。
ここでは、SEILのVPNパススルー機能を利用する場合について記述します。
VPNパススルー機能の設定
NAT/NAPTの設定
SEILではVPNパススルーを明示的に示す設定はありません。
VPNパススルーとNAT機能の対応は以下の通りです。
NAPT
- 機能が有効になっていれば、自動的にVPNパススルーが利用できるようになります(ただし、PPTPについてはTCPのポート1723を使用している必要があります)。
SNAPT(プライベート網にサーバを設置)
- IPsec (ESP) は、SNAPTでプロトコル50を指定することで対応できます。
- PPTPは、SNAPTでTCPのポート1723を指定することで対応できます。
SNAT/DNAT
- ポートやプロトコルではなく、アドレス単位で変換しますので、そもそも問題ありません。
VPNパススルーで扱えないケースは以下の通りです。
- IPsecでAH を利用している場合
- これはヘッダ書き換えが改ざんとみなされますので、通信できません。
- NATに厳しいVPN 実装を利用している場合
- 存在するかどうかは未確認ですが、IKEにはアドレス変換を検出する機能があります。アドレス変換を検出して、かつNAT-Tが無効に設定されている場合は通信をしないという実装も存在する可能性があります。
- IPsecやPPTP以外のVPNプロトコルの場合
- SEIL側で特別な対応はしていないので、動かない可能性があります。TCP/UDPベースのプロトコルであれば動作する可能性は高いと思われます。
filterの設定
VPNで利用するそれぞれのプロトコルは、VPNクライアント/サーバ及び中継する装置のパケットフィルタにおいて許可(pass)される必要があります。
IPsec関連
- IPsecパケットを通すこと(ESP: プロトコル番号 50)
- IKEパケットを通すこと(UDP 宛先ポート 500)
- VPNパススルーではありませんが、IKE NAT-T を想定する場合は追加でポートを開ける必要があります(UDP 宛先ポート 4500)
- IKE,IKE NAT-Tでは、宛先ポートと送信元ポートの両方が一般的に500または4500のパケットになりますが、送信元ポートはNAT/NAPTにより変換される場合があるため、送信元ポートのpass/block設定には注意が必要です。
PPTP関連
- コントロールコネクションのパケット(TCP 宛先ポート 1723)を通すこと
- トンネルコネクションのパケット(GRE: プロトコル番号 47)を通すこと
VPNパススルーを利用する上での注意点
先着一名問題
IPsecをパススルーする場合、SEIL ではセッションを識別できないため、次のような制限があります。
- 1台のVPNサーバに対しては、最初に通信を始めたクライアントは 1台しか通信できない
- 他のクライアントが通信しようとしても、サーバからの応答パケットは全て最初のクライアントに転送される
NATセッション切れ問題
VPNでの通信はSEILのNATセッションに依存しています。したがって、NATセッションの維持時間がVPN通信の快適度に繋がる可能性があります。
TCPやUDPであれば通信時間は比較的短いかもしれませんが、VPNでは長時間繋ぎっぱなしで、パケットが流れないというケースも多いでしょう。この場合、SEILのNATセッションが時間切れで消える可能性があり、VPNが安定しないという申告が上がってくることがありえます。
対策としては、次のような方法が考えられます。
- SEIL側のセッション維持時間を長めに設定する
- VPNクライアント側でセッションを維持するためのパケット(keep alive等)を流す
もちろん、SEILの再起動によってもセッション情報は失われます。
MTU(フラグメント)問題
NAT対象のパケットが経路上でフラグメント化されてしまい、かつ順番が入れ替わると、正しくNATできないことがあります。これは経路上にMTUの小さな経路(トンネルなど)がある環境では発生する可能性があります。
このとき、順番が入れ替わったパケットを頻繁に破棄することになるため、スループットが出ないという申告になると思われます。
この様な場合はフラグメントされたパケットの整列機能(fragment-requeueing)を有効にすると問題が解決する可能性があります。
option ip fragment-reqeueueing on
フラグメントされずに、 MTUが小さな経路の手前でパケットが破棄される可能性もあります。
こちらは綺麗に対処するのは難しいですが、VPNクライアント側でMTUを調整できるのであれば、小さくすると解決するはずです。
あるいは、SEILのWAN側I/FのMTUを絞って、SEILでフラグメントするようにすると解決する可能性がありますが、この場合はネットワーク全体のスループットが低下します。
VPNソフト依存の問題
すべてのVPNソフトを検証しているわけではありませんので、一部のVPNソフトで通信できないこともありえます。このような場合、以下がチェックポイントとなるでしょう。
- VPNソフトはどのようなエラーを表示しているか
- 何が原因であるかが表示されている可能性があります。
- VPN ソフトのNAT対応機能が誤動作をしていないか
- 可能であれば、NAT対応機能が有効の場合と無効の場合の両方で試してください。
VPNパススルーの動作詳細
VPN通信は一般的に内容が暗号化されており、プロトコルもTCPやUDPではないため、通常のNAPT実装ではケアできません。
しかし、VPN通信で利用されるプロトコルをうまく扱うことで、制限はあるもののNAPT配下からVPN通信が可能になることがあります。
SEILのVPNパススルー機能が対応するプロトコルは、IPsec(ESP)とPPTPです。
TCPとUDPではプロトコル番号とポート番号をヒントにアドレス変換を実行しますが、VPNの場合も同様にアドレス変換を実行します。
ESPの場合
ESPのパケットをNAT越しに転送する機能は、一般的に「IPsecパススルー」と呼ばれます。ESPの場合、アドレス変換のヒントになる情報としては
- IPヘッダの送信元、送信先
- IPヘッダのプロトコル番号(ESP)
- ESPヘッダの SPI (Security Parameter Index)
がありえます。このうち、SPIについてはIKEにより暗号化された状態で折衝がおこなわれ、in/out で別々のSPIが割り当てられます。このため、SPIを見ることはできるのですが、in/out の対応を知ることはできません。
たとえば、以下のような通信があるとしましょう。
[PC1] ---SPI:1--->+ <--SPI:2----+ | +------- [SEIL]--- SPI:1, SPI:3 ----> [VPN Server] | <-- SPI:2, SPI:4 ----- [PC2] ---SPI:3--->+ <--SPI:4----+
ここで、SPI:1 と SPI:2、SPI:3 と SPI:4 が対であるということを知っているのは、PC1, PC2, VPN Serverのみで、SEILは知ることができません。
もしSEILがNAPTしているとするならば、
[PC1] ---SPI:1--->+ <-SPI:不明--+ | NAPT +------- [SEIL]--- SPI:1, SPI:3 ----> [VPN Server] | <-- SPI:2, SPI:4 ----- [PC2] ---SPI:3--->+ <-SPI:不明--+
という状態になります。SPI:1 と SPI:3 は識別でき、アドレス変換は可能なのですが、VPN Serverからの戻りである SPI:2 と SPI:4 については、双方とも宛先は NAPT後のSEILのアドレスであり、これを逆変換することができません。
そこで、SEILではSPIは参考にせず、「ESPであればNAPTの逆変換の対象にする」というセッションを作成します。先にESPによる通信を開始したのがPC1であれば、VPN Serverから受信したESPのパケットは一律PC1へ転送します。先に通信したのがPC2であれば、一律PC2へ転送します。
[PC1] ---SPI:1--->+ <--SPI:2,4--+ | NAPT/VPN パススルー +------- [SEIL]--- SPI:1, SPI:3 ----> [VPN Server] | <-- SPI:2, SPI:4 ----- [PC2] ---SPI:3--->+
これにより、PC1 は ESP のパケットをNAT越しにやりとりできることになります。しかし、PC2 は ESP のパケットを受信することはできません。これを俗に「先着一名問題」と呼んでいます。
この問題が発生するのは、PC1とPC2が同じVPN Serverと通信した場合です。もし、VPN Serverが異なるのであれば、この問題は発生しません。
[PC1] ---SPI:1--->+ +---SPI:1--->[VPN Server1] <--SPI:2----+ +<--SPI:2---- | | +------- [SEIL]---------+ | | [PC2] ---SPI:3--->+ +---SPI:3--->[VPN Server2] <--SPI:4----+ +<--SPI:4----
なぜならば、SEILが受信するパケットは、送信元アドレス(VPN Server1 or VPN Server2)が異なるためです。この場合、src: VPN Server1, protocol: ESP であれば PC1 へ、src: VPN Server2, protocol: ESP であればPC2へ転送します。これをベンダによっては、「IPsecパススルーマルチセッション」と呼んでいることがあります。SEILでは特に呼び分けはしておらず、VPNパススルーもしくはIPsecパススルーです。
PPTPの場合
PPTPはコントロールコネクション(TCP:1723)とトンネルコネクション(GRE)の 2 つのプロトコルを組み合わせて動作します。
コントロールコネクションは通常のTCPですが、PPTPであることを認識すると必要に応じて Call ID の書き換えが行われます。PPTPであるかどうかはTCPのポート番号により判定しています。内容的には SIP proxy に近い動作ですが、nat proxy コマンドで port/protocol を指定することはできません。
(PPTPで1723以外のポートを使うことは事実上無いと考えられます(Windwosではポート番号の変更は出来ないようです))
トンネルコネクション(GRE) については、アドレス変換のヒントとなる情報には以下があります。
- コントロールコネクションでの折衝内容
- IPヘッダの送信元、送信先
- IPヘッダのプロトコル番号(GRE)
- GRE ヘッダの Call ID
- PPTP用のextented GREであるため、通常のGRE とは少々異なります(セッション情報が入る)
Call IDの決定は暗号化されずに行われますので、SEILはCall IDを追跡・書き換えすることが可能です。つまり、Call IDをTCP/UDPのポート番号相当として扱えます。
したがって、PPTPに関しては普通のNAPTと同じように、セッション単位での管理が可能となり、ESP のような先着一名問題は発生しません。