WPA3-Enterprise 192 bit modeのためのFreeRADIUS構築

# はじめに
 
　`NETGEAR WAX610`[^1]の`WPA3-Enterprise` モードを`FreeRADIUS`用いて動かすのに苦労したので備忘録として残そうと思います。
# WPA3-Enterprise
　`WPA3-Enterprise`は`WPA2`の後継となる現在最新の企業向けWi-Fiセキュリティの規格です。端末とアクセスポイントの認証を行うのに`802.1X認証`を行います。
 　WPA3-Enterpriseには以下の3つモードがあります
 * WPA3 Enterprise Only mode
 * WPA3 Enterprise Transition mode
 * WPA3 Enterprise 192-bit mode(CNSA)

　**NETGEAR WAX610は192-bit modeです。**

:::note info
`192-bit mode`の**192**とは鍵長ではなく、暗号における**192ビットセキュリティ**を意味します
:::
# 802.1X
　802.1X認証は`Supplicant`(端末)と`Authenticator`(APやSwitch)と`Authentication Server`(Radius Server)で構成されます。`FreeRADIUS`は`Authentication Server`として機能する**オープンソースのRadius Server**となります。
 
　IEEE802.1X認証は認証方法に明確な規定はないのですが、EAP方式のいくつかの認証方式があります。
 * EAP-TLS
 * EAP-TTLS
 * EAP-PEAP
 * EAP-FAST
 * EAP-LEAP
 * EAP-MD5
 
　**192-bit modeはTLS認証しか対応していないため、`EAP-TLS認証`で構築します。**

# 192-bit modeの要件
192-bit modeの面倒なところは、**FreeRADIUSのデフォルトの設定ではWi-Fi Allienceが公開している要件[^2]を満たさない** ことです。具体的には次の`暗号スイート`のいずれかを満たす必要があります。**暗号スイートの見方はググってください。[^3]** 
* `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`
* `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`
　**RSA：3072bit以上**
* `TLS_DHE_RSA_WITH_AES_256_GCM_SHA384`
　**RSA：3072bit以上**
　**DHE ：3072bit以上**
 
今回は```TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384```を満たすように設定を行います。
 # 手順
  手順は以下の通りです。
  1. FreeRADIUSのインストール
  2. 証明書の作成
  2. EAP-TLS認証の設定
  2. ローカルでの動作確認
  2. ネットワーク経由で動作確認
  3. 端末に証明書をインストール
  3. アクセスポイントの設定
  3. 最終テスト
# 構築環境
 * `AlmaLinux 8.8` 
 * `NETGEAR WAX610`(アクセスポイント)
 * `Cisco 800M Series`(ルーター)
 
 FreeRADIUSのバージョンは以下の通りです。
```:FreeRadiusのバージョン
# radiusd -v
radiusd: FreeRADIUS Version 3.0.20, for host x86_64-redhat-linux-gnu
FreeRADIUS Version 3.0.20
Copyright (C) 1999-2019 The FreeRADIUS server project and contributors
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE
You may redistribute copies of FreeRADIUS under the terms of the
GNU General Public License
For more information about these matters, see the file named COPYRIGHT
```

# 1.FreeRADIUSのインストールと動作確認
　環境によってはインストール済みかもしれません。その場合はとりあえずパッケージをアップデートしておくといいかもしれません。

root権限で作業をします
```
#root権限
sudo su
```
 
 ```
 #FreeRADIUSのインストール
 dnf install freeradius freeradius-utils
 ```
 インストールされたパッケージは ```/etc/raddb```に存在します。FreeRADIUSの設定および証明書の発行は`/etc/raddb`以下の設定ファイルを編集していきます。
 
 # 2.証明書の作成
EAP-TLS認証に用いる証明書を発行します。
FreeRADIUSでは証明書の発行にcnf形式の設定ファイルを利用します。
以下のファイルを編集します。
* `/etc/raddb/certs/ca.cnf` (ルート証明書の設定)
* `/etc/raddb/certs/server.cnf` (サーバー証明書の設定)
* `/etc/raddb/certs/client.cnf` (クライアント証明書の設定)
## 2.1 ルート証明書の設定
まずは、ルート証明書の設定を編集していきます。重要な箇所だけ示します。
```ca.cnf
[CA_default]
default_days          = 1200
default_bits          = 3072
commonName            = "uni root certificate"
```
* `default_bits`: 証明書の公開鍵の強度です。要件は```RSA3072```以上です。
* `default_days`は証明書の有効期限です。お好みです。
* `common_name`は証明書の名前です。お好みです。

## 2.2 サーバー証明書の設定
　次にサーバー証明書の設定をしていきます。こちらはちょっと厄介です。既出の項目の説明は省きます
``` server.cnf
[CA_default]
default_days          = 800
default_md            = sha384
copy_extensions       = copy

[req]
default_bits          = 3072
req_extensions        = v3_req

[server]
commonName            = "Uni Server Certificate"
subjectAltName = @alt_names

[alt_names]
DNS.1 = example.com
DNS.2 = aaa.example.com
```
* `default_md`:署名アルゴリズムです。要件はSHA384です。
* `copy_extensions`・`req_extensions`・`subjectAltName`・`DNS.1`・`DNS.2`: Android11以上の端末で使うためのおまじないです。

