2013年12月20日金曜日

Vista(HomePremium)からNATの外に出てWindows7(Pro)にL2TP/IPsecでVPN接続するテスト記録

2台のPCをL2TP over IPsecでVPN接続してみた。

[VPNクライアント・発信側]
Windows Vista HomePremium SP2 64bit
コンピュータ名:CliPC

[VPNサーバ・着信側]
Windows7 Professional SP1 32bit
コンピュータ名:SerPC
物理NICのIPアドレス:G.G.G.1 (グローバルアドレスのつもり)
仮想LoopbackのIPアドレス:192.168.22.1/24

[NAT対応]
NATを経由する L2TP over IPsec を使うためには、
NAT Traversal というのを有効にする必要があるらしい。
クライアント と サーバ 両方でレジストリの変更をする。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PolicyAgent
で
AssumeUDPEncapsulationContextOnSendRule 
DWORD(32ビット)値:1
を作成し、PCを再起動して作業完了。

クライアントもサーバも両方がNATの内側なら、
DWORD(32ビット)値:2
に、設定するらしい。

[[参考]]
How to configure an L2TP/IPsec server behind a NAT-T device in Windows Vista and in Windows Server 2008
http://support.microsoft.com/kb/926179/
※Windows7でも、同じ作業が必要らしいので行った。

[Microsoft管理コンソール(MMC)のショートカットを作成]
次の二つ
 セキュリティが強化されたwindowsファイアウォール
 証明書マネージャ(コンピューターアカウント・ローカルコンピューター用)
 ※certmgr.mscの通常起動では、現在のユーザ用で別物なので注意
は何度も使うので、管理者権限のあるユーザ+UACでmmc.exeを起動し、
スナップインの追加と削除でこの二つを追加し、
名前を付けて保存 で、ショートカットを作成した。

[セキュリティが強化されたwindowsファイアウォールの設定]
クライアントは、L2TP(UDP1701)宛の送信、
サーバはL2TP(UDP1701)宛の送受信を許可しておけばいけた。
もっと少ない許可でいけるかもしれないが、試していない。
※IPsecは、UDP500、UDP4500(NAT利用時)、ESP(プロトコル番号50 NAT非利用時)
 あたりを使うを使うらしいが、[NAT対応]による影響か、IPSecは特別扱いか、
 コアネットワークTeredo 許可(サービス はUDP全ポート)の影響か、
 理由は分からないが、これらのポート、プロトコルについては何も設定しなかった。
PPTPとSSTPは、許可を無効にしておく。
※サーバがPPTPを受け付けないようにするには、
 ココで設定するしか方法がわからなかった。

ちなみに、サーバ側がNAT内側ならば、NATの設定で
UDP500とUDP4500を当該サーバに転送すればよいらしい。
UDP1701は不要で、 IPSecパススルー という機能は、
NAT Traversalを用いる場合に使っては駄目らしいが分からない。

[[参考]]
iPhoneをVPNで @ 勝手にまとめウィキ - L2TP/Windows7
http://www58.atwiki.jp/iphonevpn/pages/17.html

[認証に事前共有キーを使ってL2TP IPsec VPN接続]
[[サーバ側の準備]]
証明書マネージャ で 個人 に 信頼されたルート証明機関 証明書 から、
有効期限内で目的 が <全て> の証明書を1つコピーする。
Microsoft Root Certificate Authority というのを使った。
※これはおまじない的な作業だが、必要らしい

ファイアウォール で セキュリティの規則 を 新規作成 する。
 カスタム
 エンドポイント1 を G.G.G.1 エンドポイント2は 任意
  ※NAT経由なら使うことはなさそうだが、エンドポイント2を指定すれば、
  クライアントのIPアドレス(通常グローバルアドレス)毎に異なる
  事前共有キー を設定できると思われる。
 受信接続と送信接続の認証を要求する
 詳細設定 で 追加 事前共有キー 
 プロトコル UDP エンドポイント1 を 1701 エンドポイント2は 任意
 ドメイン・プライベート・パブリック

