FreeBSD 11-STABLEでL2TP/IPsec Gatewayを作りました


前置き

 本ページは、L2TP/IPsec Gateway を実験する為のサーバを立てる上でのポイントを記述しております。
 本ページの記載内容をニッチな商用シーンや私的な運用シーンで利用する事を考えている方は、必ず、自分で充分な検証を実施してください
 次に内容は充分に検証しておらず、かなりの間違いが含まれている可能性があります
 又、それなりに細部の知識を必要とすると思われますので、そう言った部分は、他の文献をあたってください。

 想定される知識は、以下の通りです。

  1. 電子証明書における記載内容に関する知識(subjectAltName, keyUsage, extendedKeyUsage)
  2. RADIUSに関するプロトコル面の知識
  3. IPsec に関するプロトコル面の知識
  4. FreeBSD の運用面の慣習
  5. PC-Unix のコマンド、コンフィグレーションに関する操作
 上記は、一切説明なしで記述しております。

全体のイメージとゴール

 ざっくりとしたイメージは、以下の通りです。

 [L2TP/IPsec Gateway(FreeBSD 11-STABLE)] ← VPN → [Windows Client(Windows 7 L2TP/IPsec)]
 [IPsec 機能部:IPv6 KAME実装のracoon]
 [ユーザ認証機能部:mpd5]
 [RADIUS 機能部:FreeRADIUS]

 上記のような機能を用いて、以下を実現します。

各機能部の説明

1. Racoon(IPsec 機能部)

 IPsec における鍵交換と保護トンネルを構築する部分です。
 大きくIKE SA(フェーズ1)とIPsec SA(フェーズ2)に分かれます。

# 電子証明書フォルダ
path certificate ${電子証明書をハッシュ名で探せるフォルダ}

# IKE SA
remote anonymous
{
 # 鍵交換モード
 exchange_mode main;
 # 証明書
 certificate_type x509 ${ゲートウェイが提示する電子証明書ファイル} ${ゲートウェイの秘密鍵ファイル};
 # 証明書の検証方法
 verify_cert on;
 send_cert on;
 # 識別子の書式
 my_identifier asn1dn;
 peers_identifier asn1dn;
 ca_type x509 ${認証局チェインをひとまとめにしたファイル};
 # ネゴシエート
 passive off;
 # 鍵交換で提示する条件
 proposal {
  encryption_algorithm aes;
  hash_algorithm sha1;
  authentication_method rsasig;
  dh_group modp2048;
 }
}

# IPsec SA
sainfo anonymous
{
 encryption_algorithm aes;
 authentication_algorithm hmac_sha1
 compression_algorithm deflate;
# Windows L2TP/IPsec クライアント(RasMan)は、PFS を嫌う
# pfs_group 17;
 lifetime time 600 sec;
}

 主要な部分を太字で示しております。 大抵の場合、この辺りをサイトに合わせて決定する必要がある筈です。
 この構成を適用すると、以下のような挙動をする様子です。

 この設定を行い「setkey」コマンドでポリシーを適用することで、IPsec 部は稼働します。
 setkeyの部分は、FreeBSD ハンドブックに記載がありますので、割愛します。

2. mpd5(データリンクの確立機能部)

 Multi Protocol Daemonと命名されているデーモンで、実際のトンネルインターフェースとユーザ認証を受け付ける部分です。
 この機能部分は、一言では説明しづらい複雑な処理を担っている部分となります。
 内部挙動が複雑で、複数ノードを受け付ける上、ゲートウェイに必要な機能が多く実装されている印象です。
 拠点間VPN(グローバルIPアドレスを相互に持ち、静的にリンクされる運用)であれば、この部分は必要ない筈です。

startup:
	# コンソールやウェブサーバに接続ユーザを設定
	set user HoGeHoge ParaPara ${ロール}
	# コンソールソケットを127.0.0.1:5005に作成
	set console self 127.0.0.1 5005
	set console open

default:
	load lt2p_server

radius:
	# RADIUSクライアント設定を /etc/radius.conf から入力
	set radius config /etc/radius.conf
	# RADIUSサーバにNAS 登録
	set radius me ${RADIUS-Server}
	# RADIUS認証の機能を有効
	set auth enable radius-auth
	# RADIUSアカウンティング機能を有効
	set auth enable radius-acct
	# RADIUSメッセージ認証を有効
	set radius enable message-authentic
	# EAP をRADISに中継
	set eap enable radius-proxy

