(FreeBSD6) racoon2 による IPsec の設定

はてブ数 2007/01/18Linux

racoon2 とは

WIDE Project 内の Racoon2 Project によって開発されている、racoon に代わる IPsec 用 IKE deamon(鍵交換デーモン)です。現時点で 20061228a が最新版として公開されています。詳細は不明ですが、どうやらIKEv2に合わせ、全面的に書き直されているようで、従来のracoonとは設定ファイルの書式が異なります

ftp://ftp.racoon2.wide.ad.jp/pub/racoon2/

racoon2 による設定事例はほとんど見ることができないので、ここに事例とハマりどころを記しておきます。質問などありましたら、答えられる範囲でお答えします。なお、IPsecの詳細については割愛します。

設定の目的

  • IKEv1 を使用して鍵交換を行い、Linux 2.6.x との間で IPsec 通信路を設定する。
  • 事前共有鍵方式(pre_shared_key : psk)による鍵交換を行う。
  • ESP + トンネリングモードにより、それぞれルータとなっている FreeBSD、Linux 間でVPN接続を行う。
  • FreeBSD、Linux はそれ自身が PPPoE によるセッションを張っており、NATサーバを兼ねている。

全体像は図で示すと次のとおりです。ここでは、FreeBSD側の設定のみ述べます。

192.168.10.0/24 <--LAN--> FreeBSD (210.11.11.11) 
   <--Internet--> (210.22.22.22) Linux <--LAN--> 192.168.20.0/24

ports から racoon2 をインストール

FreeBSD では /usr/ports/security/racoon2 に Ports がありますので、そこから make install します。Linuxなどと接続する場合、IKEv1 プロトコルが必須になりますが、20060712a版はIKEv1に対応していません。Ports を最新版に置き換えるなどして、必ず 20061228a 以降のバージョンをインストールしてください。*1

# cd /usr/port/security/racoon2
# make
# make install

なお、旧racoon由来のツールは /usr/ports/security/IPsec-tools にあります。

*1 : Makefile などを見ることで確認できます

racoon2 による IPsec の設定上の注意

まず、racoon2 を設定する際は、次の点に注意してください。ハマります。

[FreeBSD] gif0インタフェースは必要ない

FreeBSDの handbook はじめ各種の記事には gif インタフェースが必要とかかれていますが、まったく必要ありません

gifインターフェイスを必要する説明では、gif インターフェイス自身が持っているIPのカプセル化機能を用いてVPNを構築し、このときのGLOBAL IP(インターネット)間の通信を IPsec にして暗号化する趣旨で書かれています。このことから、gif と同じカプセル化を実行できない Linux などと相互接続することは不可能ですし、IPsec自体にカプセル化の機能がありますので、多重にカプセル化するのはナンセンスです。

[FreeBSD] /etc/IPsec.conf は必要ない

同様に rc.conf に IPsec_enable の記述も必要ありません。racoon2 では、setkey によるこれらの設定を、racoon2.conf の中身を反映し自動で行ってくれます。

静的 routing は必要ない

IPsec 対象パケット(from 192.168.10.0/24 to 192.168.20.0/24)は、LAN を抜け FreeBSD のカーネルに入った時点で IPsec によりカプセル化(from 210.11.11.11 to 210.22.22.22) され Linux マシンに届けられます。この Linux マシンでカプセルを解かれ(from 192.168.10.0/24 to 192.168.20.0/24)、相手方LAN内に到達します。

この状況からもわかるとおり、FreeBSD、Linux のそれぞれのマシン上で特別な静的routingは不要です。下手に設定することで、IPsecがきちんと動作しなくなりますので注意してください。*2

psk.txt には秘密鍵(パスフレーズ)のみを書く

racoon2.conf 内において、 remote の設定項目を例えば次のように書いたとします。

remote Linux-machine {
	ikev2 {
		(略)
		pre_shared_key "${PSKDIR}/linux.psk";
        };
};

このとき、linux.psk には Linux-machine により指定した IPsec 通信相手との共有鍵のみを直接記述します。ここを間違えると大ハマリします。次のように書いてはいけません

