FreeRADIUS EAP-TLS, works but and "Check Client Certificate CN" doesn't
-
So I have WPA2/Enterprise with EAP-TLS working on Windows and Android with Unifi APs against FreeRADIUS on pfsense+.
BUT, there is an EAP-TLS sessing in Services -> FreeRADIUS -> EAP -> EAP-TLS called "Check Client Certificate CN". The description says "When enabled, the Common Name of the client certificate must match the username set in 'FreeRADIUS > Users'."
Can't get this setting to work. I can make a user with username "foo" and a cert with common name "foo" and everything works great. Problem is that I can change the "foo" user's FreeRADIUS username to "bob" and it still works. On Windows and Android WiFi clients, you have to specify an "identity" (username) but it seems to be ignored by FreeRADIUS.
SO, it looks like that when EAP-TLS is in use that the FreeRADIUS users don't really matter. I CAN revoke the certificate (and then bounce FreeRADIUS) and the user can't login.
In addition, there doesn't seem to be a way to turn off other EAP auth methods like EAP-TTLS, so IF there is a user defined in FreeRADIUS and I revoke their cert so they can't use EAP-TLS, they can switch to EAP-TTLS (no client cert) as long as they know the password for the user.
Am I not getting something?
BTW, here's some things I had to do to get it working.
- Use a publicly trusted SSL server cert for FreeRADIUS. I used a Let's Encrypt cert via the pfsense acme package (which was awesome)
- Issue all your certs off your root CA. Don't use an intermediate CA. Everything works with the intermediate except CRL checking.
- On Windows, define your WiFi connection in Control Panel -> Network & Sharing Center -> Setup New Connection. You dont have the options you need in the half-baked modern GUI.
- On Android, you have to type in a "domain". This is the FQDN of the publicly trusted FreeRADIUS SSL server cert.
- EAP-TLS and EAP-TTLS/MS-CHAP-V2 both work. EAP-TTLS uses the FreeRADIUS username/password. EAP-TLS just uses the client cert (but you have to specify an "identity" (username) in both Windows and Android, but, as I mention above, it seems to be ignored by FreeRADIUS.
-
@Lobanz can you share full documentation on how to configure EAP-TLS and what changes need to be done in Windows to connect wifi
-
@Lobanz said in FreeRADIUS EAP-TLS, works but and "Check Client Certificate CN" doesn't:
"When enabled, the Common Name of the client certificate must match the username set in 'FreeRADIUS > Users'."
Hmmm, I do believe this use to work.. But yeah seems I am able to duplicate the issue. I have that checked.
I even completely deleted the freerad user, and still auths just fine..
-
Below is my configuration for EAP-tls but I am unable to connect to wifi for windows
radiusd.confprefix = /usr/local
exec_prefix = ${prefix}
sysconfdir = ${prefix}/etc
localstatedir = /var
sbindir = ${exec_prefix}/sbin
logdir = ${localstatedir}/log
raddbdir = ${sysconfdir}/raddb
radacctdir = ${logdir}/radacct
name = radiusd
confdir = ${raddbdir}
modconfdir = ${confdir}/mods-config
certdir = ${confdir}/certs
cadir = ${confdir}/certs
run_dir = ${localstatedir}/run
db_dir = ${raddbdir}
libdir = /usr/local/lib/freeradius-3.2.3
pidfile = ${run_dir}/${name}.pid
max_request_time = 30
cleanup_delay = 5
max_requests = 1024
hostname_lookups = no
regular_expressions = yes
extended_expressions = yeslog {
destination = files
colourise = yes
file = ${logdir}/radius.log
syslog_facility = daemon
stripped_names = yes
auth = yes
auth_badpass = yes
auth_goodpass = yes
msg_goodpass = ""
msg_badpass = ""
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 = no
# Disable this check since it may not be accurate due to how FreeBSD patches OpenSSL
allow_vulnerable_openssl = yes
}$INCLUDE clients.conf
thread pool {
start_servers = 5
max_servers = 32
min_spare_servers = 3
max_spare_servers = 10
max_queue_size = 65536
max_requests_per_server = 0
auto_limit_acct = no
}modules {
$INCLUDE ${confdir}/mods-enabled/
}instantiate {
exec
expr
expiration
logintime
### Dis-/Enable sql instatiate
#sql
daily
weekly
monthly
forever
}
policy {
$INCLUDE policy.d/
}
$INCLUDE sites-enabled/
EAP
EAP
eap {
default_eap_type = tls
timer_expire = 60
ignore_unknown_eap_types = no
cisco_accounting_username_bug = no
max_sessions = 4096DISABLED WEAK EAP TYPES MD5, GTC
pwd {
group = 19
server_id = theserver@example.com
fragment_size = 1020
virtual_server = "inner-tunnel"
}
tls-config tls-common { # private_key_password = whatever private_key_file = ${certdir}/server_key.pem certificate_file = ${certdir}/server_cert.pem ca_path = ${confdir}/certs ca_file = ${ca_path}/ca_cert.pem # auto_chain = yes # psk_identity = "test" # psk_hexphrase = "036363823" dh_file = ${certdir}/dh random_file = /dev/urandom fragment_size = 1024 include_length = yes check_crl = no ### check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd/emailAddress=test@mycomp.com/CN=myca" ### ### check_cert_cn = %{User-Name} ### cipher_list = "DEFAULT" cipher_server_preference = no
disable_tlsv1_2 = no
ecdh_curve = "prime256v1" tls_min_version = "1.2" cache { enable = no lifetime = 24 max_entries = 255 #name = "EAP module" #persist_dir = "/tlscache" } verify { # skip_if_ocsp_ok = no # tmpdir = /tmp/radiusd # client = "/path/to/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" } ocsp { enable = no override_cert_url = no url = "http://127.0.0.1/ocsp/" # use_nonce = yes # timeout = 0 # softfail = no } } tls { tls = tls-common # virtual_server = check-eap-tls } ttls { tls = tls-common default_eap_type = md5 copy_request_to_tunnel = no include_length = yes # require_client_cert = yes virtual_server = "inner-tunnel-ttls" #use_tunneled_reply is deprecated, new method happens in virtual-server } ### end ttls peap { tls = tls-common default_eap_type = mschapv2 copy_request_to_tunnel = no # proxy_tunneled_request_as_eap = yes # require_client_cert = yes
MS SoH Server is disabled
virtual_server = "inner-tunnel-peap" #use_tunneled_reply is deprecated, new method happens in virtual-server } mschapv2 {
send_error = no
identity = "FreeRADIUS"
}
fast {
tls = tls-common
pac_lifetime = 604800
authority_identity = "1234"
pac_opaque_key = "0123456789abcdef0123456789ABCDEF"
virtual_server = inner-tunnel
}
}
/usr/local/etc/raddb/clients.conf
client "wifi" {
ipaddr = 192.168.0.1
proto = udp
secret = '123456789'
require_message_authenticator = no
nas_type = other
### login = !root ###
### password = someadminpass ###
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
default
server default {
listen {
type = auth
ipaddr = *
port = 1812
}authorize {
filter_username
filter_password
preprocess
operator-name
cui
AUTHORIZE FOR PLAIN MAC-AUTH IS DISABLED
auth_log
chap mschap digest
wimax
IPASS
suffix ntdomain eap { ok = return
updated = return
}
unix
files if ((notfound || noop) && ("%{%{Control:Auth-Type}:-No-Accept}" != "Accept")) { ### sql DISABLED ### if (true) { ### ldap ### if (notfound || noop) { reject } } } -daily -weekly -monthly -forever # Formerly checkval if (&request:Calling-Station-Id == &control:Calling-Station-Id) { ok } expiration logintime pap Autz-Type Status-Server { }
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
mschap
Auth-Type MOTP {
motp
}
Auth-Type GOOGLEAUTH {
googleauth
}
digestpam
unix
#Auth-Type LDAP { #ldap #### ldap2 disabled ### #} eap
Auth-Type eap {
eap {
handled = 1
}
if (handled && (Response-Packet-Type == Access-Challenge)) {
attr_filter.access_challenge.post-auth
handled # override the "updated" code from attr_filter
}
}
}
preacct {
preprocessACCOUNTING FOR PLAIN MAC-AUTH DISABLED
acct_counters64
update request { &FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}" }
acct_unique
IPASS
suffix ntdomain files
}
accounting {
cui
detail ### This makes it possible to run the datacounter_acct module only on accounting-stop and interim-updates if ((request:Acct-Status-Type == Stop) || (request:Acct-Status-Type == Interim-Update)) { datacounterdaily datacounterweekly datacountermonthly datacounterforever }
unix
radutmp
sradutmp
main_pool
### sql DISABLED ### daily weekly monthly forever
if (noop) {
ok
}
pgsql-voip
exec attr_filter.accounting_response Acct-Type Status-Server { }
}
session {
radutmp
radutmp
}
post-auth {
if (!&reply:State) {
update reply {
State := "0x%{randstr:16h}"
}
}
update { &reply: += &session-state: }
main_pool
cui
reply_log
sql DISABLED
ldap
exec
wimax
update reply {
Reply-Message += "%{TLS-Cert-Serial}"
Reply-Message += "%{TLS-Cert-Expiration}"
Reply-Message += "%{TLS-Cert-Subject}"
Reply-Message += "%{TLS-Cert-Issuer}"
Reply-Message += "%{TLS-Cert-Common-Name}"
Reply-Message += "%{TLS-Cert-Subject-Alt-Name-Email}"
Reply-Message += "%{TLS-Client-Cert-Serial}"
Reply-Message += "%{TLS-Client-Cert-Expiration}"
Reply-Message += "%{TLS-Client-Cert-Subject}"
Reply-Message += "%{TLS-Client-Cert-Issuer}"
Reply-Message += "%{TLS-Client-Cert-Common-Name}"
Reply-Message += "%{TLS-Client-Cert-Subject-Alt-Name-Email}"
}
insert_acct_class
if (&reply:EAP-Session-Id) {
update reply {
EAP-Key-Name := &reply:EAP-Session-Id
}
}
remove_reply_message_if_eap Post-Auth-Type REJECT { # log failed authentications in SQL, too. # sql attr_filter.access_reject eap remove_reply_message_if_eap } Post-Auth-Type Challenge { }
}
pre-proxy {
operator-name
cui
files
attr_filter.pre-proxy
pre_proxy_log
}
post-proxy {
post_proxy_log
attr_filter.post-proxy eap
Post-Proxy-Type Fail-Accounting {
detail
}
}
}