l2tp_server:
	set ippool add lt2p_pool ${VPN に割り当てるIPアドレスの開始IPアドレス} ${同、終了IPアドレス}
	create bundle template B_l2tp
	set iface enable proxy-arp
	set iface enable tcpmssfix
	set ipcp yes vjcomp
	# トンネルのゲートウェイ側に与えるIPアドレス(VPN)
	set ipcp ranges ${トンネルのゲートウェイ側IPアドレス} ippool lt2p_pool

	create link template L_lt2p l2tp
	set link action bundle B_l2tp
	set link enable multilink
	# ユーザ認証でCHAPとPAPを拒否、EAP を受容
	set link no pap chap
	set link enable eap
	set link keep-alive 0 0
	set link mtu 1280
	# radius に関する設定を読み込む
	load radius
	# 内部認証機能を無効
	set auth disable internal
	# L2TPゲートウェイのパケットを受け付けるインターフェース
	set l2tp self ${物理インターフェース}
	set l2tp enable length
	# L2TPの受付開始
	set link enable incoming

 前節と同様に主要な部分を太字で示しております。
 この構成を適用すると、以下のような挙動をする様子です。

 このデーモンは、デバイス、インターフェース、データリンク、認証をコマンドで実行するステートマシンのように動作するようです。
 ソケットでコンソールを提供できるので、コンソールを外向きのインターフェースにバインドすると、外からコンソールにアクセスできるように思われます。
 ほぼコマンドで挙動を変更でき、加えて、多くの保護機能を動的に切り替える事が出来るようです。
 ですので、コンソールをループバック以外にバインドするのは避けて、無用な機能を有効化するのは避けた方が良いと思います。

3. RADIUS(ユーザ認証機能部)

 こちらは、このページでは記述しません。 連携させる為には、電子証明書によるEAP が利用できるようにしておく必要があります。
 mpd5から観た場合、/etc/radius.confにRADIUSサーバの所在(ipアドレス、ポート)と共有秘密を設定してください。

電子証明書に関する条件

 特にWindowsに電子証明書を与える所で詰まると思います。
 填まる箇所としては、以下の所があります。

 これらを避ける為に証明書の目的を「全て」にするのは避けた方が良いと考えます。
 セキュリティレベルと利便性を下げ、他のアプリケーションが誤動作する恐れがあります。
 iPhoneは分かりませんが、Windows クライアントが受け付けた証明書であれば、それを準用することでAndroid端末でも利用できると思われます。

動作確認

 L2TPの良い所は、既存のLAN、インターネット回線だけで動作確認が出来る点があります。
 「ネットワークと共有センター」から「新しい接続またはネットワークのセットアップ」に従って操作することで、ローカルネットワークのみで接続確認が出来ます。
 接続先は、ホスト名にしておいた方が無難です。

結び

 以上で、VPN の実験環境が実現できると思います。

 尚、このページの内容を用いても、固定グローバルIPアドレスを持たない限り、インターネット側からVPN に接続するのは難しいと思われます。
 具体的には、IKE SAの装置間認証で電子証明書による相互認証を事前共有鍵方式にすることになります。
 この辺りはhostsで偽装することも可能かも知れませんが、外からと内側とつなぎ替えて運用する際に運用対処や不便が生じるように思います。
 この他にもVPN 上にDNS を立てたい、プロキシ構成を自動化したいといった場合にも対応できません。
 プロキシを用いた運用を行っている、又は、プロキシを自動構成にしていると、仮想ネットワーク側にパケットが流れず、VPN 側の望んだウェブサービスに接続できないという現象に見舞われると思います。
 スマートフォンだとプロキシが手動構成になっているのは、恐らく、プロキシによるウェブブラウザの対向ノードのフックが原因なのだと思われます。

 長くなりましたが、簡単にVPN を実現したい場合は、OpenVPN を用いた方が無難です。
 とはいえ、固定グローバルIPアドレスが必要と思われます。 ただ、どこぞのSaaSを使うなら、VPN を使わない方が無難じゃないかと思います。