一つ前の節では、暗号化は単純な共有鍵によって行われました。 したがって、安全を確保するには、 この暗号化設定を信頼できる経路で転送しなければいけません。 リモートのホストを telnet で設定しなければならないような場合には、 第三者にこの共有鍵が覗けてしまうので、その設定が安全であるとは言えません。
さらに、鍵が共有されているということは、秘匿性がないということです。 リモートはこの鍵を用いてもたいした悪さはできませんが、 しかし別々の相手と通信する際には、必ずそれぞれ別々の鍵を使う必要があります。 これには鍵の数が非常にたくさん必要です。 もし 10 組のパートナーを組むなら、最低 50 種類の鍵が必要です (訳注 10_C_2 なら 45 だと思いますが…)。
対称鍵の問題に加え、鍵の更新にも問題があります。 第三者が十分な量のトラフィックを盗聴すると、 鍵をリバースエンジニアリングすることが不可能ではなくなります。 これは時々鍵を新しくすることによって避けられますが、 これは自動化が必要な処理です。
もうひとつの問題として、前述したような手動の鍵処理では、 アルゴリズムと鍵の長さを正確に定義しなければならず、 リモートとの調整の手間がかかります。 もっと幅広い鍵ポリシーを記述できるほうが望ましいです。例えば 「こちらでは 3DES と Blowfish が使えて、鍵の長さには次のようなのが使えます」 のように。
これらの問題を解決するために、IPSEC では Internet Key Exchange が使えます。 これはアルゴリズムの詳細をネゴシエートして、 ランダムに生成された鍵を自動的に交換し、 非対称暗号化技術を用いて鍵を転送します。
Linux 2.5 の IPSEC 実装では、KAME の 'racoon' IKE デーモンが動作します。 11 月 9 日 (訳注: 2002 年) の段階では、Alexey の iptools 配布に入っている racoon は、コンパイルはできますが、2 つのファイルで #include <net/route.h> を削除する必要があります。 または、私も コンパイル済バイナリ を提供しています。
Note: IKE は UDP ポート 500 にアクセスできる必要があります。 iptables でブロックしていないことを確認しましょう。
先に説明した通り、自動鍵処理では多くの作業をしてくれます。 特に、Security Associations を動作の途中で生成してくれます。 しかしポリシーの設定は、希望するようには行ってくれません。
よって、IKE の恩恵を享受するには、ポリシーは設定して、 SA は設定しない、ということになります。 カーネルは SA の無い IPSEC ポリシーを発見するとそれを IKE デーモンに知らせ、 そしてデーモンがネゴシエーションの作業を開始します。
繰り返しますが、Security Policy は我々が「何を」必要とするかの指定です。 Security Association は、それを「どのように」実現するかを記述します。 自動鍵処理を用いれば、我々は何をしたいかだけを指定すればよくなるのです。
Kame の racoon には非常にたくさんのオプションがありますが、 そのほとんどは、デフォルトが非常に良く考えられた値になっています。 よってほとんどは変更する必要がありません。 前述のように、オペレータは Security Policy を定義すればよく、 Security Associations は必要ありません。 ネゴシエーションは IKE デーモンに任せます。
この例では、再び 10.0.0.11 と 10.0.0.216 が安全な通信を確立しようとしています。 しかし今回は racoon の助けを借ります。 簡単のために、この設定には事前に共有した、 嫌われ者の「共有暗号鍵」があるとしましょう。 X.509 認証は別の節で議論します。 Section 7.2.3 をみてください。
ほぼデフォルトの設定でいきましょう。 両方のホストで同じです。
path pre_shared_key "/usr/local/etc/racoon/psk.txt"; remote anonymous { exchange_mode aggressive,main; doi ipsec_doi; situation identity_only; my_identifier address; lifetime time 2 min; # sec,min,hour initial_contact on; proposal_check obey; # obey, strict or claim proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method pre_shared_key; dh_group 2 ; } } sainfo anonymous { pfs_group 1; lifetime time 2 min; encryption_algorithm 3des ; authentication_algorithm hmac_sha1; compression_algorithm deflate ; } |
たくさんの設定がありますね。デフォルトの設定にさらに近づければ、 もうちょっと減らせると思いますが。いくつか注目すべき点を。 anonymous (匿名) 設定を 2 つ行っていますが、 これはすべてのリモートに適用され、 以降の設定が簡単になります。ホストごとの記述は、 特に必要としなければ、書かなくてかまいません。
さらに、この設定では自分自身の指定は IP アドレスによって行う ('my_identifier address') ように指定しました。 またこちらで行えるのは 3des, sha1 で、 psk.txt にある事前共有鍵を使う、と宣言しています。
psk.txt には 2 つのエントリを設定しておきます。 これは各ホストで異なります。10.0.0.11 では:
10.0.0.216 password2 |
10.0.0.11 password2 |
これで望むポリシーを設定する準備ができました。 これも簡単で、10.0.0.216 では:
#!/sbin/setkey -f flush; spdflush; spdadd 10.0.0.216 10.0.0.11 any -P out ipsec esp/transport//require; spdadd 10.0.0.11 10.0.0.216 any -P in ipsec esp/transport//require; |
#!/sbin/setkey -f flush; spdflush; spdadd 10.0.0.11 10.0.0.216 any -P out ipsec esp/transport//require; spdadd 10.0.0.216 10.0.0.11 any -P in ipsec esp/transport//require; |
これで racoon を起動する準備ができました! 一度起動すれば、10.0.0.11 から 10.0.0.216 に telnet しようとしたとき、 あるいは他の接続を試みたとき、racoon はネゴシエーションを開始します:
12:18:44: INFO: isakmp.c:1689:isakmp_post_acquire(): IPsec-SA request for 10.0.0.11 queued due to no phase1 found. 12:18:44: INFO: isakmp.c:794:isakmp_ph1begin_i(): initiate new phase 1 negotiation: 10.0.0.216[500]<=>10.0.0.11[500] 12:18:44: INFO: isakmp.c:799:isakmp_ph1begin_i(): begin Aggressive mode. 12:18:44: INFO: vendorid.c:128:check_vendorid(): received Vendor ID: KAME/racoon 12:18:44: NOTIFY: oakley.c:2037:oakley_skeyid(): couldn't find the proper pskey, try to get one by the peer's address. 12:18:44: INFO: isakmp.c:2417:log_ph1established(): ISAKMP-SA established 10.0.0.216[500]-10.0.0.11[500] spi:044d25dede78a4d1:ff01e5b4804f0680 12:18:45: INFO: isakmp.c:938:isakmp_ph2begin_i(): initiate new phase 2 negotiation: 10.0.0.216[0]<=>10.0.0.11[0] 12:18:45: INFO: pfkey.c:1106:pk_recvupdate(): IPsec-SA established: ESP/Transport 10.0.0.11->10.0.0.216 spi=44556347(0x2a7e03b) 12:18:45: INFO: pfkey.c:1318:pk_recvadd(): IPsec-SA established: ESP/Transport 10.0.0.216->10.0.0.11 spi=15863890(0xf21052) |
ここで setkey -D を実行して Security Associations を表示すると、 実際に存在していることがわかります:
10.0.0.216 10.0.0.11 esp mode=transport spi=224162611(0x0d5c7333) reqid=0(0x00000000) E: 3des-cbc 5d421c1b d33b2a9f 4e9055e3 857db9fc 211d9c95 ebaead04 A: hmac-sha1 c5537d66 f3c5d869 bd736ae2 08d22133 27f7aa99 seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Nov 11 12:28:45 2002 current: Nov 11 12:29:16 2002 diff: 31(s) hard: 600(s) soft: 480(s) last: Nov 11 12:29:12 2002 hard: 0(s) soft: 0(s) current: 304(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 3 hard: 0 soft: 0 sadb_seq=1 pid=17112 refcnt=0 10.0.0.11 10.0.0.216 esp mode=transport spi=165123736(0x09d79698) reqid=0(0x00000000) E: 3des-cbc d7af8466 acd4f14c 872c5443 ec45a719 d4b3fde1 8d239d6a A: hmac-sha1 41ccc388 4568ac49 19e4e024 628e240c 141ffe2f seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Nov 11 12:28:45 2002 current: Nov 11 12:29:16 2002 diff: 31(s) hard: 600(s) soft: 480(s) last: hard: 0(s) soft: 0(s) current: 231(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 2 hard: 0 soft: 0 sadb_seq=0 pid=17112 refcnt=0 |
10.0.0.11[any] 10.0.0.216[any] tcp in ipsec esp/transport//require created:Nov 11 12:28:28 2002 lastused:Nov 11 12:29:12 2002 lifetime:0(s) validtime:0(s) spid=3616 seq=5 pid=17134 refcnt=3 10.0.0.216[any] 10.0.0.11[any] tcp out ipsec esp/transport//require created:Nov 11 12:28:28 2002 lastused:Nov 11 12:28:44 2002 lifetime:0(s) validtime:0(s) spid=3609 seq=4 pid=17134 refcnt=3 |
これが動作しないときは、 設定ファイルがすべて root の所有であるか、 root からしか読めないようになっているかを確認してください。 racoon をフォアグラウンドで起動するには '-F' を用います。 コンパイル時に設定されたファイルの代わりに 特定の設定ファイルを読み込ませるには、'-f' を用います。 詳細についてこと細かに知りたければ、racoon.conf に 'log debug' という行を追加してください。
先に説明した通り、共有鍵の利用には難しい点があります。 共有は面倒で、それに一度共有されてしまうとそれはもう秘密ではないからです。 ありがたいことに、非対称暗号技術を利用すればこの問題を解決できます。
IPSEC への各参加者が公開鍵と秘密鍵を作れば、 通信の両者が公開鍵を発行し、ポリシーを設定すれば、 安全な通信を確立できます。
鍵の生成は割に簡単ですが、しかし多少の作業が必要です。 以下では 'openssl' のツールをもとにした作業を説明します。
OpenSSL には鍵に関する膨大なインフラストラクチャがあり、 CA による署名を行うことも行わないこともできます。 ここではインフラの大部分は回避し、 CA 無しで済ませる、 お馴染みのいんちきセキュリティを適用しましょう。
まず私たちのホストの「証明請求書 (certificate request)」を発行します。 名前は 'laptop' とします。
$ openssl req -new -nodes -newkey rsa:1024 -sha1 -keyform PEM -keyout \ laptop.private -outform PEM -out request.pem |
Country Name (2 letter code) [AU]:NL State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:Delft Organization Name (eg, company) [Internet Widgits Pty Ltd]:Linux Advanced Routing & Traffic Control Organizational Unit Name (eg, section) []:laptop Common Name (eg, YOUR name) []:bert hubert Email Address []:ahu@ds9a.nl Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: |
ここでこの請求書に、「自己署名」します:
$ openssl x509 -req -in request.pem -signkey laptop.private -out \ laptop.public Signature ok subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic \ Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl Getting Private key |
この手続きを鍵の必要なホストのすべてで繰り返します。 この '.public' 鍵は問題なく配布できますが、'.private' 鍵の方は 秘匿しておくように!
ホストの公開鍵・秘密鍵ができたら、これらを使うよう racoon に伝えます。
先ほどの設定に戻りましょう。 2 つのホストを 10.0.0.11 ('upstairs') と 10.0.0.216 ('laptop') とします。
10.0.0.11 の racoon.conf ファイルに、以下を追加します:
path certificate "/usr/local/etc/racoon/certs"; remote 10.0.0.216 { exchange_mode aggressive,main; my_identifier asn1dn; peers_identifier asn1dn; certificate_type x509 "upstairs.public" "upstairs.private"; peers_certfile "laptop.public"; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; dh_group 2 ; } } |
ここの 'asn1dn' の行は、ローカル・リモート両側の識別子としては、 公開鍵から取り出されたものを用いるよう、racoon に伝えています。 これは前述の 'subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl' という出力です。
certificate_type の行は、 ローカルの公開鍵・秘密鍵を設定しています。 peers_certfile 文は、 リモートの接続先の公開鍵を laptop.public というファイルから読み込むよう racoon に伝えています。
proposal ブロックは先ほどのものと変わっていません。 ただし今回は authentication_method が rsasig になっており、 認証に RSA 公開鍵/秘密鍵を用いることが示してあります。
10.0.0.216 の設定への追加もだいたい同じで、 ただしいつもの通り鏡映の関係にあります。
path certificate "/usr/local/etc/racoon/certs"; remote 10.0.0.11 { exchange_mode aggressive,main; my_identifier asn1dn; peers_identifier asn1dn; certificate_type x509 "laptop.public" "laptop.private"; peers_certfile "upstairs.public"; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; dh_group 2 ; } } |
両方のホストにこれらの文を追加したら、 あとは鍵をその場所に置くだけです。'upstairs' マシンでは、 /usr/local/etc/racoon/certs に upstairs.private, upstairs.public, laptop.public が必要です。 このディレクトリが root の保有になっており、 モードが 0700 になっていることを確認のこと。 さもないと racoon は読み込みを行いません!
マシン 'laptop' では、 /usr/local/etc/racoon/certs に laptop.private, laptop.public, upstairs.public が必要です。 要するに、各ホストでは自分の公開鍵と秘密鍵、 さらにリモートの公開鍵を必要とします。
Security Policy が設定されていることを確認します (Section 7.2.2 の 'spdadd' 行を実行)。 続いて racoon を起動すれば、すべて動作するはずです。
リモートの接続先との間で安全な通信を行うには、 公開鍵を交換しなければなりません。 公開鍵そのものは秘匿しておかなくて良いのですが、 一方、その鍵が本当に改竄されていない鍵である保証が非常に大切です。 要するに、「途中の奴」がいないことが確かでなければなりません。
この作業を簡単にするため、OpenSSL には 'digest' コマンドがあります。
$ openssl dgst upstairs.public MD5(upstairs.public)= 78a3bddafb4d681c1ca8ed4d23da4ff1 |
これで、リモートのパートナーとの間で、 ダイジェストが同じであることを確認するだけですみます。 これを行うには実際に会うか、あるいは電話をすればいいでしょう。 リモート側でのこの番号が、実は鍵と同じメールで送られて来た、 というのではダメですよ!
これを行うもう一つの方法は、CA を行っている 信頼できる第三者 (Trusted Third Party) を用いることです。 この CA に、(先ほどは自分たちで行った) 署名をしてもらうのです。