(うまく動作しない例)
210.11.11.11	test1
210.22.22.22	test2

これには2つの勘違いがあります。IPsec における事前共有鍵は、自分(FreeBSD)と相手(Linux)の通信において、ただ1つしか存在しません。

もう1つが重大な誤りです。旧racoonでは、このファイルの書式は問題ないのですが、racoon2 では、psk ファイルの中身を一切解釈しません。pskファイル全体で1つの秘密鍵を示します。例えば、秘密共有鍵が "test" だったとき、pskファイルの中身が

test

という 4byte のファイルなら正しく動作しますが、

test[LF]

という改行を含めた 5byte のファイルである場合、鍵交換に失敗します。

またpskファイルのパーミッションは必ず600にしておきます(600でないと、デーモンの動作に失敗すると思います)。

*2 : FreeBSD から直接 192.168.20.0/24 へ向けてパケットを投げる場合は静的routingの設定が必要ですが、詳細は後述します。基本的には必要ないと覚えておいてください。

racoon2 による IPsec の設定例

racoon2.conf を置いておきます。以下は抜粋です。

remote remote@ip210.22.22.22 {
    acceptable_kmp { ikev1; };
    ikev1 {
	logmode normal;
	my_id ipaddr 210.11.22.33;		←相手が自分を識別するときのID代わり
	peers_id ipaddr 210.22.22.22;		←通信相手を識別するID代わり
	peers_ipaddr 210.22.22.22 port 500;	←通信相手のIKE deamon
	kmp_enc_alg { 3des_cbc; };
	kmp_hash_alg { sha1; };
	kmp_dh_group { modp2048; };
	kmp_auth_method { psk; };
	pre_shared_key "${PSKDIR}/210.22.22.22"; ←この通信のpskのみが書かれたファイル
	exchange_mode main;
    };
};
selector 31 {
	direction outbound;
	src 192.168.10.0/24;
	dst 192.168.20.0/24;
	upper_layer_protocol "any";
	policy_index ip210.22.22.22;
};
selector 32 {
	direction inbound;
	dst 192.168.10.0/24;
	src 192.168.20.0/24;
	upper_layer_protocol "any";
	policy_index ip210.22.22.22;
};
policy ip210.22.22.22 {
	action auto_IPsec;
	remote_index remote@ip210.22.22.22;
	IPsec_mode tunnel;
	IPsec_index { IPsec_esp; };
	IPsec_level require;	←20061228a現在、unique は未実装。指定すると IPsec が動作しません。
	my_sa_ipaddr    210.11.11.11;
	peers_sa_ipaddr 210.22.22.22;
};

racoon2 を IKE として使用する場合、spmd デーモンと iked デーモンの2つに分かれています。FreeBSD では次のように設定・起動させます。

/etc/rc.conf
spmd_enable="YES"
iked_enable="YES"
手動での起動方法
# /usr/local/etc/rc.d/spmd start
# /usr/local/etc/rc.d/iked start

spmd は racoon2.conf の selector および policy の項目を読み出し setkey を実行します。spmd を起動させたあと、SPD エントリを確認すると次のようになります。

# setkey -DP
192.168.20.0/24[any] 192.168.10.0/24[any] any
        in IPsec
        esp/tunnel/210.22.22.22-210.11.11.11/require
        created: Jan 18 19:46:52 2007  lastused: Jan 18 22:17:32 2007
        lifetime: 0(s) validtime: 0(s)
        spid=16389 seq=1 pid=23230
        refcnt=1
192.168.10.0/24[any] 192.168.20.0/24[any] any
        out IPsec
        esp/tunnel/210.11.11.11-210.22.22.22/require
        created: Jan 18 19:46:52 2007  lastused: Jan 18 22:17:48 2007
        lifetime: 0(s) validtime: 0(s)
        spid=16388 seq=0 pid=23230
        refcnt=1

iked (racoon2)が相手方含めうまく動作し鍵交換に成功すれば、SADエントリが登録されIPsecの通信が確立されます。