ネットワーク接続(NIC一覧) ファイル メニュー から 新しい着信接続 を作る。
 ※VPN接続のクライアント認証で有効な ユーザ(と、その パスワード) を
  既存のユーザから選ぶが、VPN接続後にファイル共有や
  リモートデスクトップに使うIDとは別でかまわないっぽい。
  クライアント認証に、一応、長いパスワードを使いたいので、
  VPN接続のクライアント認証専用のユーザを追加することにした。
 作った着信の プロパティ IPv4 プロパティ で、クライアントに割り当てる
 IPアドレス範囲を設定する。仮想LoopbackのIPアドレスと同じサブネットの
 192.168.22.10 から 99 にした。

[[クライアント側の準備]]
新しい接続またはネットワークのセットアップ で、サーバへの接続を作成する。
作成後 プロパティ で詳細設定をしていく。
 セキュリティ タブ
  L2TP/IPsec  詳細設定で 事前共有キー 
 ネットワーク タブ
  IPv4 プロパティ 詳細設定 
   リモート ネットワークでデフォルト ゲートウェイを使う を解除

[[接続実行]]
VPN接続を数クリックで実行でるようになり、
クライアントからサーバの仮想Loopback(192.168.22.1)へアクセスできる
ようになった。
※ファイアーウォールの設定次第ではpingの反応すらないのは当然

バッチファイルで接続を実行するなら、
VPN接続のプロパティ オプション タブ で
接続中の進捗表示と名前、パスワードの入力を求める
を解除しておいて、
rasphone.exe -d 接続先の名前
を実行すればよい。

L2TP/IPsecで接続できてるか確認するには、
ファイアウォール 監視 セキュリティアソシエーション を見れば良いっぽい。

[[オマケ]]
IPsecに関連しそうなWindowsの サービス については以下の通り
 IKE and AuthIP IPsec Keying Modules 必須っぽい
 IPsec Policy Agent 任意っぽい

[[参考]]
クライアント版WindowsをL2TP/IPSecサーバーにしてiPhoneから接続する: 超私的まとめも
http://zzt231.cocolog-nifty.com/blog/2012/09/windowsl2tpipse.html


[認証に証明書を使ってL2TP IPsec VPN接続]
[[証明書の作成]]
debian wheezy openssl パッケージを使って、
個人的なCA(で、1つの証明書+秘密鍵)を作成し、
証明書については当該CA(秘密鍵)が発行する
サーバ用の 証明書+秘密鍵 (ファイル名 SerPC.p12) と
クライアント用の 証明書+秘密鍵 (ファイル名 CliPC.p12) を
作成した。CAの証明書は、SerPC.p12 でも CliPC.p12 でも、
Windowsでインポートすると一緒にインポートされる。

私は勘違いしていたのだが・・・
通常設定、あるいは仕様で、Windows Vista,7 は、
認証に証明書を使ってL2TP IPsec VPN接続 をする時は、
VPNクライアントとVPNサーバーの両方が、同一のCA(秘密鍵)で発行を受けた
証明書+秘密鍵 を持っていないといけない。
すなわち、VPNクライアントはCA1による証明書、
VPNサーバはCA1とは別のCA2による証明書になっている
証明書+秘密鍵 では、たとえ、CA1とCA2の両方のCAの証明書を
VPNクライアントとVPNサーバーの両方で、信頼されたルート証明機関 に
インポートしたとしても、VPN接続はできない。
そのため、Verisign を始め、信頼されたルート証明機関 に、
OSインストール時から入ってる証明機関から発行された証明書+秘密鍵
を持っている外部の知らないホストが、VPNサーバに接続してきた場合、
証明書の認証は通過して、あとはIDとパスワードだけで接続できてしまう・・・
という心配は無いっぽい。

IPSec の特段の注意事項
http://technet.microsoft.com/JA-JP/library/cc757905.aspx

