FreeRadiusとOpenWrtを使ったWPA Enterprise (EAP-TLS)の設定 (1)

WPA PersonalとWPA Enterpriseの違い

WPA PersonalはルーターなどのAPとClientのデバイスとのWi-Fi通信で事前共有鍵(PSK)を使った最も普及している暗号化方式です。WPAにはWPAとWPA2の2種類があり、PSK方式の暗号化アルゴリズムにはTKIPとAESの2種類があり、そのいずれの組み合わせでも使用が可能です。またWPA-PSKとWPA2-PSKの混在モードでも設定可能です。

WPA EnterpriseはRadius(IEEE 802.1X)を使ったユーザー認証です。暗号化アルゴリズムは、WPA Personalと同じくTKIPとAESの2種類あり混在モードも可能ですが、セキュリティ的にはAESのほうが優れているためAESのみの設定がおすすめです。認証方法にはEPA-TLS、EPA-LEAP、EPA-TTLSなどいくつか方式がありますが、EPA-TLSがもっとも安全なので、ここではEPA-TLSの設定で進めていきます。

WPA Enterpriseのメリット

WPA Enterpriseを採用するメリットは、事前共有鍵を使ったWPA Personalの認証に比べセキュリティが高いことです。もしWPA Personalだと事前共有鍵が盗まれたら、すべての接続しているデバイスの共有鍵も作りなおさなければなりません。WPA Enterpriseでは各ユーザーごとに認証を行うため、仮にそのユーザの鍵が盗まれたとしても、そのユーザーに対して証明書破棄をすればほかのユーザーは影響を受けません。

もうひとつのメリットは、複数のAPを運用してい場合、APからAPに移動した時にWPA Personalは認証、ローカルネットワークでのIP割当て順で再接続します。WPA Enterpriseの再接続はRadius側で認証しているので、ローカルネットワークでのIP割当てのみになります。その違いからAP間の移動でのWi-Fi通信の切り替えがスムーズに行なえます。

WPA Enterpriseのセットアップは次の3つのステップです。

  1. Radiusサーバーのセットアップ
  2. WPA Enterprise用のAPのセットアップ
  3. クライアントのセットアップ

RadiusサーバーはFreeRadiusを使うことにしました。APのセットアップではOpenWrtの入ったルーターを使用し、各クライアントごとの設定方法を解説します。

1. FreeRadiusのセットアップ

Note:FreeRadius 3では設定ファイルのディレクトリが異なります。設定内容は同じですが、このセットアップではFreeRadius 2を使っています。

/etc/freeradius/eap.conf:

eap { 
               default_eap_type = tls 
               timer_expire     = 60 
               ignore_unknown_eap_types = no 
               cisco_accounting_username_bug = no 
               max_sessions = ${max_requests} 
               tls { 
                       certdir = ${confdir}/certs 
                       cadir = ${confdir}/certs 
                       private_key_password = whatever 
                       private_key_file = ${certdir}/server.key 
                       certificate_file = ${certdir}/server.pem 
                       CA_file = ${cadir}/ca.pem 
                       dh_file = ${certdir}/dh 
                       random_file = /dev/urandom 
                       CA_path = ${cadir} 
                       cipher_list = "HIGH" 
                       ecdh_curve = "prime256v1" 
                       cache { 
                             enable = no 
                             lifetime = 24 # hours 
                             max_entries = 255 
                       } 
                       verify { 
                               tmpdir = /var/tmp/radiusd 
                               client = "/usr/bin/openssl verify -CApath ${..CA_path} %{TLS-Client-Cert-Filename}" 
                       } 
                       ocsp { 
                             enable = no 
                             override_cert_url = yes 
                             url = "http://127.0.0.1/ocsp/" 
                       } 
               } 
       }

/etc/freeradius/clients.conf:

client 192.168.1.0/27 { 
        secret    = secret1 
        shortname = localAP 
        require_message_authenticator = yes 
}

次に /var/tmp/radiusdを作成します。

sudo mkdir /var/tmp/radiusd
sudo chown freerad /var/tmp/radiusd
sudo chgrp freerad /var/tmp/radiusd
sudo chmod 700 /var/tmp/radiusd

必要ないバーチャルサーバを削除します。そして今回の設定用にdefaultからコピーします。(例:my_ap)

