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に設定を一式入れます。あとはデーモンを起動するだけです。