ちなみに、VPNクライアントとVPNサーバーの両方が
同じ 証明書+秘密鍵 を使った場合、VPN接続はできる。


SerPC.p12 と CliPC.p12 の作成手順の抜粋は以下の通り。

mkdir oreore-ca/
cd oreore-ca
cp /usr/lib/ssl/misc/CA.sh ./
cp /etc/ssl/openssl.cnf ./
vi CA.sh
diff CA.sh /usr/lib/ssl/misc/CA.sh
< if [ -z "$DAYS" ] ; then DAYS="-days 7300" ; fi # 20 year
< CADAYS="-days 7300" # 20 years
※-days オプション で 証明書の有効期限を 20年に設定
---
< REQ="$OPENSSL req -config ./openssl.cnf $SSLEAY_CONFIG"
< CA="$OPENSSL ca -config ./openssl.cnf $SSLEAY_CONFIG"
※-config ./openssl.cnf の追加で、設定ファイルのパスを設定
---
<     $REQ -new -nodes -extensions v3_req -keyout newreq.pem -out newreq.pem $DAYS
※-newreq-nodes の部分で、設定ファイル内の [ v3_req ] 部分を有効にした。
---
<     $CA -policy policy_anything -extensions v3_req -out newcert.pem -infiles newreq.pem
※-signreq の部分で、設定ファイル内の [ v3_req ] 部分を有効にした
 [ v3_req ] では、証明書 の 目的 等を設定している。
 [ v3_req ] が無効なら、証明書 の 目的 は すべて になるようだ。
 ただし、通常、Windows7のVPNサーバは、目的 の設定を無視するようだ。
 無視しないようにする方法はわからなかったので、
 特に、クライアント認証(発信)では使うが、
 サーバ認証(着信)には使いたくない証明書があっても、
 VPN着信を作っていた場合、サーバ認証に使ってしまう。


vi openssl.cnf
diff openssl.cnf /etc/ssl/openssl.cnf
< #attributes  = req_attributes
※'extra' attributes とか、入力の省略
---
< countryName_default  = JP
※証明書サブジェクトのデフォルト値変更
---
< extendedKeyUsage = clientAuth,serverAuth
※[ v3_req ] 部分において、発行する 証明書 の 拡張キー使用法(EKU) を
 サーバー認証 と サーバ認証 に設定。
 ただし、Windows7のVPNサーバは、このあたりの設定を無視するので、
 意味が無い。気分の問題。

CA.sh -newca
※CAの情報を入力していく。
 一応、クライアント サーバ いずれとも無関係な感じにしておくと
 無難かなと思ったので、Common Name とかは、気をつけておいた。
openssl x509 -in ./demoCA/cacert.pem -out ./demoCA/cacert.crt
※これはオマケの処理だが、WindowsでCAの証明書のみを
 インポートしてみたいときは、これで作ったcacert.crtを使う。

CA.sh -newreq-nodes
※サーバ用の証明書を作る。注意点は、
 Common Name (e.g. server FQDN or YOUR name)で、
 サーバのDNS名を設定した方がよさそう。
 VPNクライアントが、VPNサーバをIPアドレスではなくDNS名で指定し、かつ、
 サーバーの証明書の名前と使用法の属性を検証する を有効にしていたとき、
 この2つのDNS名が一致するか確認することで、
 サーバの成りすまし防止ができるっぽい。
CA.sh -signreq
CA.sh -pkcs12 "SerPC Certificate"
mv newcert.p12 SerPC.p12

CA.sh -newreq-nodes
※クライアント用の証明書を作る。
 Common Name (e.g. server FQDN or YOUR name)は、
 クライアントのコンピュータ名を使っては!!!いけない!!!。
 コンピュータ名と一致すると、正当性の確認処理か何かが
 行われるためか、VPN接続を実行できなかった。
 DNS名も使わない方がよいかもしれない、わからない。
CA.sh -signreq
CA.sh -pkcs12 "CliPC Certificate"
mv newcert.p12 CliPC.p12