sudo rm /etc/freeradius/sites-enabled/*
sudo cd /etc/freeradius/sites-available
sudo cp default my_ap
sudo ln -s /etc/freeradius/sites-available/my_ap /etc/freeradius/sites-enabled/my_ap
sudo nano my_ap

/etc/freeradius/sites-enabled/my_ap:

authorize { 
        preprocess 
        eap { 
                ok = return 
        } 
        expiration 
        logintime 
} 
authenticate { 
        eap 
} 
preacct { 
        preprocess 
        acct_unique 
        suffix 
} 
session { 
        radutmp 
} 
post-auth { 
        exec 
        Post-Auth-Type REJECT { 
                attr_filter.access_reject 
        } 
} 
pre-proxy { 
} 
post-proxy { 
        eap 
}

バーチャルサーバに登録します。

sudo cd /etc/freeradius/sites-enabled/
sudo ln -s ../sites-available/my_ap

次に起動できるかテストを行います。このときデバッグモードで立ち上げます。

sudo systemctl stop freeradius
sudo freeradius -X

証明書の作成

sudo apt-get install make

次にデフォルトの証明書を削除します。

sudo cd /etc/freeradius/certs/
sudo rm *.pem *.key

次に証明書の作成にあたってディレクトリを作成し、証明書作成環境を整えます。

sudo mkdir -p /var/certs/freeradius
sudo chgrp ssl-cert /var/certs/freeradius
sudo chmod 710 /var/certs/freeradius
sudo cp /usr/share/doc/freeradius/examples/certs/* /var/certs/freeradius/
sudo cd /var/certs/freeradius/
sudo rm bootstrap
sudo chmod 600 *
sudp make destroycerts
sudo make dh
sudo make index.txt
sudo make serial

次にca.cnfを編集します。編集する箇所は、default_days、default_md、default_bits、input_password、output_password、[certificate_authority]の段落です。例とし次のようになります。

[ ca ]                                                                                                 
default_ca              = CA_default                                                                   
                                                                                                       
[ CA_default ]                                                                                         
dir                     = ./ 
certs                   = $dir 
crl_dir                 = $dir/crl 
database                = $dir/index.txt 
new_certs_dir           = $dir 
certificate             = $dir/ca.pem 
serial                  = $dir/serial 
crl                     = $dir/crl.pem 
private_key             = $dir/ca.key 
RANDFILE                = $dir/.rand 
name_opt                = ca_default 
cert_opt                = ca_default 
default_days            = 1095 
default_crl_days        = 30 
default_md              = sha256 
preserve                = no 
policy                  = policy_match 
crlDistributionPoints   = URI:http://www.example.com/example_ca.crl 
 
[ policy_match ] 
countryName             = match 
stateOrProvinceName     = match 
organizationName        = match 
organizationalUnitName  = optional 
commonName              = supplied 
emailAddress            = optional 
 
[ policy_anything ] 
countryName             = optional 
stateOrProvinceName     = optional 
localityName            = optional 
organizationName        = optional 
organizationalUnitName  = optional 
commonName              = supplied 
emailAddress            = optional 
 
[ req ] 
prompt                  = no 
distinguished_name      = certificate_authority 
default_bits            = 4096 
input_password          = radiuspass 
output_password         = pass 
x509_extensions         = v3_ca 
 
[certificate_authority] 
countryName             = JP 
stateOrProvinceName     = Radius 
localityName            = Somewhere 
organizationName        = Example Inc. 
emailAddress            = admin@example.com 
commonName              = "Radius Certificate Authority" 
 
[v3_ca] 
subjectKeyIdentifier    = hash 
authorityKeyIdentifier  = keyid:always,issuer:always 
basicConstraints        = CA:true 
crlDistributionPoints   = URI:http://www.example.com/example_ca.crl

ca.pemを作成します。

sudo make ca.pem
sudo make ca.der
sudo make printca

もしエラーが出てやり直す場合は次のようにします。

sudo make destroycerts

次にserver.cnfを同様に編集します。

[ ca ] 
default_ca              = CA_default 
 
[ CA_default ] 
dir                     = ./ 
certs                   = $dir 
crl_dir                 = $dir/crl 
database                = $dir/index.txt 
new_certs_dir           = $dir 
certificate             = $dir/ca.pem 
serial                  = $dir/serial 
crl                     = $dir/crl.pem 
private_key             = $dir/ca.key 
RANDFILE                = $dir/.rand 
name_opt                = ca_default 
cert_opt                = ca_default 
default_days            = 1095 
default_crl_days        = 30 
default_md              = sha256 
preserve                = no 
policy                  = policy_match 
 
[ policy_match ] 
countryName             = match 
stateOrProvinceName     = match 
organizationName        = match 
organizationalUnitName  = optional 
commonName              = supplied 
emailAddress            = optional 
 
[ policy_anything ] 
countryName             = optional 
stateOrProvinceName     = optional 
localityName            = optional 
organizationName        = optional 
organizationalUnitName  = optional 
commonName              = supplied 
emailAddress            = optional 
 
[ req ] 
prompt                  = no 
distinguished_name      = server 
default_bits            = 4096 
input_password          = radiuspass 
output_password         = radiuspass
 
[server] 
countryName             = JP 
stateOrProvinceName     = Radius 
localityName            = Somewhere 
organizationName        = Example Inc. 
emailAddress            = admin@example.com 
commonName              = "Radius Server Certificate"

そしてserver.pemを作成します。

sudo make server.pem

次にclient.cnfを編集します。

[ ca ] 
default_ca              = CA_default 
 
[ CA_default ] 
dir                     = ./ 
certs                   = $dir 
crl_dir                 = $dir/crl 
database                = $dir/index.txt 
new_certs_dir           = $dir 
certificate             = $dir/ca.pem 
serial                  = $dir/serial 
crl                     = $dir/crl.pem 
private_key             = $dir/ca.key 
RANDFILE                = $dir/.rand 
name_opt                = ca_default 
cert_opt                = ca_default 
default_days            = 1095 
default_crl_days        = 30 
default_md              = sha256 
preserve                = no 
policy                  = policy_match 
 
[ policy_match ] 
countryName             = match 
stateOrProvinceName     = match 
organizationName        = match 
organizationalUnitName  = optional 
commonName              = supplied 
emailAddress            = optional 
 
[ policy_anything ] 
countryName             = optional 
stateOrProvinceName     = optional 
localityName            = optional 
organizationName        = optional 
organizationalUnitName  = optional 
commonName              = supplied 
emailAddress            = optional 
 
[ req ] 
prompt                  = no 
distinguished_name      = client 
default_bits            = 4096 
input_password          = radiuspass 
output_password         = radiuspass
 
[client] 
countryName             = JP 
stateOrProvinceName     = Radius 
localityName            = Somewhere 
organizationName        = Example Inc. 
emailAddress            = user1@my.net 
commonName              = user1@my.net

Makefileはそのままでもよいのですが、使いやすいように編集します。

Makefile  
###################################################################### 
# 
#       Make file to be installed in /etc/raddb/certs to enable 
#       the easy creation of certificates. 
# 
#       See the README file in this directory for more information. 
# 
#       $Id: de56a19f2f8b0b764c076cd825d8375f9c7e0c85 $ 
# 
###################################################################### 
 
DH_KEY_SIZE     = 1024 
 
# 
#  Set the passwords 
# 
PASSWORD_SERVER = `grep output_password server.cnf | sed 's/.*=//;s/^ *//'` 
PASSWORD_CA     = `grep output_password ca.cnf | sed 's/.*=//;s/^ *//'` 
PASSWORD_CLIENT = `grep output_password client.cnf | sed 's/.*=//;s/^ *//'` 
 
