Gentooでlibreswan 3.8 を使用して、2つのサーバーをトンネルモード接続する手順。(201410)

{:TableOfContents}

下準備

カーネルの設定

ipsec verifyでは ssを使用してUDPソケットを調べるので、UDPモニタインタフェースが必要。

 networking support
   networking options
     <*>   UDP sockets monitoring interface

gentooでのiproute2のipコマンドのパス

libreswan 3.8の ipsec verify は、 /sbin/ip と /usr/sbin/ip しか探さない。Gentooでは /bin/ip なので、/sbinにシンボリックリンクを張っておく。

% ln -s /bin/ip /sbin/

ファイヤウォールを通すプロトコル、ポート

  • プロトコル50(ESP) と 51(AH)
  • UDP ポート500 (ISAKMP)
  • UDP ポート4500 (NAT Traversal、オプション)

emrge libreswan

nssのUSEフラグ utilsが必要。インストールしたら、まず /etc/ipsec.conf の最終行コメント解除して、コンフィグファイルを分割できるようにしておく。

include /etc/ipsec.d/*.conf

ipsec verifyで問題解決

先に /etc/init.d/ipsec startしてから ipsec verifyする。

# ipsec verify
NETKEY: Testing XFRM related proc values
         ICMP default/send_redirects                    [NOT DISABLED]  ダメ
         ICMP default/accept_redirects                  [NOT DISABLED]  ダメ
Hardware random device                                  [N/A]
Checking rp_filter                                      [ENABLED]
 Pluto listening for IKE on udp 500                     [FAILED]        ダメ
 Pluto listening for IKE/NAT-T on udp 4500              [DISABLED]      ダメ
Checking NAT and MASQUERADEing                          [TEST INCOMPLETE]
Checking 'ip' command                                   [FAILED]        ダメ
        [OK]
Opportunistic Encryption                                [DISABLED]

ICMP redirect関連。

sysctl.confで幾つか変更する。 確認したところ、default系を変更する必要があり、all系はほっといてよし。

# vi /etc/sysctl.conf
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0

sysctl -p や rc single ; rc defaultではインターフェースに反映されなかったので、リブートした。

Pluto listening for IKE (IKE/NAT-T)

カーネルの UDPモニタインターフェースが有効になっていないと、チェックスクリプトが使用する ss (iproute2)がUDPソケットを見つけられない。

その他

ログを見るとエラーが出ていたので、この2つをmkdirした。

pluto[7059]: Could not change to directory '/etc/ipsec.d/cacerts': No such file or directory
pluto[7059]: Could not change to directory '/etc/ipsec.d/crls': 2 No such file or directory
  • NAT and MASQUARADEの結果は、システムの状況と関係ない。

    チェックスクリプト/usr/libexec/ipsec/verifyは、何もチェックせず TEST INCOMPLETEと報告する。つまりチェックが未完成と言うこと。

  • Opportunistic Encryptionは、コンフィグ内容を調べて表示しているだけ。

    oe= のエントリがなければ[DISABLED]となるが、設定エラーではない。

  • 未解決:無視:ipsecがAES関連の何かを登録失敗する(/var/log/messages)。だが問題なく動いているので先送り。

libreswanへの鍵・証明書の設定

  • left側ホスト名を west とする。
  • right側ホスト名を east とする。

westへのwest秘密鍵・証明書の設定、eastへのwest証明書の設定手順の例。 eastの鍵・証明書の設定作業は同様のため省略。

鍵と証明書は既存とする。

westへのwest鍵・証明書の設置(nss)

nssにサーバー秘密鍵単体をインポートする方法が分からないので、PKCS#12にパックしてからインポートする。

PKCS#12バンドル作成

westでサーバー秘密鍵と証明書(west.keyとwest.crt)、およびCA証明書(cacert.pem)の3つを合わせたPKCS#12バンドルをつくる。ここで設定するパスワードは、後のnssへのインポート時に聞かれる。

(ca) # openssl pkcs12 -export -certfile <俺CA>/cacert.pem -inkey west.key -in west.crt -out west.p12

このPKCS#12をwestのNSSデータベースへインポートする。多分、分解されて鍵と証明書2つの形で保管される。 使用した証明書にnicknameがなかったので(多分)、pk12utilから、「替わりにこう決めるよ?」と念を押された。このnicknameは後で使用する。

(west)# pk12util -i west.p12 -d /etc/ipsec.d
pk12util: no nickname for cert in PKCS12 file.
pk12util: using nickname: west_domain - oreoreCACompany
pk12util: PKCS12 IMPORT SUCCESSFUL

libreswanの鍵ファイル作成

westの鍵ファイル*.secretsに、上記のニックネームを記述する。 もし鍵と証明書でニックネームが異なる場合は、 certutil -K -d /etc/ipsec.d(鍵) と certutil -L -d /etc/ipsec.d(証明書)で調べること。 ファイル中に複数の鍵を記述しても良く、また複数の*.secretsがあれば、デフォルトでは全て読み込まれる。

(west)# vi /etc/ipsec.d/mytunnel.secrets
: RSA "west_domain - oreoreCAcompany"

westおよびeastの*.confに証明書ニックネーム指定

(west)# vi /etc/ipsec.d/mytunnel.conf
conn mytunnel
         :
       leftcert="west_domain - oreoreCAcompany"

westの公開鍵(サーバー証明書)をeastに設置。

west.crt をeastのnssデータベース(/etc/ipsec.d)に追加する。その際ニックネームを、上のnssインポート時と同じにする。こうすると、両側の設定ファイルの内容をほとんど同じにできる。

(east)# certutil -A -d /etc/ipsec.d -i west.crt -a -n "west_domain - oreoreCAcompany" -t P
(east)# certutil -L -d /etc/ipsec.d # 確認

なお -a : ascii format , -n <nickname> , -t P : type of trust attributes P=peerとのこと。

証明書削除は certutil -D -d /etc/ipsec.d -n <nickname>

####eastの設定ファイルでwest証明書のニックネームを指定 (east)# vi /etc/ipsec.d/my_tunnel.conf conn mytunnel : leftcert=“west_domain - oreoreCAcompany”

eastの鍵と証明書に関する作業

westと異なるのは サーバー証明書、サーバー秘密鍵とニックネーム。

シンプルなトンネル設定例 (固定IP 対 動的IP)

  • westが固定IP, eastがISP提供の動的グローバルIP (+プライベートLAN)
  • westのnssデータベースにはWESTの鍵+証明書と、EASTの証明書が格納されている
  • EASTのnssデータベースにはEASTの鍵+証明書と、WESTの証明書が格納されている

これらにニックネームでアクセスする。left側(WEST)の設定ファイル:

(WEST)# vi /etc/ipsec.d/mytunnel.conf
conn mytunnel
   auto=start
   authby=rsasig

    leftid=@WEST # なんでも良いみたい。
   rightid=@EAST

    leftcert="west_domain - oreoreCompany" #証明書ニックネーム
   rightcert="east_domain - oreoreCompany" # 同上

    left=1xx.xx3.x1x.x7x
   right=%any           # west accepts dynamic IP
   #right=%defaultroute  # east knows its IP

right側(east)の設定ファイルも1箇所以外同じ。 right=%anyではなく、right=%defaultrouteにして、自分の動的IP を使う。

(east)# vi /etc/ipsec.d/mytunnel.conf
conn mytunnel
   auto=start
   authby=rsasig

    leftid=@WEST # なんでも良いみたい。
   rightid=@EAST

    leftcert="west_domain - oreoreCompany"
   rightcert="east_domain - oreoreCompany"

    left=1xx.xx3.x1x.x7x
   #right=%any           # west accepts dynamic IP
   right=%defaultroute  # east knows its IP

その他tips

nssデータベースの初期化

データベースのファイル cert8.db とかを消した後などに必要

ipsec initnss --configdir /etc/ipsec.d

無人でIPSecを始動するには、データベースのパスワードを空にしておかなければならない。

sshのパケットをtcpdump (通常vsIPSecトンネル)

IPsecなし

22:14:31.782943 IP <east> > <west>.<port of ssh>: Flags [P.], seq 104:156, ack 105, win 16360, length 52
22:14:31.811565 IP <west> > <east>.55266: Flags [P.], seq 105:157, ack 156, win 337, length 52
22:14:32.011446 IP <east> > <west>.<port of ssh>: Flags [.], ack 157, win 16347, length 0

IPSec トンネルモード

22:19:41.301178 IP <east> > <west>: ESP(spi=0x975b85fe,seq=0x2), length 132
22:19:41.311601 IP <west> > <east>: ESP(spi=0x461810dd,seq=0x3), length 132
22:19:41.311601 IP <west> > <east>: Flags [P.], seq 836:888, ack 313, win 337, length 52

ある日のLEFTのログ:RIGHTと接続するまで

L.e.f.t, Ri.g.h.t は IPアドレス。 @WEST, @EAST は leftid と rightidの設定値

"mytunnel": cannot initiate connection without knowing peer IP address (kind=CK_TEMPLATE)
packet from Ri.g.h.t:500: received Vendor ID payload [Dead Peer Detection]
packet from Ri.g.h.t:500: received Vendor ID payload [FRAGMENTATION]
packet from Ri.g.h.t:500: received Vendor ID payload [RFC 3947]
packet from Ri.g.h.t:500: ignoring Vendor ID payload [draft-ietf-ipsec-nat-t-ike-03]
packet from Ri.g.h.t:500: ignoring Vendor ID payload [draft-ietf-ipsec-nat-t-ike-02_n]
packet from Ri.g.h.t:500: ignoring Vendor ID payload [draft-ietf-ipsec-nat-t-ike-02]
packet from Ri.g.h.t:500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-00]
"mytunnel"[1] Ri.g.h.t #1: responding to Main Mode from unknown peer Ri.g.h.t
"mytunnel"[1] Ri.g.h.t #1: transition from state STATE_MAIN_R0 to state STATE_MAIN_R1
"mytunnel"[1] Ri.g.h.t #1: STATE_MAIN_R1: sent MR1, expecting MI2
"mytunnel"[1] Ri.g.h.t #1: NAT-Traversal: Result using RFC 3947 (NAT-Traversal): no NAT detected
"mytunnel"[1] Ri.g.h.t #1: transition from state STATE_MAIN_R1 to state STATE_MAIN_R2
"mytunnel"[1] Ri.g.h.t #1: STATE_MAIN_R2: sent MR2, expecting MI3
"mytunnel"[1] Ri.g.h.t #1: Main mode peer ID is ID_FQDN: '@EAST'
"mytunnel"[1] Ri.g.h.t #1: I am sending my cert
"mytunnel"[1] Ri.g.h.t #1: transition from state STATE_MAIN_R2 to state STATE_MAIN_R3
"mytunnel"[1] Ri.g.h.t #1: STATE_MAIN_R3: sent MR3, ISAKMP SA established {auth=OAKLEY_RSA_SIG cipher=aes_128 prf=oakley_sha group=modp2048}
"mytunnel"[1] Ri.g.h.t #1: the peer proposed: L.e.f.t/32:0/0 -> Ri.g.h.t/32:0/0
"mytunnel"[1] Ri.g.h.t #2: responding to Quick Mode proposal {msgid:4d1eef47}
"mytunnel"[1] Ri.g.h.t #2:     us: L.e.f.t<L.e.f.t>[@WEST]
"mytunnel"[1] Ri.g.h.t #2:   them: Ri.g.h.t[@EAST]
"mytunnel"[1] Ri.g.h.t #2: transition from state STATE_QUICK_R0 to state STATE_QUICK_R1
"mytunnel"[1] Ri.g.h.t #2: STATE_QUICK_R1: sent QR1, inbound IPsec SA installed, expecting QI2
"mytunnel"[1] Ri.g.h.t #2: transition from state STATE_QUICK_R1 to state STATE_QUICK_R2
"mytunnel"[1] Ri.g.h.t #2: STATE_QUICK_R2: IPsec SA established tunnel mode {ESP=>0xa4e90da0 <0x2a7c6672 xfrm=AES_128-HMAC_SHA1 NATOA=none NATD=none DPD=none}