OpenWrtでWPA2-Enterprise(EAP-PEAP/MSCHAPv2)の構築(NEW)

OpenWRT 18.06.1になって設定が大幅に変わり修正が必要になりますが、性能が大幅に強化されて結果的に良くなりました。以前トラベルルータにWPA2-Enterprise(EAP-PEAP/MSCHAPv2)を構築したのですが、セキュリティの問題が若干残されていました。今回セットアップしたところ不具合は解消されていて、セットアップも滞りなく済みました。

このコンパクトなルータにFreeRadiusを入れてWPA2-Enterpriseを使えるようにしてセキュリティを強化します。コンパクトさゆえにいろいろと制約がありファームウェアをカスタマイズすることから始めます。OpenWrtの標準仕様はwpad-miniでWPA2が使えません。そこでフルバージョンのwpadパッケージをインストールするのですが、squashfsに組み込まれているためwpad-miniを消すことが出来ません。となると限りあるストレージを余計に使ってしまいます。そこでパッケージを最適化してファームウェアを作り直します。

FreeRADIUSのセットアップに必要なパッケージ

まず、FreeRADIUSのパッケージをインストールします。

opkg update
opkg install freeradius3 freeradius3-common freeradius3-democerts freeradius3-mod-always freeradius3-mod-attr-filter freeradius3-mod-chap freeradius3-mod-detail freeradius3-mod-eap freeradius3-mod-eap-mschapv2 freeradius3-mod-pap freeradius3-mod-eap-peap freeradius3-mod-eap-tls freeradius3-mod-exec freeradius3-mod-expiration freeradius3-mod-expr freeradius3-mod-files freeradius3-mod-digest freeradius3-mod-logintime freeradius3-mod-unix
opkg install freeradius3-mod-mschap freeradius3-mod-passwd freeradius3-mod-preprocess freeradius3-mod-radutmp freeradius3-mod-realm freeradius3-utils

(※注:13 FEB 2019)現在、一部パッケージが欠損しているので旧バージョンからlibtalloc_2.1.7-2_mipsel_24kc.ipkをインストールします。

次にopensslコマンドを使えるようにパッケージをインストールします。またWPAエンタープライズを使用するにはwpadが必要です。

opkg install openssl-util libopenssl
opkg remove wpad-mini
opkg install wpad

秘密鍵と証明書のインストール

opensslの使い方は過去の記事にいくつか書きましたが、今回は検索したサイトを参考に作成してみました。

openssl ecparam -out ecca.param -name secp384r1
openssl req -nodes -newkey ec:ecca.param -days 3650 -x509 -sha256 -keyout ecca.key -out ecca.crt
openssl req -nodes -newkey ec:ecca.crt -days 3650 -sha256 -keyout serverec.key -out serverec.csr

mkdir ./demoCA/
mkdir ./demoCA/newcerts
touch ./demoCA/index.txt
echo 01 > ./demoCA/serial

openssl ca -extensions v3_ca -days 3650 -out serverec.crt -in serverec.csr -cert ecca.crt -keyfile ecca.key
cat serverec.crt serverec.key > serverec.pem
openssl dhparam -out dhparam.pem 2048
cp ecca.crt serverec.pem dhparam.pem /etc/freeradius3/certs

秘密鍵と証明書をインストールしたら証明書のテストをしてみます。

openssl x509 -in serverec.crt -text
openssl verify -CAfile ecca.crt serverec.pem

Freeradiusの設定

/etc/freeradius3/mods-available/eap

eap {
        default_eap_type = peap
        timer_expire     = 60
        ignore_unknown_eap_types = no
        cisco_accounting_username_bug = no
        max_sessions = ${max_requests}
        tls-config tls-common {
                private_key_file = ${certdir}/serverec.pem
                certificate_file = ${certdir}/serverec.pem
                ca_file = ${cadir}/ecca.crt
                dh_file = ${certdir}/dhparam.pem
                ca_path = ${cadir}
                cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA256:ECDHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;"
                ecdh_curve = "secp384r1"
                cache {
                        enable = no
                        max_entries = 255
                }
                verify {
                        tmpdir = /tmp/run
                        client = "/usr/bin/openssl verify -CAfile $ca_file %{TLS-Client-Cert-Filename}"
                }
                ocsp {
                        enable = no
                        override_cert_url = yes
                        url = "http://127.0.0.1/ocsp/"
                }
        }
        peap {
                tls = tls-common
                default_eap_type = mschapv2
                copy_request_to_tunnel = yes
                use_tunneled_reply = yes
                virtual_server = "inner-tunnel"
        }
        mschapv2 {
                send_error = no
        }
}