USER_NAME       = `grep emailAddress client.cnf | grep '@' | sed 's/.*=//;s/^ *//'` 
CA_DEFAULT_DAYS = `grep default_days ca.cnf | sed 's/.*=//;s/^ *//'` 
 
###################################################################### 
# 
#  Make the necessary files, but not client certificates. 
# 
###################################################################### 
.PHONY: all 
all: index.txt serial dh random server ca 
 
.PHONY: client 
client: client.pem 
 
.PHONY: ca 
ca: ca.der 
 
.PHONY: server 
server: server.pem server.vrfy 
 
###################################################################### 
# 
#  Diffie-Hellman parameters 
# 
###################################################################### 
dh: 
        openssl dhparam -out dh $(DH_KEY_SIZE) 
 
###################################################################### 
# 
#  Create a new self-signed CA certificate 
# 
###################################################################### 
ca.key ca.pem: ca.cnf 
        @[ -f index.txt ] || $(MAKE) index.txt 
        @[ -f serial ] || $(MAKE) serial 
        openssl req -new -x509 -keyout ca.key -out ca.pem \ 
                -days $(CA_DEFAULT_DAYS) -config ./ca.cnf 
 
ca.der: ca.pem 
        openssl x509 -inform PEM -outform DER -in ca.pem -out ca.der 
 