:::note info 
 Android 11以上の端末ではEAP-TLS認証の検証に`ドメイン名`が必要となりました。そのため、証明書にドメインの設定を書いています。*ドメインは架空のもので構いません。* 
:::
## 2.3 クライアント証明書の設定
 クライアント証明書のcommonName認証時にFreeRADIUSのログに表示されます。
```client.cnf
[CA_defaults]
default_days          = 1200
default_md            = sha384
default_bits          = 3072
[client]
commonName            = uni8sai
```

## 2.4 証明書の発行
 証明書の設定が終わったら発行を行います。makeコマンドの実行で簡単に可能です。
``` :証明書の発行
# make all
```
* コマンド実行後に以下のファイルができます
    * `ca.pem` (ルート証明書)
    * `ca.key` (ルート証明書の秘密鍵)
    * `ca.crl`(CRL)
    * `server.pem`(サーバー証明書と秘密鍵)
    * `server.crt`(サーバー証明書)
    * `server.key`(サーバー証明書の秘密鍵)
    * `client.pem`(クライアント証明書と秘密鍵)
    * `client.crt`(クライアント証明書)
    * `client.key`(クライアント証明書の秘密鍵)


# 3. EAP-TLS認証の設定
証明書の発行をしたら、いよいよFreeRadiusでEAP-TLS認証ができるように設定します。```/etc/raddb/mods-available/eap```を編集します。
``` :/etc/raddb/mods-available/eap
default_eap_type = tls
private_key_password = whatever
private_key_file = ${certdir}/server.pem
certificate_file = ${certdir}/server.pem
ca_file = ${cadir}/ca.pem
allow_expired_crl = yes
cipher_list = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CAMELLIA128-SHA"
ecdh_curve = "secp384r1"
```
* `default_eap_type`:EAPのデフォルトの認証方式
* `private_key_password`:サーバー証明書のパスワード。デフォルトのままですが、変更する場合は`sever.cnf`の`input(output)_password`の両方も同じものに変更してください
* `certificate_file`: サーバー証明書のファイルを指定
* `private_key_file`:サーバー証明書の秘密鍵を指定
* `ca_file`: ルート証明書のファイルを指定
* `allowexpired_crl`: 有効期限の切れたcrlも使用可能に
* `cipher_list`: EAP-TLS通信で許可する暗号スイート。明示的に指定していますが、`"HIGH"`で大丈夫なはずです。
* `ecdh_curve`: ECDHEの鍵長。384にしてありますが、デフォルトの256bitで大丈夫です。(あとで問題ないと気づきました)

:::note info
`server.pem`は証明書と秘密鍵が一体化しているため、証明書と秘密鍵は同じファイルになるはずです。
:::

:::
# 4.ローカルホストで動作確認
ルート証明書とクライアント証明書・秘密鍵をホームディレクトリにコピーしてから、ローカルホストでテストします。
## 4.1 証明書のコピー
いちいち権限付与するのめんどいので、-aオプションで属性そのままコピーしました。
```:ホームディレクトリへコピー
# cp -a /etc/raddb/certs/ca.pem .
# cp -a /etc/raddb/certs/client.crt .
# cp -a /etc/raddb/certs/client.key .
```
## 4.2 テスト用configの設定
ホームディレクトリに以下の内容のファイル(eap-tls-test.conf)を作成します。
```eap-tls-test.conf
network={
key_mgmt=WPA-EAP
eap=TLS
anonymous_identity="anonymous"
ca_cert="ca.pem"
client_cert="client.crt"
private_key="client.key"
private_key_passwd="whatever"
}
```

次に/etc/raddb/clients.confを以下のように編集します。
```/etc/raddb/clients.conf
client localhost {
#略
secret = testing123
#以下略
}
```

## 4.3 テスト
freeradiusをバッググラウンド(screen)で実行します。

screenコマンドって最初から入ってるでしょ...と思ったら入ってませんでした。
しかも、centosレポジトリにも入ってないようです。
そのため、EPELレポジトリからインストールします。
```:screenのインストール
# dnf install epel-release
# dnf --enablerepo=epel install screen
```
これで、screenコマンドが使えるはずです。screenコマンドでtestという名前のセッションを作り、そこでFreeRADIUSを実行しましょう。
``` 
screen -S test
sudo radiusd -X
```
screenをデタッチ(ctrl + a + d)した後、eapol_testコマンドを実行します。
``` :eapolでテスト
eapol_test -c eap-tls-test.conf -s testing123
```
いっぱいログが出力されますが最終的にSUCCESSと表示されればローカル上でのテストに成功です
# 5 ネットワーク経由で動作確認
　4章ではローカルホストでのテストだったため、認証する端末とRadiusサーバーが同じでした。
ここでは、Radiusサーバーをローカルネットワークに置き、同じネットワークに接続する他の端末からRadiusサーバーにアクセスして認証可能か確認します。
## 5.1 サーバー側の設定
```/etc/raddb/clients.conf```に以下の内容を追加します。(IPやshortnameは自分の環境で適宜変えてください)