# setkey -D
210.22.22.22 210.11.11.11
        esp mode=tunnel spi=126366317(0x0788326d) reqid=0(0x00000000)
        E: 3des-cbc  2a7834a 4c3204b2 85ebe60f 63897650 eea4cacd 302f1999
        A: hmac-sha1  ec8798a 0c05beba c96bf2d0 27476813 6b25fbd3
        seq=0x0000004a replay=4 flags=0x00000000 state=mature
        created: Jan 18 19:47:13 2007   current: Jan 18 22:35:10 2007
        diff: 2877(s)   hard: 28800(s)  soft: 28800(s)
        last: Jan 18 18:32:48 2007      hard: 0(s)      soft: 0(s)
        current: 19600(bytes)   hard: 0(bytes)  soft: 0(bytes)
        allocated: 74   hard: 0 soft: 0
        sadb_seq=1 pid=26699 refcnt=2
210.11.11.11 210.22.22.22
        esp mode=tunnel spi=129847243(0x07bd4fcb) reqid=0(0x00000000)
        E: 3des-cbc  d6d8a358 5ea1524f e93b927c 8b78ed33 43dc4656 1471817a
        A: hmac-sha1  19eaf381 15ab1ae4 a724f53d 6e56354f b959d443
        seq=0x00000004 replay=4 flags=0x00000000 state=mature
        created: Jan 18 19:47:13 2007   current: Jan 18 22:35:10 2007
        diff: 2877(s)   hard: 28800(s)  soft: 28800(s)
        last: Jan 18 18:32:32 2007      hard: 0(s)      soft: 0(s)
        current: 1028(bytes)    hard: 0(bytes)  soft: 0(bytes)
        allocated: 4    hard: 0 soft: 0
        sadb_seq=0 pid=26699 refcnt=1

鍵交換に成功しない限りSADエントリは登録されませんので、通信がうまくいかない場合の原因を racoon2 か IPのフィルタ か判別することができます。

鍵交換に失敗している場合
# setkey -D
NO SAD entries

動作確認と問題調査方法

設定上の注意を参照すれば、だいたいのトラブルは避けられると思いますが、トラブル対処方をいくつか書いておきます。

tcpdumpによる調査

racoon2 の IKE の動作、きちんとコネクションの確立用パケットが送られているかは次のように書きます。tun0 は、FreeBSDマシンのPPPoEデバイスで、Linuxなどではppp0などになります。調査時はLAN内のマシンから、相手側LANへpingを投げるなどします。

# tcpdump -i tun0 port 500
listening on tun0, link-type NULL (BSD loopback), capture size 96 bytes
19:22:04.467053 IP 210.11.11.11.isakmp > 210.22.22.22.isakmp: isakmp: phase 1 I ident
19:22:04.471308 IP 210.22.22.22.isakmp > 210.11.11.11.isakmp: isakmp: phase 1 R ident
19:22:04.620765 IP 210.11.11.11.isakmp > 210.22.22.22.isakmp: isakmp: phase 1 I ident
19:22:04.747872 IP 210.22.22.22.isakmp > 210.11.11.11.isakmp: isakmp: phase 1 R ident
19:22:04.976045 IP 210.11.11.11.isakmp > 210.22.22.22.isakmp: isakmp: phase 1 I ident[E]
19:22:04.981089 IP 210.22.22.22.isakmp > 210.11.11.11.isakmp: isakmp: phase 1 R ident[E]
19:22:05.985104 IP 210.11.11.11.isakmp > 210.22.22.22.isakmp: isakmp: phase 2/others I oakley-quick[E]
19:22:05.990244 IP 210.22.22.22.isakmp > 210.11.11.11.isakmp: isakmp: phase 2/others R oakley-quick[E]
19:22:05.991644 IP 210.11.11.11.isakmp > 210.22.22.22.isakmp: isakmp: phase 2/others I oakley-quick[E]

同様にIPsecracoon2 の IKE の動作、きちんとコネクションの確立用パケットが送られているかは次のように書きます。tun0 は、FreeBSDマシンのPPPoEデバイスで、Linuxなどではppp0などになります。調査時はLAN内のマシンから、相手側LANへpingを投げるなどします。