###################################################################### 
# 
#  Create a new server certificate, signed by the above CA. 
# 
###################################################################### 
server.csr server.key: server.cnf 
        openssl req -new  -out server.csr -keyout server.key -config ./server.cnf 
 
server.crt: server.csr ca.key ca.pem 
        openssl ca -batch -keyfile ca.key -cert ca.pem -in server.csr  -key $(PASSWORD_CA) -out server
.crt -extensions xpserver_ext -extfile xpextensions -config ./server.cnf 
 
server.p12: server.crt 
        openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12  -passin pass:$(PASSWO
RD_SERVER) -passout pass:$(PASSWORD_SERVER) 
 
server.pem: server.p12 
        openssl pkcs12 -in server.p12 -out server.pem -passin pass:$(PASSWORD_SERVER) -passout pass:$(
PASSWORD_SERVER) 
 
.PHONY: server.vrfy 
server.vrfy: ca.pem 
        openssl verify -CAfile ca.pem server.pem 
 
###################################################################### 
# 
#  Create a new client certificate, signed by the the above CA 
# 
###################################################################### 
client.csr client.key: client.cnf 
        openssl req -new  -out client.csr -keyout client.key -config ./client.cnf 
        cp client.key $(USER_NAME).key 
 
client.crt: client.csr ca.pem ca.key 
        openssl ca -batch -keyfile ca.key -cert ca.pem -in client.csr  -key $(PASSWORD_CA) -out client
.crt -extensions xpclient_ext -extfile xpextensions -config ./client.cnf 
 
client.p12: client.crt 
        openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12  -passin pass:$(PASSWO
RD_CLIENT) -passout pass:$(PASSWORD_CLIENT) 
        cp client.p12 $(USER_NAME).p12 
 
client.pem: client.p12 
        openssl pkcs12 -in client.p12 -out client.pem -passin pass:$(PASSWORD_CLIENT) -passout pass:$(
PASSWORD_CLIENT) 
        cp client.pem $(USER_NAME).pem 
 
client_android.p12: client.crt 
        openssl pkcs12 -export -in client.crt -inkey client.key -certfile ca.pem -name "$(USER_NAME)" -out client_android.p12 -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) 
        cp client_android.p12 $(USER_NAME)_android.p12 
 
.PHONY: client.vrfy 
client.vrfy: ca.pem client.pem  
        c_rehash . 
        openssl verify -CApath . client.pem 
 
###################################################################### 
# 
#  Miscellaneous rules. 
# 
###################################################################### 
index.txt: 
        @touch index.txt 
 
serial: 
        @echo '01' > serial 
 
random: 
        @if [ -c /dev/urandom ] ; then \ 
                dd if=/dev/urandom of=./random count=10 >/dev/null 2>&1; \ 
        else \ 
                date > ./random; \ 
        fi 
 
print: 
        openssl x509 -text -in server.crt 
 
printca: 
        openssl x509 -text -in ca.pem 
 
clean: 
        @rm -f *~ *old client.csr client.key client.crt client.p12 client.pem 
 
# 
#       Make a target that people won't run too often. 
# 
destroycerts: 
        rm -f *~ dh *.csr *.crt *.p12 *.der *.pem *.key index.txt* \ 
                        serial* random *\.0 *\.1

注意:インデントはスペースではなくタブを使います

PKCS#12をPEMフォーマットでクライアント用の証明書を発行します。

sudo make client.pem
sudo make client_android.p12

以上で証明書の作成ができたので所有者、パーミッションを変更してサーバーの設定ファイルにインストールします。

sudo chmod 600 *
sudo chmod 640 ca.pem server.pem server.key dh 
sudo chgrp ssl-cert ca.pem server.pem server.key dh
sudo cd /etc/ssl/certs
sudo ln -sf /var/certs/freeradius/ca.pem ca.pem
sudo ln -sf /var/certs/freeradius/server.pem server.pem
sudo c_rehash .
sudo cd /etc/ssl/private
sudo ln -sf /var/certs/freeradius/server.key server.key
sudo cd /etc/freeradius/3.0/certs
sudo ln -sf /var/certs/freeradius/dh
sudo mkdir -p /var/tmp/radiusd
sudo chown freerad:freerad /var/tmp/radiusd
sudo chmod 700 /var/tmp/radiusd

証明書をチェックします。

/usr/bin/openssl verify -CApath /etc/ssl/certs server.pem
server.pem: OK

デバッグモードで起動して無事動いていれば完成です。

sudo freeradius -X

サーバーを自動起動出来るようにします。

sudo systemctl enable freeradius
sudo systemctl start freeradius

UPDATE(18/8/2018): FreeRadius3

Ubuntu 18.04 LTSからFreeRadius3になり設定も大幅に変更になりました。以下、新しい設定です。証明書は/etc/sslに保存するようになりました。

/etc/freeradius/3.0/radiusd.conf:

prefix = /usr
exec_prefix = /usr
sysconfdir = /etc
localstatedir = /var
sbindir = ${exec_prefix}/sbin
logdir = /var/log/freeradius
raddbdir = /etc/freeradius/3.0
radacctdir = ${logdir}/radacct
name = freeradius
confdir = ${raddbdir}
modconfdir = ${confdir}/mods-config
certdir = ${confdir}/certs
cadir   = ${confdir}/certs
run_dir = ${localstatedir}/run/${name}
db_dir = ${raddbdir}
libdir = /usr/lib/freeradius
pidfile = ${run_dir}/${name}.pid
correct_escapes = true
max_request_time = 30
cleanup_delay = 5
max_requests = 16384
hostname_lookups = no

log {
        destination = files
        colourise = yes
        file = ${logdir}/radius.log
        syslog_facility = daemon
        stripped_names = no
        auth = no
        auth_badpass = no
        auth_goodpass = no
        msg_denied = "You are already logged in - access denied"
}

checkrad = ${sbindir}/checkrad

security {
        user = freerad
        group = freerad
        allow_core_dumps = no
        max_attributes = 200
        reject_delay = 1
        status_server = yes
}

proxy_requests  = no
$INCLUDE clients.conf

thread pool {
        start_servers = 5
        max_servers = 32
        min_spare_servers = 3
        max_spare_servers = 10
        max_requests_per_server = 0
        auto_limit_acct = no
}

modules {
        $INCLUDE mods-enabled/
}

instantiate {
        exec
        expr
        expiration
        logintime
}

policy {
        $INCLUDE policy.d/
}

$INCLUDE sites-enabled/

/etc/freeradius/3.0/clients.conf:(例)

client 192.168.1.0/27 { 
        secret    = secret1 
        shortname = localAP 
        require_message_authenticator = yes 
}

/etc/freeradius/3.0/mods-available/eap: OpenSSLで証明書をチェックします。また証明書のパスが変更になっています。

eap {
        default_eap_type = tls
        timer_expire     = 60
        ignore_unknown_eap_types = no
        cisco_accounting_username_bug = no
        max_sessions = ${max_requests}

        tls-config tls-common {
                private_key_password = whatever
                private_key_file = /etc/ssl/private/server.key
                certificate_file = /etc/ssl/certs/server.pem
                ca_file = /etc/ssl/certs/ca.pem
                dh_file = ${certdir}/dh
                ca_path = ${cadir}
                cipher_list = "HIGH"
                cipher_server_preference = no
                ecdh_curve = "prime256v1"

                cache {
                        enable = no
                }

                verify {
                        tmpdir = /var/tmp/radiusd
                        client = "/usr/bin/openssl verify -CApath /etc/ssl/certs %{TLS-Client-Cert-Filename}"
                }

                ocsp {
                        enable = no
                        override_cert_url = yes
                        url = "http://127.0.0.1/ocsp/"
                }
        }

        tls {
                tls = tls-common

        }

/etc/freeradius/3.0/sites-enabled/my_ap:

server default {

listen {
        type = auth
        ipaddr = *
        ipv6addr = ::
        port = 0
}

authorize { 
        preprocess 
        eap { 
                ok = return 
        } 
        expiration 
        logintime 
} 
authenticate { 
        eap 
} 
preacct { 
        preprocess 
        acct_unique 
        suffix 
} 
session { 
        radutmp 
} 
post-auth { 
        exec 
        Post-Auth-Type REJECT { 
                attr_filter.access_reject 
        } 
} 
pre-proxy { 
} 
post-proxy { 
        eap 
}
}

 

>>FreeRadiusとOpenWrtを使ったWPA Enterprise (EAP-TLS)の設定 (2)

References: