FreeBSDでWPA2-EAP認証

今後、システムの再インストールなんかで参照することもあるかと思うのでメモ代わりに。

まえおき

今まで自宅の無線LAN環境はWPA-PSK(TKIP)だったのだが、「これ、15分くらいで破られるそうだし、一番強いとされるWPA2-PSK(AES)だって結局のところパスワード認証だから総当たりで破られるかも知れんね」ということで、FreeRadiusを使った認証に代えてみることにした。無線APはコレガのCG-WLR300NMにした。普及価格帯でEAP(IEEE802.1X認証)に対応しているのはコレガとPlanexだけみたいで、同価格だったPlanexのCQW-MR500と迷ったのだが、Planexの方は「外部RADIUSサーバ対応」という、EAPに対応しているか今ひとつ確信が持てない表記だったので、コレガの方にした。有線LANポートが3つしかなく、PS3、TV、ハブにつないだら空きが無くなるのが難点だが、よく考えたらテレビは別にインターネットにつながんなくてもいいな。

FreeRadiusはFreeBSDサーバ(jail環境)に入れることにした。最初は玄箱で運用しようとしていたのだが、FreeRadiusをビルドしなおす必要があると分かってやになった。サーバのメンテの時は無線LANが使えなくなるが、ま、しょうがないか。(有線LANを使えばいいわけだし)

参考にしたところは、広瀬雄二氏の「FreeRADIUSとOpenSSLで構築する802.1X認証サーバ」という記事。


準備

まず、net/freeradius2をインストール。それから、/etc/ssl/openssl.cnfの編集。証明書類はとりあえず/usr/local/ssl/CA/に置くことにした。 具体的な変更箇所は以下の通り。

  • [ CA_default ]セクションのdefault_daysの内容を3650に変更。(証明書の期間を10年に)

  • [ req ]セクションのdefault_bitsの内容を2048に変更。(RSA鍵の長さを2048ビットに)

  • [ req_distinguished_name ]セクションのcountryName_default(デフォルトの国名)、stateOrProvinceName_default(デフォルトの県名)、0.organizationName_default(デフォルトの組織名)、emailAddress_default(デフォルトの管理者メールアドレス)を適切な値に変更。

  • [ req_distinguished_name ]セクションに、変数localityName_defaultを追加し、値に都市名を記入。


ルート証明書の作成

まず、newreq.pemを作成する。念のため、カレントディレクトリを/usr/local/ssl/CAにしておく。

# openssl req -new -x509 -keyout newreq.pem -out newreq.pem -passin pass:パスワード -passout pass:パスワード -days 3650

いろいろ聞かれるが、CommonName以外はそのままエンターキー押下でOK。CommonNameはユニークな名前をつけておく。

続いて、CAの階層化を行う。なお、FreeBSDではユーザーランドにCA.plスクリプトが無いので、/usr/src/crypto/openssl/appsに入っているものを、/usr/local/sbinあたりにコピーして使う。CA.plの$DAYS$CA_DAYSの値を"-days 3650"に変更しておく。

# echo "newreq.pem" | CA.pl -newca >/dev/null

さらに、PKCS#12形式の証明書ファイル(root.p12)とPEM形式の証明書ファイル(root.pem)を順次作成する。

# openssl pkcs12 -export -in demoCA/cacert.pem -inkey newreq.pem -out root.p12 -cacerts -passin pass:パスワード -passout pass:パスワード
# openssl pkcs12 -in root.p12 -out root.pem -passin pass:パスワード -passout pass:パスワード

最後に、newreq.pemを削除する。

# rm newreq.pem

サーバ証明書の作成

まず、/usr/local/ssl/CA/に、下記の内容でxpextensionsというファイルを作成する。

[ xpclient_ext ]
extendedKeyUsage = 1.3.6.1.5.5.7.3.2

[ xpserver_ext ]
extendedKeyUsage = 1.3.6.1.5.5.7.3.1
subjectAltName = DNS:ドメイン

(2023/11/7追記)どうやら最近のAndroidではWiFi設定に「ドメイン」というのが必須項目となり、SAN(Subject Alternative Names)をサーバ証明書側で設定する必要があるようだ。上記のように [ xpserver_ext ] の下に subjectAltName を設定してサーバ証明書を作り直したところ、うまく動作するようになった。(追記終わり)

続いて、PKCS#10形式の証明書ファイル(newreq.pem)を作成する。CommonNameには、"Server"を指定する。challenge passwordには、忘れにくいパスワードを設定しておく。

# openssl req -new -keyout newreq.pem -out newreq.pem -passin pass:パスワード -passout pass:パスワード

それから、 証明書リクエストに署名をする。

# echo '01' > ./demoCA/serial
# openssl ca -policy policy_anything -out newcert.pem -passin pass:パスワード -key パスワード -extensions xpserver_ext -extfile xpextensions -infiles newreq.pem

PKCS#12形式の証明書ファイル(srvcert.p12)とPEM形式の証明書ファイル(srvcert.pem)を順次作成する。

# openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -out srvcert.p12 -clcerts -passin pass:パスワード -passout pass:パスワード
# openssl pkcs12 -in srvcert.p12 -out srvcert.pem -passin pass:パスワード -passout pass:パスワード

最後に、newreq.pemとnewcert.pemを削除する。

# rm newreq.pem newcert.pem

クライアント証明書の作成

まず、PKCS#10形式の証明書ファイル(newreq.pem)を作成する。CommonNameには、"Client"を指定する(2017/10/21追記:別のCommonNameでも構わない。異なるCommonNameを使うことで複数のクライアント証明書を作成・署名することもできる)。challenge passwordには、忘れにくいパスワードを設定しておく。

# openssl req -new -keyout newreq.pem -out newreq.pem -passin pass:パスワード -passout pass:パスワード

それから、 証明書リクエストに署名をする。

# openssl ca -policy policy_anything -out newcert.pem -passin pass:パスワード -key パスワード -extensions xpclient_ext -extfile xpextensions -infiles newreq.pem

PKCS#12形式の証明書ファイル(clicert.p12)とPEM形式の証明書ファイル(clicert.pem)を順次作成する。(2023/11/9追記: xpextensions ファイルに subjectAltName 行があるとopensslが"unsupported certificate purpose"というエラーを出して認証してくれないようだ。なので、サーバ用とクライアント用で別々の xpextensions ファイルを用意したほうが良さそうだ。(追記終わり)

# openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -out clicert.p12 -clcerts -passin pass:パスワード -passout pass:パスワード
# openssl pkcs12 -in clicert.p12 -out clicert.pem -passin pass:パスワード -passout pass:パスワード

最後に、newreq.pemとnewcert.pemを削除する。

# rm newreq.pem newcert.pem

FreeRadiusの設定