/etc/freeradius3/mods-available/mschap

mschap {
        use_mppe = yes
        require_encryption = yes
        require_strong = yes
}

/etc/freeradius3/clients.conf

client localhost {
        ipaddr = 127.0.0.1
        proto = *
        secret = testing123
        require_message_authenticator = yes
        shortname = localhost
}

/etc/freeradius3/proxy.conf

proxy server {
        default_fallback = no
}
home_server localhost {
        type = auth
        ipaddr = 127.0.0.1
        port = 1812
        secret = testing123
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        check_timeout = 4
        num_answers_to_alive = 3
        max_outstanding = 65536
        coa {
                irt = 2
                mrt = 16
                mrc = 5
                mrd = 30
        }
        limit {
              max_connections = 16
              max_requests = 0
              lifetime = 0
              idle_timeout = 0
        }
}
home_server_pool my_auth_failover {
        type = fail-over
        home_server = localhost
}
realm example.com {
        auth_pool = my_auth_failover
}
realm LOCAL {
}

/etc/freeradius3/radiusd.conf

prefix = /usr
exec_prefix = /usr
sysconfdir = /etc
localstatedir = /var
sbindir = /usr/sbin
logdir = /var/log
raddbdir = /etc/freeradius3
radacctdir = /var/db/radacct
name = radiusd
confdir = ${raddbdir}
modconfdir = ${confdir}/mods-config
certdir = ${confdir}/certs
cadir   = ${confdir}/certs
run_dir = ${localstatedir}/run/${name}
db_dir = ${raddbdir}
libdir = /usr/lib/freeradius3
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 {
        allow_core_dumps = no
        max_attributes = 200
        reject_delay = 1
        status_server = yes
}
proxy_requests  = yes
$INCLUDE proxy.conf
$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 {
}
policy {
        $INCLUDE policy.d/
}
$INCLUDE sites-enabled/

/etc/freeradius3/mods-config/files/authorize (users -> mods-config/files/authorize)

"testuser" Cleartext-Password := "pass123"

/etc/freeradius3/sites-available/default

server default {
authorize {
        preprocess
        mschap
        suffix
        eap {
                ok = return
        }
        expiration
        logintime
}
authenticate {
        Auth-Type MS-CHAP {
                mschap
        }
        eap
}
preacct {
        preprocess
        acct_unique
        suffix
        files
}
accounting {
        attr_filter.accounting_response
}
session {
        radutmp
}
pre-proxy {
}
post-proxy {
        eap
}
}

/etc/freeradius3/sites-available/inner-tunnel

server inner-tunnel {
listen {
       ipaddr = 127.0.0.1
       port = 18120
       type = auth
}
authorize {
        mschap
        suffix
        update control {
                &Proxy-To-Realm := LOCAL
        }
        eap {
                ok = return
        }
        files
        expiration
        logintime
}
authenticate {
        Auth-Type MS-CHAP {
                mschap
        }
        eap
}
session {
        radutmp
}
pre-proxy {
}
post-proxy {
        eap
}
} # inner-tunnel server block

LD_LIBRARY_PATH=/usr/lib/freeradius3 radiusd -Xでテストしてみます。

OpenWrtの設定

/etc/config/wireless

config wifi-iface
        option device 'radio0'
        option mode 'ap'
        option ssid 'OpenWrt'
        option network 'lan'
        option encryption 'wpa2+ccmp'
        option auth_server '127.0.0.1'
        option auth_secret 'testing123'
        #option acct_server '127.0.0.1'
        #option acct_secret 'testing123'
        option auth_port '18120'

ネットワークを再起動してアクセスします。

この設定例でアクセスするユーザー/パスワードはtestuser/pass123です。CAがなくても動きますが違うCAを割り当てるとエラーになります。

(7) Received Access-Request Id 174 from 127.0.0.1:35223 to 127.0.0.1:1812 length 215
(7)   User-Name = "testuser"
(7)   Called-Station-Id = "AA-BB-CC-DD-EE-88:OpenWrt"
(7)   NAS-Port-Type = Wireless-802.11
(7)   Service-Type = Framed-User
(7)   NAS-Port = 1
(7)   Calling-Station-Id = "AA-BB-CC-DD-EE-BD"
(7)   Connect-Info = "CONNECT 54Mbps 802.11g"
(7)   Acct-Session-Id = "DF7CBB543A644BB1"
(7)   Attr-186 = 0x000fac04
(7)   Attr-187 = 0x000fac04
(7)   Attr-188 = 0x000fac01
(7)   Framed-MTU = 1400
(7)   EAP-Message = 0x0219001119800000000715030300020230
(7)   State = 0xac4603eaae5f1a4f6f28de953f47432f
(7)   Message-Authenticator = 0x658b7dd98aa402d4019b914b4fe15e74
(7) session-state: No cached attributes
(7) # Executing section authorize from file /etc/freeradius3/sites-enabled/inner-tunnel
(7)   authorize {
(7)     [chap] = noop
(7)     [mschap] = noop
(7) suffix: Checking for suffix after "@"
(7) suffix: No '@' in User-Name = "testuser", looking up realm NULL
(7) suffix: No such realm "NULL"
(7)     [suffix] = noop
(7)     update control {
(7)       &Proxy-To-Realm := LOCAL
(7)     } # update control = noop
(7) eap: Peer sent EAP Response (code 2) ID 25 length 17
(7) eap: Continuing tunnel setup
(7)     [eap] = ok
(7)   } # authorize = ok
(7) Found Auth-Type = eap
(7) # Executing group from file /etc/freeradius3/sites-enabled/inner-tunnel
(7)   authenticate {
(7) eap: Expiring EAP session with state 0xac4603eaae5f1a4f
(7) eap: Finished EAP session with state 0xac4603eaae5f1a4f
(7) eap: Previous EAP request found for state 0xac4603eaae5f1a4f, released from the list
(7) eap: Peer sent packet with method EAP PEAP (25)
(7) eap: Calling submodule eap_peap to process data
(7) eap_peap: Continuing EAP-TLS
(7) eap_peap: Peer indicated complete TLS record size will be 7 bytes
(7) eap_peap: Got complete TLS record (7 bytes)
(7) eap_peap: [eaptls verify] = length included
(7) eap_peap: <<< recv TLS 1.2  [length 0002] 
(7) eap_peap: ERROR: TLS Alert read:fatal:unknown CA
(7) eap_peap: ERROR: TLS_accept: Failed in unknown state
(7) eap_peap: ERROR: SSL says: error:14094418:lib(20):func(148):reason(1048)
(7) eap_peap: ERROR: SSL_read failed inside of TLS (-1), TLS session failed
(7) eap_peap: ERROR: TLS receive handshake failed during operation
(7) eap_peap: ERROR: [eaptls process] = fail
(7) eap: ERROR: Failed continuing EAP PEAP (25) session.  EAP sub-module failed
(7) eap: Sending EAP Failure (code 4) ID 25 length 4
(7) eap: Failed in EAP select
(7)     [eap] = invalid
(7)   } # authenticate = invalid
(7) Failed to authenticate the user
(7) Using Post-Auth-Type Reject
(7) Post-Auth-Type sub-section not found.  Ignoring.
(7) Delaying response for 1.000000 seconds

エキストラ:

openvpnのインストール

opkg install openvpn-mbedtls

ダッシュボードのopenvpnの設定はバグがあって使えないので/etc/openvpnに設定を一式入れます。あとはデーモンを起動するだけです。

参考: