はじめに
このエントリはCiscoWLCとFreeRADIUSを利用した、EAP-TLS認証の手順について記載します。
更新履歴
2020/1/29 パラメータの表記を一部修正しました。
対象機器および環境
- Cisco Virtual Wireless LAN Controller (Ver.8.2.x)
- CentOS7(7.6.1810)
- OpenSSL(1.0.2k)
- FreeRADIUS(3.0.13)
このエントリを読むとできること
- OpenSSLで構築したルートCAと中間CAを利用して
- サーバ証明書とクライアント証明書を発行して
- WLCとFreeRADIUSを利用した
- EAP-TLS認証ができるようになる
はず。
関連するエントリ
OpenSSLでプライベート認証局の構築(ルートCA、中間CA)
Cisco WLCにSSIDを作成する(802.1X/PSK) コマンド編+よくつかうコマンド
CentOS7で各種ネットワークサービスを基本設定したメモ(dhcp/radius/proxy/tftp/syslog)
前提条件
サーバ証明書はルートCAから発行
クライアント証明書は中間CAから発行
という構成にしています。
クライアントの増減のたびにルートCAのお世話になるのはどうも違うと思います。中間CAにクライアント証明書の発行の権限を持たせるイメージです。
手順
Cisco WLCの設定
WLCでは以下で作成したような802.1X認証用のSSID作成などが必要です。
Cisco WLCにSSIDを作成する(802.1X/PSK) コマンド編+よくつかうコマンド
Cisco WLCにSSIDを作成する(802.1X/PSK)
チェーン証明書の作成
FreeRADIUSでの証明書配置や、WindowsクライアントのためのPKCS#12作成時に利用するための、チェーン証明書(ルートCA+中間CA)を先に作成しておく。
cd /opt/pki/
openssl x509 -in RootCA/RootCA_crt.pem -out chainCA_crt.pem
openssl x509 -in InterCA/InterCA_crt.pem >> chainCA_crt.pem
FreeRADIUSサーバ
VMnetserv01
というホスト名に対して発行しています。
サーバ証明書発行
RootCAの秘密鍵のパスワードは、 前回構築 した文字列をそのまま利用しています。
(VMnetserv01というサーバに対して発行するので、新規ディレクトリを作成する)
mkdir -p /opt/pki/Server/VMnetserv01
cd /opt/pki/Server/VMnetserv01
(パスワード無し秘密鍵とCSRを同時に発行しています)
openssl req -new \
-out VMnetserv01_csr.pem \
-newkey rsa:2048 \
-nodes \
-keyout VMnetserv01_key.pem \
-subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=VMnetserv01.example.net"
(RootCAで署名します)
cd /opt/pki/RootCA
openssl ca -config ../configs/openssl_sign.cnf -batch -extensions v3_server \
-out ../Server/VMnetserv01/VMnetserv01_crt.pem \
-in ../Server/VMnetserv01/VMnetserv01_csr.pem \
-cert RootCA_crt.pem \
-keyfile RootCA_key.pem \
-passin pass:rootcaprivkeypass
(余計な文字列を取り除きます)
cd /opt/pki/Server/VMnetserv01
openssl x509 -in VMnetserv01_crt.pem -out VMnetserv01_crt.pem
FreeRADIUS設定
(証明書を収容するディレクトリを新規に作成します)
mkdir -p /etc/raddb/p2certs
(DHファイルの作成)
openssl dhparam -5 -out /etc/raddb/p2certs/dh 1024
(各証明書を配置していきます)
cp /opt/pki/Server/VMnetserv01/VMnetserv01_key.pem /etc/raddb/p2certs
cp /opt/pki/Server/VMnetserv01/VMnetserv01_crt.pem /etc/raddb/p2certs
cp /opt/pki/chainCA_crt.pem /etc/raddb/p2certs
証明書ディレクトリの設定を変更
-----8<-----snip-----8<-----
certdir = ${confdir}/p2certs
cadir = ${confdir}/p2certs
-----8<-----snip-----8<-----
eapセクション中の default_eap_type が md5となっていても、tlsとなっていても、デフォルトのEAPが通らない場合はNAKレスポンス中にステーション側のEAP方式を返すらしいので、RADIUSサーバ側で適切なEAP方式を試行するっぽい。
-----8<-----snip-----8<-----
eap {
#default_eap_type = md5
default_eap_type = tls
tls-config tls-common {
#private_key_password = whatever
#private_key_file = ${certdir}/server.pem
#certificate_file = ${certdir}/server.pem
#ca_file = ${cadir}/ca.pem
private_key_file = ${certdir}/VMnetserv01_key.pem
certificate_file = ${certdir}/VMnetserv01_crt.pem
ca_file = ${cadir}/chainCA_crt.pem
}
}
-----8<-----snip-----8<-----
クライアント
クライアント証明書発行
InterCAの秘密鍵のパスワードは、 前回構築 した文字列をそのまま利用しています。
(Client01というクライアントに対して発行するので、新規ディレクトリを作成する)
mkdir -p /opt/pki/Client/Client01
cd /opt/pki/Client/Client01
(パスワード無し秘密鍵とCSRを同時に発行しています)
openssl req -new \
-out Client01_csr.pem \
-newkey rsa:2048 \
-nodes \
-keyout Client01_key.pem \
-subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=Client01.example.net"
(InterCAで署名します)
cd /opt/pki/InterCA
openssl ca -config ../configs/openssl_sign.cnf -batch -extensions v3_client \
-out ../Client/Client01/Client01_crt.pem \
-in ../Client/Client01/Client01_csr.pem \
-cert InterCA_crt.pem \
-keyfile InterCA_key.pem \
-passin pass:intercaprivkeypass
(余計な文字列を取り除きます)
cd /opt/pki/Client/Client01
openssl x509 -in Client01_crt.pem -out Client01_crt.pem
(Windowsで利用するため、PKCS#12:秘密鍵と証明書をまとめたファイルを作成します)
(-passoutでエクスポート用パスワード "exportpass" を与えています)
openssl pkcs12 -export \
-inkey Client01_key.pem \
-in Client01_crt.pem \
-certfile ../../chainCA_crt.pem \
-out Client01_crt.p12 \
-passout pass:exportpass
Windowsクライアント設定
作成したp12ファイルをWindowsクライアントへ転送する。
(画面ではWinSCPを利用)
p12エクスポート時に設定した-passout の文字列を入力する。
(先ほどの例では "exportpass" という文字列)
最下段の「証明書」をダブルクリックして「コンピュータアカウント」を選択し、「次へ」をクリック
選択されたスナップインに 証明書(ローカルコンピュータ)があることを確認して「OK」をクリック
左側メニューの「証明書」→「個人」→「証明書」をクリックし、作成したクライアント証明書が存在するか確認。
証明書をダブルクリックして、「証明書パス」のタブをクリック
証明書パスの画面で「×」印がついておらず、証明書の状態が「この証明書は問題ありません」となっているれば問題なく導入されている。
「OK」をクリックして、閉じる。
Ctrl+Rをクリックして、 control.exe /name Microsoft.NetworkAndSharingCenter
と入力して、「OK」をクリック
中央付近の「新しい接続またはネットワークのセットアップ」をクリック
「ワイヤレスネットワークに手動で接続します」を選択して「次へ」をクリック
「ネットワーク名」にSSIDを入力(例ではIntraGeneral)
自動的に開始するかどうかはお好みで。
SSIDをステルス化していれば「ネットワークがブロードキャストを行っていない~~」にチェックを入れ「次へ」をクリック
表示される画面で「セキュリティ」タブをクリック
ネットワークの認証方法の選択を「Microsoft: スマートカードまたはその他の証明書」を選択し、隣の「設定」をクリック
信頼されたルート証明機関にルートCAのチェックを入れる(例ではexample Root CA)
「新しいサーバまたは信頼された証明機関を~~」にチェックを入れ「OK」をクリック
もとの画面に戻るので、「詳細設定」をクリックすると、下記の画面が表示される。
「802.1Xの設定」タブで、認証モードを指定するにチェックを入れ、プルダウンメニュから「コンピュータの認証」を選択し、「OK」をクリック
その後、ほかの設定画面も「OK」「閉じる」ですべて閉じる。
ここまででWindowsの無線設定が完了しました。
動作確認
最初にRADIUSサーバをデバッグモードで起動させてみて、問題なく認証されるかを確認する。
(radiusサービスが停止していることを確認する)
# systemctl status radiusd
● radiusd.service - FreeRADIUS high performance RADIUS server.
Loaded: loaded (/usr/lib/systemd/system/radiusd.service; enabled; vendor preset: disabled)
Active: inactive (dead) since 木 2019-01-03 19:38:23 JST; 3h 39min ago
Main PID: 6132 (code=exited, status=0/SUCCESS)
1月 03 19:38:23 VMnetserv01.example.net systemd[1]: Stopping FreeRADIUS high performance RADIUS server....
1月 03 19:38:23 VMnetserv01.example.net systemd[1]: Stopped FreeRADIUS high performance RADIUS server..
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
#
(radiusサーバをデバックモードで起動しておく)
# radiusd -X
(ばばばー、って表示されるあ、そのまま流しておく)
デバッグモードで起動したradiusのログの最後のほうに、
Login OK: [host/Client01.example.net] (なんちゃら~~)
と表示されていれば、認証できている。
認証成功時のradiusログは以下のようなもの
(20) Received Access-Request Id 53 from 10.254.10.201:50312 to 10.254.10.251:1812 length 302
(20) User-Name = "host/Client01.example.net"
(20) Chargeable-User-Identity = 0xc9
(20) Location-Capable = Civic-Location
(20) Calling-Station-Id = "40-e2-30-af-55-79"
(20) Called-Station-Id = "d4-a0-2a-11-d5-a0:IntraGeneral"
(20) NAS-Port = 1
(20) Cisco-AVPair = "audit-session-id=c90afe0a00000078b3192e5c"
(20) Acct-Session-Id = "5c2e19b3/40:e2:30:af:55:79/168"
(20) NAS-IP-Address = 10.254.10.201
(20) NAS-Identifier = "VMwlc01"
(20) Airespace-Wlan-Id = 1
(20) Service-Type = Framed-User
(20) Framed-MTU = 1300
(20) NAS-Port-Type = Wireless-802.11
(20) Tunnel-Type:0 = VLAN
(20) Tunnel-Medium-Type:0 = IEEE-802
(20) Tunnel-Private-Group-Id:0 = "4001"
(20) EAP-Message = 0x020700060d00
(20) State = 0x47ff5d6b42f8509cdd59458a7ab664e0
(20) Message-Authenticator = 0x4e520e371412faf3d280e4d28edc2686
(20) session-state: No cached attributes
(20) # Executing section authorize from file /etc/raddb/sites-enabled/default
(20) authorize {
(20) policy filter_username {
(20) if (&User-Name) {
(20) if (&User-Name) -> TRUE
(20) if (&User-Name) {
(20) if (&User-Name =~ / /) {
(20) if (&User-Name =~ / /) -> FALSE
(20) if (&User-Name =~ /@[^@]*@/ ) {
(20) if (&User-Name =~ /@[^@]*@/ ) -> FALSE
(20) if (&User-Name =~ /\.\./ ) {
(20) if (&User-Name =~ /\.\./ ) -> FALSE
(20) if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) {
(20) if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) -> FALSE
(20) if (&User-Name =~ /\.$/) {
(20) if (&User-Name =~ /\.$/) -> FALSE
(20) if (&User-Name =~ /@\./) {
(20) if (&User-Name =~ /@\./) -> FALSE
(20) } # if (&User-Name) = notfound
(20) } # policy filter_username = notfound
(20) [preprocess] = ok
(20) [chap] = noop
(20) [mschap] = noop
(20) [digest] = noop
(20) suffix: Checking for suffix after "@"
(20) suffix: No '@' in User-Name = "host/Client01.example.net", looking up realm NULL
(20) suffix: No such realm "NULL"
(20) [suffix] = noop
(20) eap: Peer sent EAP Response (code 2) ID 7 length 6
(20) eap: No EAP Start, assuming it's an on-going EAP conversation
(20) [eap] = updated
(20) files: users: Matched entry DEFAULT at line 1
(20) files: users: Matched entry DEFAULT at line 1
(20) files: users: Matched entry DEFAULT at line 1
(20) [files] = ok
(20) [expiration] = noop
(20) [logintime] = noop
(20) [pap] = noop
(20) } # authorize = updated
(20) Found Auth-Type = eap
(20) # Executing group from file /etc/raddb/sites-enabled/default
(20) authenticate {
(20) eap: Expiring EAP session with state 0x47ff5d6b42f8509c
(20) eap: Finished EAP session with state 0x47ff5d6b42f8509c
(20) eap: Previous EAP request found for state 0x47ff5d6b42f8509c, released from the list
(20) eap: Peer sent packet with method EAP TLS (13)
(20) eap: Calling submodule eap_tls to process data
(20) eap_tls: Continuing EAP-TLS
(20) eap_tls: Peer ACKed our handshake fragment. handshake is finished
(20) eap_tls: [eaptls verify] = success
(20) eap_tls: [eaptls process] = success
(20) eap: Sending EAP Success (code 3) ID 7 length 4
(20) eap: Freeing handler
(20) [eap] = ok
(20) } # authenticate = ok
(20) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(20) post-auth {
(20) update {
(20) No attributes updated
(20) } # update = noop
(20) [exec] = noop
(20) policy remove_reply_message_if_eap {
(20) if (&reply:EAP-Message && &reply:Reply-Message) {
(20) if (&reply:EAP-Message && &reply:Reply-Message) -> FALSE
(20) else {
(20) [noop] = noop
(20) } # else = noop
(20) } # policy remove_reply_message_if_eap = noop
(20) } # post-auth = noop
(20) Login OK: [host/Client01.example.net] (from client example.net port 1 cli 40-e2-30-af-55-79)
(20) Sent Access-Accept Id 53 from 10.254.10.251:1812 to 10.254.10.201:50312 length 0
(20) Tunnel-Type = VLAN
(20) Tunnel-Medium-Type = IEEE-802
(20) Tunnel-Private-Group-Id = "1"
(20) MS-MPPE-Recv-Key = 0x2fffb3dd4351fa83c019ab3eaa5451386a3deb0c2cebbda985094dd7818f0e13
(20) MS-MPPE-Send-Key = 0x1ed298b804eecfe8303731cc5a186df7bd56b678170d6f475b77acbca86cc57e
(20) EAP-Message = 0x03070004
(20) Message-Authenticator = 0x00000000000000000000000000000000
(20) User-Name = "host/Client01.example.net"
(20) Finished request
ここまでできたら、radiusサーバを ctrl+C
で停止させる。
# systemctl enable radiusd
# systemctl start radiusd
# systemctl status radiusd
● radiusd.service - FreeRADIUS high performance RADIUS server.
Loaded: loaded (/usr/lib/systemd/system/radiusd.service; enabled; vendor preset: disabled)
Active: active (running) since 木 2019-01-03 23:48:58 JST; 11s ago
Process: 28658 ExecStart=/usr/sbin/radiusd -d /etc/raddb (code=exited, status=0/SUCCESS)
Process: 28654 ExecStartPre=/usr/sbin/radiusd -C (code=exited, status=0/SUCCESS)
Process: 28653 ExecStartPre=/bin/chown -R radiusd.radiusd /var/run/radiusd (code=exited, status=0/SUCCESS)
Main PID: 28661 (radiusd)
CGroup: /system.slice/radiusd.service
mq28661 /usr/sbin/radiusd -d /etc/raddb
1月 03 23:48:58 VMnetserv01.example.net systemd[1]: Starting FreeRADIUS high performance RADIUS server....
1月 03 23:48:58 VMnetserv01.example.net systemd[1]: Started FreeRADIUS high performance RADIUS server..
WLCからは以下のように見えます
(Cisco Controller) >show client summary ssid ip username
Number of Clients................................ 3
MAC Address AP Name Status SSID IP Address Username
----------------- ---------------- ------------- -------------------- -------------------------------- ------------------
40:e2:30:af:55:79 APbranch01-01F01 Associated IntraGeneral 10.101.19.1 host/Client01.example.net
50:dc:e7:b3:bf:34 APhq01-01F01 Associated IntraStrict 10.1.19.2 N/A
ac:63:be:92:9d:f9 APhq01-01F01 Associated IntraStrict 10.1.19.5 N/A
(Cisco Controller) >
さいごに
感想
証明書失効時の動作検証などできていないため、後日整理したいと思います。
おまけ
チェーン証明書、サーバ証明書、クライアント証明は、以下の一連のテキストコピペで発行できます。
前回作成のルートCAと中間CA のあとに発行すると、その環境のままサーバ証明書とクライアント証明書が発行できます。
cd /opt/pki/
openssl x509 -in RootCA/RootCA_crt.pem -out chainCA_crt.pem
openssl x509 -in InterCA/InterCA_crt.pem >> chainCA_crt.pem
mkdir -p /opt/pki/Server/VMnetserv01
cd /opt/pki/Server/VMnetserv01
openssl req -new -out VMnetserv01_csr.pem -newkey rsa:2048 -nodes -keyout VMnetserv01_key.pem -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=VMnetserv01.example.net"
cd /opt/pki/RootCA
openssl ca -config ../configs/openssl_sign.cnf -out ../Server/VMnetserv01/VMnetserv01_crt.pem -in ../Server/VMnetserv01/VMnetserv01_csr.pem -cert RootCA_crt.pem -keyfile RootCA_key.pem -passin pass:rootcaprivkeypass -batch -extensions v3_server
cd /opt/pki/Server/VMnetserv01
openssl x509 -in VMnetserv01_crt.pem -out VMnetserv01_crt.pem
mkdir -p /opt/pki/Client/Client01
cd /opt/pki/Client/Client01
openssl req -new -out Client01_csr.pem -newkey rsa:2048 -nodes -keyout Client01_key.pem -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=Client01.example.net"
cd /opt/pki/InterCA
openssl ca -config ../configs/openssl_sign.cnf -out ../Client/Client01/Client01_crt.pem -in ../Client/Client01/Client01_csr.pem -cert InterCA_crt.pem -keyfile InterCA_key.pem -passin pass:intercaprivkeypass -batch -extensions v3_client
cd /opt/pki/Client/Client01
openssl x509 -in Client01_crt.pem -out Client01_crt.pem
openssl pkcs12 -export -inkey Client01_key.pem -in Client01_crt.pem -certfile ../../chainCA_crt.pem -out Client01_crt.p12 -passout pass:exportpass