FreeRADIUS и корпоративный WiFi

Материал из ALT Linux Wiki

Введение

Данная статья не претендует на "единственное правильное решение". Я искал решение, применимое к максимальному количеству сочетаний WiFi-оборудования и операционных систем клиентов, достаточно хорошее с точки зрения безопасности.


При разворачивании/оптимизации существующей WiFi-сети непременно встает вопрос "а какой вариант авторизации выбрать PSK (общий пароль сети) или Enterprise (персональная авторизация каждого клиента)"?

Вариант PSK прост в настройке и достаточно удобен при небольшом количестве клиентов сети: в случае компрометации, пароль легко меняется и сообщается всем легитимным клиентам.

Но что если клиентов пара сотен, а точек доступа десяток-другой, да еще они расположены в разных офисах? Из-за утраты пароля одним клиентом, ощутимые неудобства получат все остальные клиенты, плюс обновить настройку десятков устройств (и никого не пропустить!) - дело хлопотное.

В таком случае разумно выбрать вариант Enterprise. При компрометации учетных данных какого-либо клиента, достаточно поменять/заблокировать данные только этого клиента, никак не беспокоя остальных.

Enterprise

Реализация Enterprise в оборудовании WiFi представлена протоколами EAP: EAP-MD5, EAP-LEAP, EAP-PEAP, EAP-GTC, EAP-TLS, EAP-TTLS. Описание легко гуглится. На мой взгляд наилучшим "общим знаменателем" по критериям "безопасность", "поддержка оборудованием доступа", "поддержка клиентским ПО в различных ОС" являются протоколы EAP-PEAP и EAP-TLS. С оговоркой (Windows "из коробки" его не поддерживает) можно добавить EAP-TTLS.

EAP-TLS - авторизация по сертификату.

EAP-PEAP, EAP-TTLS - авторизация по логину/паролю.

EAP-TLS

предполагает использование инфраструктуры управления сертификатами: CA, OCSP и вот это вот все. Плюс могут встретиться небольшие затруднения при настройке клиентского ПО (супликанта). Но в целом, это отличный выбор.

EAP-PEAP

Протокол EAP-PEAP создает безопасный TLS-туннель до сервера авторизации (т.е. метод защищен от прослушивания) и уже внутри него пара логин/пароль передается по протоколу MS-CHAPv2.

EAP-TTLS

Протокол EAP-TTLS так же создает безопасный TLS-туннель до сервера авторизации, но внутри может передавать помимо MS-CHAP еще и "менее защищенные" PAP и CHAP.

FreeRADIUS

В качестве сервера авторизации я выбрал FreeRADIUS.

Пакеты freeradius и freeradius-utils:

apt-get install freeradius freeradius-utils

Конфигурация по умолчанию настроена для максимальной универсальности, поддерживает несколько методов авторизации, в том числе и небезопасные (PAP, CHAP, и т.д.). Я предпочел сконфигурировать сервер с поддержкой только "безопасных" EAP-TLS, EAP-PEAP и EAP-TTLS.

Конфигурация Site

Прежде всего убираю sites по-умолчанию