# tcpdump -i tun0 esp
listening on tun0, link-type NULL (BSD loopback), capture size 96 bytes
19:25:45.999494 IP 210.22.22.22 > 210.11.11.11: ESP(spi=0x0e0d347f,seq=0xe), length 116
19:25:46.000196 IP 210.11.11.11 > 210.22.22.22: ESP(spi=0x05d52d17,seq=0x11), length 116
19:25:47.001858 IP 210.22.22.22 > 210.11.11.11: ESP(spi=0x0e0d347f,seq=0xf), length 116
19:25:47.002553 IP 210.11.11.11 > 210.22.22.22: ESP(spi=0x05d52d17,seq=0x12), length 116
19:25:48.001502 IP 210.22.22.22 > 210.11.11.11: ESP(spi=0x0e0d347f,seq=0x10), length 116
19:25:48.002231 IP 210.11.11.11 > 210.22.22.22: ESP(spi=0x05d52d17,seq=0x13), length 116

racoon2 のデバッグモード

iked を起動する際、

# iked -D 0xff

とすることで詳細なデバッグメッセージを得ることができます。標準では syslog に投げられますので、syslog.conf を適切に設定して別ファイル(パーミッション600)に出力する方がよいでしょう。

# iked -F -D 0xff

としてフォアグランド動作にしてコンソールでデバッグしても良いのですが、この場合SADの登録に失敗するのでIPsecを動作させることはできません(Phase2までは成功します)。

IPsecの psk により生成された共有秘密が正しいかチェックするためには、ログから SKEYID, SKEYID_d, SKEYID_a, SKEYID_eが通信する相互のマシンで一致しているか確認してください(これらはその直前に記録された乱数である nonce 1, nonce 2 から生成されるので、確認時は必ず同じ通信を確認してください)。

ipfilter や iptables の確認

racoon2 のログに、IPsec-SA establish と書かれ、setkey -DできちんとSADが表示されている場合は、通信できない原因として IP 系のフィルタを疑ってください。また、静的ルーティングとして不要なルールが追加されていないかも確認してください。

FreeBSD、Linux それぞれ、正常にIPsec通信できる状態で、routingテーブルは次のようになっています。

FreeBSD
# netstat -rn    #210.xx.xx.xxはプロバイダgw
Destination        Gateway            Flags    Refs      Use  Netif Expire
default            210.xx.xx.xx       UGS         1   208515   tun0
127.0.0.1          127.0.0.1          UH          0     6283    lo0
192.168.10         link#1             UC          0        0   eth0
192.168.10.1       00:02:b3:5c:bf:05  UHLW        2        0    lo0
210.xx.xx.xx       210.11.11.11       UH          1        0   tun0
Linux
# route -rn    #210.yy.yy.yyはプロバイダgw
210.yy.yy.yy    0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
192.168.20.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         210.yy.yy.yy    0.0.0.0         UG    0      0        0 ppp0

IPsecを実行しているマシンから直接相手側LANにアクセスする。

IPsecを構築しているFreeBSDマシンから、相手側LAN 192.168.20.0/24 アクセスするには、次のようなルーティングを追加します。

FreeBSDの場合
# route add 192.168.20.0/24 192.168.10.1     192.168.10.1はFreeBSDのLAN側IP

Linuxの場合はこの設定を行うと、IPsec通信自体が行われなくなりますので注意してください。

未解決の問題点

  • LAN内マシンから相手側LAN内マシンに対してftpを行うと、active mode (passive off) では通信ができない。Linuxのカーネルモジュール ip_nat_ftp が原因だと思われます(未確認)。
  • LAN内マシンから相手側LAN内マシンに対し VNC 通信を行うと、画面データがまったく送られてこない。→一応解決しました

参考資料

最初の pdf は racoon2 開発者たちによって書かれた技術資料なのでかなり参考になります。またracoon2 に付属のドキュメントが日本語でかかれていますので、それを読むことを勧めます*3。ソースを直接展開しても容易に読むことができます。

*3 : FreeBSDならば /usr/local/share/doc/racoon2 にあります。