以上で証明書の作成は完了。

[[[参考]]]
セキュリティ・PKI/OpenSSL - yanor.net/wiki
http://yanor.net/wiki/?%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%BBPKI%2FOpenSSL

6-6(1)CAの構築 : 基礎から学ぶ無線LANの設定と設計
http://www.viva-musen.net/archives/21025477.html

[[サーバ側の準備]]
証明書マネージャ で 個人 に サーバ用の 証明書+秘密鍵 をインポートする。
一緒にインポートされたCAの証明書を、信頼されたルート証明機関 に移動する。
ファイアウォール での設定は、通常不要。
※事前共有キーでも証明書でも着信可にする方法は不明。
 特定の証明書+秘密鍵だけを着信可にする方法不明。
 エンドポイントの設定で、クライアントアドレス毎に
 選ぶことはできると思う。
ネットワーク接続(NIC一覧) ファイル メニュー から 新しい着信接続 を作る。
 ※VPN接続のクライアント認証で有効な ユーザ(と、その パスワード) を
  既存のユーザから選ぶが、VPN接続後にファイル共有や
  リモートデスクトップを使うIDとは別でかまわないっぽい。
  VPN接続のクライアント認証だけに使うユーザを作って使うことにした。
 作った着信の プロパティ IPv4 プロパティ で、クライアントに割り当てる
 IPアドレス範囲を設定する。仮想LoopbackのIPアドレスと同じサブネットの
 192.168.22.10 から 99 にした。

これにより、同じCA(秘密鍵)から発行を受けた、
証明書+秘密鍵 を持つクライアントからの接続を受け付ける準備ができた。

[[クライアント側の準備]]
証明書マネージャ で 個人 に クライアント用の 証明書+秘密鍵 をインポートする。
一緒にインポートされたCAの証明書を、信頼されたルート証明機関 に移動する。
※証明書+秘密鍵 の発行時 または プロパティ で証明書の目的を
 制限、限定できるような感じになっているが、残念ながら無視される。
 着信に使うつもりがなくても、VPNの着信接続が作られてあれば、
 この 証明書+秘密鍵 が着信にも有効となってしまう。回避方法不明。
新しい接続またはネットワークのセットアップ で、サーバへの接続を作成する。
作成後 プロパティ で詳細設定をしていく。
 セキュリティ タブ
  L2TP/IPsec  詳細設定
   [o]認証に証明書を使う
    [v]サーバーの証明書の名前と使用法の属性を検証する
    ※サーバの証明書+秘密鍵作成時、サーバのDNS名を正しく設定した場合のみ
 ネットワーク タブ
  IPv4 プロパティ 詳細設定 
   リモート ネットワークでデフォルト ゲートウェイを使う の チェックを解除

[[接続実行]]
VPN接続を数クリックで実行でるようになり、
クライアントからサーバの仮想Loopback(192.168.22.1)へアクセスできる
ようになった。
※ファイアーウォールの設定次第ではpingの反応すらないのは当然

バッチファイルとかで接続を実行するなら、
接続のプロパティ オプション タブ で
[ ]接続中の進捗表示と名前、パスワードの入力を求める
にしておいて、
rasphone.exe -d 接続先の名前
を実行すればよい。

L2TP/IPsecで接続できてるか確認するには、
ファイアウォール 監視 セキュリティアソシエーション を見れば良いっぽい。

[[オマケ]]
IPsecに関連しそうなWindowsの サービス については以下の通り
 IKE and AuthIP IPsec Keying Modules 必須っぽい
 IPsec Policy Agent 任意っぽい

[[参考]]
コンピューター証明書による認証を使用して RRAS を構成する
http://technet.microsoft.com/ja-jp/library/dd458982.aspx

How to configure verification of additional fields in peer certificates during IKE negotiation for L2TP/IPsec tunnel connections in Windows Vista
http://support.microsoft.com/kb/926182

0 件のコメント:

コメントを投稿