rm -f /etc/raddb/sites-enabled/*

Затем создаю свой site-файл

# cat /etc/raddb/sites-available/site-eap-custom
server eap-phase1 {
        listen {
                type = auth
                ipaddr = *
                port = 0
                limit {
                      max_connections = 16
                      lifetime = 0
                      idle_timeout = 30
                }
        }

        listen {
                ipaddr = *
                port = 0
                type = acct
                limit {
                }
        }

        authorize {
                permit_only_eap
                filter_username
                preprocess
                suffix
                eap {
                        ok = return
                }
                files
        }

        authenticate {
                Auth-Type MS-CHAP {
                        mschap
                }
                eap
        }
}

server eap-phase2 {

        listen {
                ipaddr = 127.0.0.1
                port = 18120
                type = auth
        }

        authorize {
                mschap
                update control {
                        &Proxy-To-Realm := LOCAL
                }
                eap {
                        ok = return
                }
                files
                -ldap
                expiration
                logintime
                pap
        }

        authenticate {
                Auth-Type MS-CHAP {
                        mschap
                }
                Auth-Type PAP {
                        pap
                }
                eap
        }

        session {
                radutmp
        }

        post-auth {
                Post-Auth-Type REJECT {
                        attr_filter.access_reject
                        update outer.session-state {
                                &Module-Failure-Message := &request:Module-Failure-Message
                        }
                }
        }

        pre-proxy {
        }

        post-proxy {
                eap
        }
}

И включаю конфигурацию

ln -s /etc/raddb/sites-available/site-eap-custom /etc/raddb/sites-enabled/

Обращаю внимание, в файле описаны два сервера.

  • eap-phase1 реализует EAP-TLS и внешний TLS-туннель для EAP-PEAP и EAP-TTLS. Причем применена политика permit_only_eap, прекращающая процесс авторизации если клиент пытается авторизоваться не EAP-* методом.
  • eap-phase2 реализует MS-CHAPv2, PAP внутри TLS-тунеля и опциональную поддержку LDAP при необходимости (об этом дальше).

Модуль EAP

Для того, чтобы мой site мог работать необходимо настроить модуль eap.

Создаю свой module-файл

# cat /etc/raddb/mods-available/mod-eap-custom
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_password = whatever
                private_key_file = ${certdir}/server.pem
                certificate_file = ${certdir}/server.pem
                ca_file = ${cadir}/ca.pem
                #  OpenSSL will automatically create certificate chains,
                #  unless we tell it to not do that.  The problem is that
                #  it sometimes gets the chains right from a certificate
                #  signature view, but wrong from the clients view.
                dh_file = ${certdir}/dh
                ca_path = ${cadir}
                cipher_list = "DEFAULT"
                cipher_server_preference = no
                disable_tlsv1_1 = yes
                disable_tlsv1 = yes
                tls_min_version = "1.2"
                tls_max_version = "1.2"
                ecdh_curve = "prime256v1"
                cache {
                        enable = no
                        lifetime = 24 # hours
                        store {
                                Tunnel-Private-Group-Id
                        }
                }
                verify {
                }
                ocsp {
                        enable = no
                        override_cert_url = yes
                        url = "http://127.0.0.1/ocsp/"
                }
        }
        tls {
                tls = tls-common
        }
        ttls {
                tls = tls-common
                default_eap_type = pap
                copy_request_to_tunnel = no
                use_tunneled_reply = no
                virtual_server = "eap-phase2"
        }
        peap {
                tls = tls-common
                default_eap_type = mschapv2
                copy_request_to_tunnel = no
                use_tunneled_reply = no
                virtual_server = "eap-phase2"
        }
        mschapv2 {
        }
}

От оригинального файла модуля, приведенный отличается другим значением virtual_server в секции peap и ttls, и отключением "лишних" методов (md5, leap, gtc).

Так же, при использовании своей инфраструктуры управления сертификатами, нужно вдумчиво актуализировать секцию tls-config tls-common.

Теперь можно/нужно отключить "лишние" модули RADIUS

rm -f /etc/raddb/mods-enabled/*
for M in always attr_filter date detail detail.log dynamic_clients mod-eap-custom echo exec expiration expr \
  files linelog logintime mschap pap passwd preprocess radutmp realm replicate sradutmp unpack utf8
do
  ln -s /etc/raddb/mods-available/${M} /etc/raddb/mods-enabled/
done

client.conf (оборудование WiFi)

Пришло время описать каким устройствам разрешено общаться с RADIUS-сервером.

В файле /etc/raddb/clients.conf можно описывать как каждого клиента непосредственно, так и сразу группу.

# cat /etc/raddb/clients.conf
client wifiAPs {
        ipaddr = 192.168.0.0/16
        secret = APs_pass1
        require_message_authenticator = no
}

Формат хранения паролей

Модуль MS-CHAPv2 принимает от пользователя NT-Hash (он же MD4) и либо сравнивает его с NT-Hash из источника данных авторизации (далее "хранилище"), либо "просит" вычислить MD4-хэш модуль PAP, которому в хранилище необходим Cleartext-Password. Отсюда выбор метода EAP-PEAP допускает только два варианта хранения паролей: Cleartext-Password и NT-Password. MD4 считается недостаточно безопасным.

Модуль PAP принимает от пользователя Cleartext-Password, при необходимости вычисляет хэш (md4, md5, sha1, sha256, solted sha1,и т.д.) и сравнивает с содержимым в хранилище. Отсюда выбор метода EAP-TTLS позволяет хранить стойкие к коллизиям хэши паролей, но за это требует доверия к администратору RADIUS-сервера.

Источники данных для авторизации

FreeRADIUS умеет работать со многими источниками данным авторизации (например с /etc/passwd), но с точки зрения масштабируемости и удобства автоматизации наиболее подходящими представляются собственный файл RADIUS (/etc/raddb/users) и LDAP-каталог (OpenLDAP, Active Directory, SAMBA, IPA).

Файл users

Самый простой способ хранения данных авторизации. Файл легко обновлять и реплицировать на другие RADIUS-серверы.

С учетом вышеописанных ограничений, файл может иметь вид:

# cat /etc/raddb/users
# EAP-PEAP, MS-CHAPv2
user1 Cleartext-Password := "pass123"
user2 NT-Password := "5FBC3D5FEC8206A30F4B6C473D68AE76"
user3 Password-With-Header := "{clear}pass123"
user4 Password-With-Header := "{nt}5FBC3D5FEC8206A30F4B6C473D68AE76"
# EAP-TTLS, PAP
user5 SHA1-Password := "aafdc23870ecbcd3d557b6423a8982134e17927e"
user6 Password-With-Header := "{sha1}aafdc23870ecbcd3d557b6423a8982134e17927e"

LDAP

Если в сети уже есть LDAP-сервер или Вы "умеете его готовить" представляется разумным воспользоваться его ресурсами.

Для этого необходимо добавить пакет freeradius-ldap

apt-get install freeradius-ldap

скопировать файл модуля ldap

cp /etc/raddb/mods-available/ldap /etc/raddb/mods-available/mod-ldap-custom

внети в новый файл: сервер, учетные данные пользователя, который обладает правами читать необходимые атрибуты и метод доступа к LDAP

# cat /etc/raddb/mods-available/mod-ldap-custom
 # ...[skipped]...
ldap {
        server = 'ldap://dc.mydomain.ru'
        base_dn = 'cn=accounts,dc=mydomain,dc=ru'
        identity = 'cn=RadiusDaemon'
        password = radpass1
        sasl {
                realm = 'MYDOMAIN.RU'
        }
 # ...[skipped]...

отключить "родной" модуль ldap и включить новый

rm -f /etc/raddb/mods-enabled/ldap
ln -s /etc/raddb/mods-available/mod-ldap-custom /etc/raddb/mods-enabled/

Получилась конфигурация, аналогичная большинству статей про "WiFi+RADIUS+LDAP".

Однако во всех, встреченных мной, статьях такого рода, есть существенный изъян: в них предполагается, что клиент WiFi авторизуется в сети доменной учетной записью. Для конечного клиента сети это безусловно удобно.

Но при компрометации пароля и несвоевременном обнаружении этого факта, злоумышленик получит доступ не только к самой сети, но и к ресурсам этой сети (северам, рабочим станциям, принтерам и т.д.), к которым имеет доступ легитимный клиент.


А можно ли как-то отделить авторизацию в сети от авторизации в домене? Да, и как оказалось легко.

Нужно выбрать или создать поле типа строка (в примере ниже это wifipass), и поправить два файла:

# cat /etc/raddb/mods-available/mod-ldap-custom
 # ...[skipped]...
update {
                control:Password-With-Header    += 'wifipass'
 # ...[skipped]...
# cat /etc/raddb/mods-config/ldap/ldap.attrmap
 # ...[skipped]...
checkitem       Password-With-Header            wifipass
 # ...[skipped]...

Последний штрих

Осталось найти и "разобраться" по своему усмотрению со стандартными паролями (поменять, закомментировать секцию, и.т.п)

grep -R testing123 /etc/raddb/*

и RADIUS-сервер в первом приближении готов.