FreeBSD 13.1-RELEASEのGENERIC kernelでは標準でIPsecに対応しています。さて、これでIPsecの設定が簡単になると思ってみたら、いろいろあったのでメモ代わり。
IPsecを利用したVPNではL2TP/IPsecがよく利用されていますが、どうせ端末をIP的に繋ぐだけなら素のIPsecだけで利用した方がMTU的に効率が良さそうなので、L2TPは使わない構成にしています。鍵交換を自動化するためにstrongswanを使って、いわゆるダイヤルアップVPNを構築します。
ひとまずここでは基本的な接続の設定までを紹介するので、あとは自分で証明書認証にするとか、お気に入りのcipher suiteを指定するとかしてください。
IKE実装としてstrongswanを導入します。これだけ。
# pkg install strongswan
ひとまず一番簡単な事前共有鍵認証(PSK)で。strongswanの設定は/usr/local/etc/swanctl/conf.d/のconfファイルを読み込むようになっているので、ここに適当な名前で設定ファイルを作成します。例えば、conn.confとかの名前のファイルを置けば大丈夫。以下の例ではIPv4とIPv6の通信全てIPsecトンネルを通過させる設定になっています。localがサーバ側、remoteがクライアント側です。
クライアントに割り当てるアドレス空間は、上流のルータからこのサーバに向けて静的にルーティングしています。IPv6/IPv4の両方のIPアドレスをクライアントに動的に割り当てるには、それぞれのpoolを設定し、両方をconnection側のpoolsで指定すればよさそうでした。
クライアントにはpoolからIPアドレスが一つずつ、IPv6は/128、IPv4は/32が動的に割り当てられます。サーバは上流のルータから受け取ったパケットがIPsec SAに合致した場合はESPに包んでフォワードし、それ以外の場合は破棄します。
つまり、このサーバはルータとして動作することになります(デフォルト経路やIPアドレスの設定を手動でやらないといけない)。
IPv4をNATしたい人は上流でNATするなり、pfでNAT設定するなどしてください。
# /usr/local/etc/swanctl/conf.d/conn.conf
connections {
remote-vpn {
remote-addrs = %any
local_addrs = <サーバのホスト名もしくはIPアドレス>
pools= pool-v4, pool-v6
proposals = aes128-sha1-modp2048,aes128-sha1-modp1024,default
children {
vpn {
start_action = none
local_ts = 0.0.0.0/0, 0::0/0
hostaccess = yes
esp_proposals = aes128-sha1-modp2048,aes128-sha1
-modp1024,default
}
}
local-0 {
auth = psk
id = %ltサーバのIDとかホスト名とか>
}
remote-0 {
auth = psk
}
}
}
pools {
pool-v6 {
# addrs = 2001:db8:beef::/120
addrs = <クライアントに割り当てるプール、/120とかで十分>
dns = <名前解決用ネームサーバ>
}
pool-v4 {
# addrs = 10.0.0.0/24
addrs = <クライアントに割り当てるプール、/24とかで十分>
dns = <名前解決用ネームサーバ>
}
}
secrets {
ike- {
secret = "<適当な共有鍵>"
}
}
ルータ設定などは/etc/rc.conf。ルーティングループを起こさないようにdiscard経路を設定しています。FreeBSDではdisc0インタフェースを作り、そこに経路を向ければ良いみたい。
# /etc/rc.conf
ipv6_gateway_enable="YES"
gateway_enable="YES"
cloned_interfaces="disc0"
ipv6_static_routes="discard"
ipv6_route_discard="<クライアントに割り当てるアドレス空間> -iface disc0"
static_routes="discard"
route_discard="<クライアントに割り当てるアドレス空間> -iface disc0"
strongswan_enable="YES"
FreeBSDがクライアントの場合は、設定でauto=startにすれば能動的にセッションを張りにいきます。
Mac OSXの場合は、新しいネットワークの追加でインタフェースを「VPN」、VPNタイプを「IKEv2」、サービス名は自分の識別用に適当に。その後、サーバアドレスを「サーバのホスト名」、リモートIDも上記のipsec.confで設定したように「サーバのホスト名」、ローカルIDは自分の識別用に適当に。認証設定は「なし」にした後、共有シークレットに上記のipsec.secretsで設定した「適当な共通鍵」を入力して完了。「適用」後接続で完了。OSXではipsec0インタフェースが作られるため、ここをtcpdumpすると暗号化前&復号化後のパケットが見れます。
サーバ側ではセッションが確立しても特に新たなインタフェースは見えず、経路情報にも変化がありません。以下のipsec関連のコマンドでSAが意図した状態になっているか確認しましょう。
# ipsec status
# setkey -D