```/etc/raddb/clients.conf
 client private-network-1 {
        ipaddr          = 10.10.10.0/25
        proto = *
        secret          = testing123
        shortname       = NETGEAR
        require_message_authenticator = no
        nas_type        = other
}
```
ファイアウォールの設定をします。これを忘れて沼った人がいるとかいないとか。
``` :設定されているサービスの確認
firewall-cmd --list-all --zone=public
```
表示されるservicesの項目にradiusがないはずなので、追加します。
``` :ファイアウォールの追加設定
# firewall-cmd --add-service=radius --zone=public --permanent
# firewall-cmd --reload
```
## 5.2 動作確認する端末側の設定
次に、検証するlinux端末に4.1節と同じルート証明書とクライアント証明書・秘密鍵をコピーし、eap-tls-test.confを作成します。


## 5.3 テスト
```
eapol_test -a [radiusサーバーのIP] -c eap-tls-test.conf -s testing123 
```
実行後SUCCESSと表示されれば成功です。

# 6. 端末に証明書をインストール
　電子証明書を端末にインストールします。今回は、`Windows10 Pro`と`Android12`にインストールしてみました。2.4節で発行したルート、クライアント証明書を何らかの形で端末に配布してインストールするだけなので割愛します。**PKCS#12フォーマットの証明書を発行しておくと便利です。**


 また、Windows 10 Proにルート証明書をインストールする場合は**ルート証明書信頼するように設定してください**。クライアント証明書のインストール時にパスワードが聞かれますが、`/etc/raddb/certs/client.cnf`記載のパスワードを入力してください
:::

# 7. アクセスポイントの設定
　WAX610の管理画面から`/Wireless/Basic`に行き、`Authentication`に`WPA3 Enterprise`を選択します。
次に`/Security/RADIUS SettingsのIPv4Address`(RadiusサーバーのIP)、port(1812か1813)、Passwordを設定します。
私の環境では以下のように設定しました。
![スクリーンショット 2023-11-29 151506.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627482/e4383a34-2f87-48ed-a32f-12d86b573596.png)

# 8. 最終テスト
radiusサーバーを起動して、端末からアクセスポイントに接続してみましょう。
```
radiusd -X
```
端末がアクセスポイントに接続できれば成功です。**おめでとうございます**
# 備考
* 私の環境では**DHファイルが存在しない**状況が発生したので以下のコマンドを実行しました。
```
openssl dhparam -check -text -5 4096 -out /etc/raddb/certs/dh 
```
* DHファイルは4096bitで作成する必要あるのかと聞かれると、実際ないです。**参考サイト見たら4096bitで作成していたので...[^4]**


* makeコマンドの実行後、以下のコマンドを実行すれば**PKCS#12フォーマットの証明書**を発行できます。このフォーマットの証明書は端末へのインストール時に便利です。
```:PKCS#12形式に変換
# openssl pkcs12 -export -in ca.pem -inkey ca.key -out ca.p12
#同じディレクトリに ca.p12が作成されます
```
* ディレクトリの`mods-available`は`mods-enabled`のリンク先です。そのため、多くのFreeRADIUSの記事では、`mods-enabled`下のファイルを弄っていると思われます。[^5]
　
* `virtualbox`上でも構築できます。実際に`AlmaLinux9`で構築に成功しました。



# 最後に
　初めての記事投稿だったので文章に拙い所があったと思いますが、お許しを。
　WPA3が発表されてから5年ほど経ちますが、WPA3-Enterprise はまだまだ普及してないし、一般家庭用アクセスポイントにはそもそもEnterpriseモードがないことの方が多いので、この記事がどれ程役に立つかわかりませんが、私と同じように、構築に困った方のお役に立てれば幸いです



[^1]:[製品ページ](https://www.netgear.com/jp/business/wifi/access-points/wax610/)
[^2]:[WPA3 Specification](https://www.wi-fi.org/system/files/WPA3%20Specification%20v3.1.pdf)
[^3]:[TLS暗号設定ガイドライン](https://www.ipa.go.jp/security/crypto/guideline/gmcbt80000005ufv-att/ipa-cryptrec-gl-3001-3.0.1.pdf)
[^4]:[FreeRadius EAP-TLS configuration](https://wiki.alpinelinux.org/wiki/FreeRadius_EAP-TLS_configuration)
[^5]:[なぜmods-enabledの方を弄らなかったのか私にもわかりません](https://qiita.com/chris949/items/6f100d6b7d6675dc3789)
[スイッチとFreeRADIUSまとめて構築](https://qiita.com/kato__tatsu/items/26393ea7ef50db0462f9)