FreeRadiusの設定ファイルは/usr/local/etc/raddbに保存されている。まず、eap.confdefault_eap_type変数の値をtlsに変更する。それから、tls {で始まる箇所の内、以下の変数の値を以下のように変更する。(2018/11/4追記)FreeRadius3だとmods-available/eapに変更になった模様。また、tls {tls-config tls-common {に変わったようだ。また、下記のcertdir、cadirはなくなっており追加する必要がある。(追記終わり)

certdir = /usr/local/ssl/CA
cadir = /usr/local/ssl/CA
private_key_password = 設定したパスワード
private_key_file = ${certdir}/srvcert.pem
certificate_file = ${certdir}/srvcert.pem
CA_file = ${cadir}/root.pem
fragment_size = 1024
include_length = yes

(2017/10/21追記)また、クライアント証明書の無効化に対応できるよう、eap.conftlsセクションのcheck_crlのコメントアウトを外しておく。そして、下記のようにc_rehashスクリプトを実行してpemファイルをハッシュする。FreeBSDではデフォルトのインストール状態ではc_rehashはインストールされていないが、/usr/ports/mail/cone/scriptsに保存されているのでそれを適当なフォルダにコピーしておくとよいだろう。下記の例ではとりあえず/usr/local/binに入れておいた。あと念の為無効リストを作っておく。無効リストの作成はクライアント証明書を追加する度に行う。

# openssl ca -gencrl -out /usr/local/ssl/CA/crl.pem
# perl /usr/local/bin/c_rehash /usr/local/ssl/CA

(追記終わり)

続いて、乱数ファイルを作る。これらは適当な値でよいようなので、ログのmd5値を使う。

# md5 /var/log/messages > /usr/local/ssl/CA/dh
# md5 /var/log/maillog > /usr/local/ssl/CA/random

次に、clients.confを編集する。client localhost{で始まる箇所を全てコメントアウトしたのちした後、下記の内容を追加する。

client wireless {
      ipaddr = アクセスポイントのIPアドレス
      shortname = wireless
      secret = 共通鍵の文字列
}

それから、/etc/rc.confに、radiusd_enable="YES"を追加する。そして、/usr/local/etc/radiusd startで起動する。


アクセスポイントとクライアントの設定

まず、アクセスポイントの設定を行う。認証方式を 「WPA2-EAP」に、暗号方式をAESに設定し、さらに、RADIUSサーバのIPアドレスと「シークレット」(上のclients.confで指定した共通鍵の文字列)を設定する。

続いて、クライアントの設定を行う。

Mac OSXの場合

radiusサーバで作成したclicert.p12とroot.p12を安全な方法でクライアント機にコピーする。そして、両ファイルをダブルクリックして、証明書をインストールする。パスワードは、証明書ファイルを作るときに設定したものを使う。そして、システム環境設定のネットワーク→AirMac→詳細ボタン→802.1Xと進んで、設定を行う。

Windows XP(SP3)の場合

1 radiusサーバで作成したclisert.p12とroot.p12をクライアント機に安全な方法でコピーする。

2 root.p12をダブルクリックして証明書をインポート

3 「次へ」→「次へ」→パスワード入力

4 「次へ」→「証明書をすべて次のストアに配置する」にチェック

5 「参照」ボタンを押して「証明書ストア」欄に「信頼されたルート証明機関」を表示させる

6 「次へ」→「完了」でインポート完了。セキュリティ警告がでるが、ここは「はい」をクリック

7 clisert.p12をダブルクリックして証明書をインポート

8 「次へ」→「次へ」→パスワード入力

9 「次へ」→「証明書の種類に基づいて、自動的に証明書ストアを選択する」にチェック

10 「次へ」→「完了」でインポート完了

11 「コントロールパネル」→「ネットワーク接続」

12 「ワイヤレス ネットワーク接続」を右クリック→プロパティ

13 「ワイヤレス ネットワーク」タブで、追加ボタンをクリック

14 「アソシエーション」タブで、ネットワーク名に無線APのSSIDを、ネットワーク認証にWPA2を、データの暗号化にAESをそれぞれ設定。

15 「このネットワークがブロードキャストしていない場合でも接続する」にチェック。

16 「認証」タブの「EAPの種類」で「スマートカードまたはその他の証明書」を選択

17 「プロパティ」ボタンをクリック

18 「サーバーの証明書を有効化する」をチェック。「信頼されたルート証明機関」の中にある自分の証明機関にチェック。

19 「この接続で別のユーザー名を使う」にチェック。

20 この状態で無線APに接続しようとすると、バルーンが表示されるので、クリックして証明書の設定

FreeBSDの場合

基本的にはハンドブックの通り。まずは、/etc/certsというディレクトリを作り、ここに、安全な方法でroot.pemclicert.pemをコピーする。そして、/etc/wpa_supplicant.confを以下のように設定する。

network={
  ssid="無線APのSSID"
  proto=RSN
  key_mgmt=WPA-EAP
  eap=TLS
  identity="ユーザ名"
  ca_cert="/etc/certs/root.pem"
  client_cert="/etc/certs/clicert.pem"
  private_key="/etc/certs/clicert.pem"
  private_key_passwd="パスワード"
}

クライアント証明書の無効化(2017/10/21追記)

例えばゲストに一時的に無線LANの利用を許可する場合に、ゲスト用のクライアント証明書を作成してインストールすることが考えられる。この場合、ゲストが帰った後にクライアント証明書を無効化することが考えられる。ブログ「基礎から学ぶ無線LANの設定と設計」の記事「6-6(7)電子証明書の失効方法」及び同ブログの記事「6-5(4) FreeRadiusの設定(EAP-TLSでCRLを利用する)」によれば、クライアント証明書を無効化し、freeradiusに反映させるには下記のようにすればいいようだ。

# openssl ca -revoke クライアント証明書のpemファイル
# openssl ca -gencrl -out /usr/local/ssl/CA/crl.pem
# perl /usr/local/bin/c_rehash /usr/local/ssl/CA
# /usr/local/etc/rc.d/radiusd restart

(2017/11/23追記)

先日突然無線LANが使えなくなった。調べてみると上記「基礎から学ぶ無線LANの設定と設計」ブログにFreeRadiusで、CRLを有効にしていたらある日突然使えなくなったという記事が。つまり/etc/ssl/openssl.cnfに指定されたCRLの有効期限(default_crl_days)が30日なのでその日までにCRLの更新を行う必要がある模様。対処方法としては、default_crl_daysに十分長い日数(3650とか)を指定した上で、上記のopenssl ca -gencrl~以下のコマンドを再度実行してやるのがよいようだ。

(追記終わり)

コメント(0)



Note

本サイトのハイパーリンクの一部は、オリジナルのサイトが閉鎖してしまったため"Internet archive Wayback Machine"へのリンクとなっています。そのようなリンクにはアイコン[archive]を付与しています。

本サイトはCookieを使用しています。本サイトにおけるCookieは以下の三種類のみであり、Cookieの内容に基づいてサイトの表示を変更する以外の用途には用いておりません。