Защита беспроводных сетей, WPA: теория и практика (часть шестая)

 

В предпоследней статье речь шла о настройке WPA в доменных сетях Windows. Последняя статья этой серии будет посвящена работе со списком отзывов сертификатов.

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

 

Нижеследующие компоненты будут необходимы для работы:

  • беспроводной клиент — в данном случае использовался ноутбук Toshiba Satellite M40-101 со встроенной беспроводной картой Intel PRO/Wireless 2200BG с установленной операционной системой Windows XP pro + SP2
  • точка доступа с поддержкой WPA — ей являлась Gigabyte GN BR404W
  • RADIUS-сервер — был использован FreeRadius сервер версии 1.1.1, работающий под операционной системой Gentoo Linux.
  • OpenSSL (был использован пакет openssl-0.9.7j)

Использование персональных цифровых сертификатов для аутентификации пользователей — замечательная идея. Один раз создали, выдали пользователю, и он использует его вместо логина и пароля (а точнее, это делает операционная система, "прозрачно" для пользователя). Не нужно помнить пароли и так далее.

Но что делать, если вдруг человек, на персональном ноутбуке которого установлен сертификат, увольняется из компании? Ведь он будет иметь возможность подключаться к беспроводной сети, по крайней мере, до тех пор, пока не истечет срок действия сертификата… а ведь это серьезная дыра в безопасности нашей сети…

Для блокировки таких пользователей (а точнее, их сертификатов) применяется процедура "отзыва сертификата". А точнее, нужный сертификат помечается, как отозванный, после чего создается список всех отозванных сертификатов (под названием CRL — Certificate Revocation List). Этот список распространяется (подключается) ко всем серверам, которые производят аутентификацию пользователей с использованием сертификатов. В нашем случае этим сервером является Radius.

Давайте разберем эту процедуру подробнее.

1. Создание нового пользовательского сертификата.

Для начала создадим новый пользовательский сертификат для пользователя test_user9: ===================================================== $ ./sign_cert.sh client_cert test_user9 create certificate key: test_user9.key Generating RSA private key, 2048 bit long modulus …+++ …………………………………………+++ e is 65537 (0x10001) Enter pass phrase for test_user9.key: Verifying — Enter pass phrase for test_user9.key: # # вводим пасс-фразу, которой будет закрыт ключ сертификата пользователя# create certificate request: test_user9.csr Enter pass phrase for test_user9.key: # # опять вводим пассфразу # You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, vega 111 # ./sign_cert.sh client_cert test_user9 ----- 1. Country Name (2 letter code) [RU]: 2. State or Province Name (full name) [Euro]: 3. Locality Name (eg, city) [Moscow]: 4. Organization Name (eg, company) [TempOrg]: 5. Organizational Unit Name (eg, section) [network IT]: 6. Common Name (eg, CA name) [test_user9]: 7. Email Address (eg, name@FQDN) [email@tmp_org.ru]: # # тут вводим данные для заполнения необходимых полей сертификата # (если скрипт sign_cert.sh был настроен, то в данном диалоге # достаточно будет просто жать клавишу Enter) # sign certificate by CA: test_user9.crt (sign ca is: tmp_org-ca) CA signing: test_user9.csr -> test_user9.crt: Using configuration from ca.config Enter pass phrase for ./../tmp_org-ca.key: # # здесь надо ввести парольную фразу, которой был закрыт # приватный ключ корневого сертификата нашего CA # DEBUG[load_index]: unique_subject = "no" Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'RU' stateOrProvinceName :PRINTABLE:'Euro' localityName :PRINTABLE:'Moscow' organizationName :PRINTABLE:'TempOrg' organizationalUnitName:PRINTABLE:'network IT' commonName :T61STRING:'test_user9' emailAddress :IA5STRING:'email@tmp_org.ru' Certificate is to be certified until Aug 30 15:18:21 2008 GMT (730 days) Write out database with 1 new entries Data Base Updated convertign test_user9 certificate to pkcs12 format Enter pass phrase for test_user9.key: # # последний раз вводим пассфразу для клиентского сертификата# Enter Export Password: Verifying — Enter Export Password: # # вводим пароль, который понадобится при импортировании # пользовательского сертификата в Windows-е # CA verifying: test_user9.crt <-> CA cert test_user9.crt: OK =====================================================

Сертификат готов. Переносим его (и корневой сертификат) на клиентскую машину, устанавливаем их, согласно описанному тут и тут алгоритму.

2. Настройка профиля беспроводной сети и точки доступа

Настраиваем профиль беспроводной сети (если это еще не было сделано).

Не забываем настроить точку доступа на работу с WPA совместно с Radius-сервером.

Теперь переходим к самому интересному — настройке Radius-сервера на работу совместно со списком отзыва сертификатов. 

3. Настройка Radius для работы со списком отзыва сертификатов.

3.1 Создание CRL-списка.

Запускаем скрипт (подробнее о нем рассказывалось в третьей части) с параметром "regen_crl" — для создания списка отозванных сертификатов: ./sign_cert.sh regen_crl regen crl Using configuration from ca.config Enter pass phrase for ./../tmp_org-ca.key: # # для генерации списка, необходимо ввести пасс-фразу, которой закрыт # приватный ключ корневого сертификата нашего CA #

В результате отработки, скрипт создаст нам файл "tmp_org-ca.crl", который и содержит список всех отозванных ранее сертификатов (а точнее, файл содержит лишь серийные номера оных). Если сертификаты еще не отзывались, список будет пуст. Если часть сертификатов уже отзывалась, содержимое файла будет, например, таким (так выглядит список отзыва, если щелкнуть мышкой по этому файлу в Windows):

Особенно интересны тут два поля:

  • действителен с — с какого момента список отзыва будет действителен
  • действителен по — после этого числа список отзыва будет недействителен и его необходимо будет обновить (если этого не сделать, то тот же Radius, с включенной проверкой на отозванные сертификаты, заругается на то, что crl-файл не найден и всем клиентам будет отказано в аутентификации)

Дату "действительности" сертификата можно задать в переменной CRL_DAYS, внутри sign_cert.sh скрипта.

На закладке "список отзыва" можно посмотреть серийные номера сертификатов и дату их отзыва.

В нашем случае три сертификата, из ранее созданных, уже были отозваны (с серийными номерами 03, 06, 0а), поэтому они и фигурируют в списке CRL.

В юникс просмотреть созданный список отзыва можно так: #===================================================== # openssl ca -gencrl -out tmp_org-ca.crl #=====================================================

Основная проблема при генерации CRL-списка — пароль корневого сертификата всегда приходится вводить вручную (или прописать жестко в скрипте). То есть либо ручной ввод, либо пароль лежит в открытом виде. Первое — неудобно, второе — небезопасно.

Теперь необходимо подключить CRL к нашему Radius-серверу. Так как в конфигурационном файле Radius отсутствует переменная, хранящая путь именно к CRL-файлу, необходимо добавить содержимое этого файла к корневому сертификату нашего центра CA. Делаем это. 

3.2 Создание файла CRL для Radius.

#===================================================== # cp -f tmp_org-ca.crl /etc/raddb/ssl/ # # копируем CRL-файл в директорию, где располагаются все # сертификаты нашего Radius-сервера # # cd /etc/raddb/ssl # # переходим в эту директорию # # cat tmp_org-ca.crt > tmp_org-ca.crt_with_crl # # копируем содержимое корневого сертификата в файл tmp_org-ca.crt_with_crl # (файл при этом создается заново) # # cat tmp_org-ca.crl >> tmp_org-ca.crt_with_crl # # добавляем к содержимому файла tmp_org-ca.crt_with_crl содержимое CRL-файла # #=====================================================

В результате этих действий у нас получился файл tmp_org-ca.crt_with_crl, который содержит корневой сертификат нашего центра CA и список отзыва сертификатов.  

3.3 Настройка Radius на работу с CRL-списками

Теперь обновим конфигурационный файл для Radius. Открываем

/etc/raddb/eap.conf

и в секции tls{ } раздела eap{ } прописываем #---------------------------------------------------- # # Trusted Root CA list #CA_file = /etc/raddb/ssl/tmp_org/tmp_org-ca.crt # # старое значение переменной CA_file закомментировано # CA_file = /etc/raddb/ssl/tmp_org-ca.crt_with_crl # # обновили путь к CA-файлу # # # Check the Certificate Revocation List # 1) Copy CA certificates and CRLs to same directory. # 2) Execute 'c_rehash '. # 'c_rehash' is OpenSSL's command. # 3) Add 'CA_path=' # to radiusd.conf's tls section. # 4) uncomment the line below. # 5) Restart radiusd check_crl = yes # # добавили (или раскомментировали) переменную check_crl # установили ее в "yes" # #----------------------------------------------------

После перезапуска Radius-а (radiusd -X) сервер готов проверять CRL-списки.

4. Проверка возможности подключения пользователя с валидным сертификатом.

Сначала попробуем подключиться с использованием валидного (неотозванного) сертификата (test_user9):

  #===================================================== rad_recv: Access-Request packet from host 192.168.1.254:2048, id=0, length=182 Message-Authenticator = 0xf4710cf8c7bfa44269baf29799913c4e Service-Type = Framed-User User-Name = "test_user9" Framed-MTU = 1488 Called-Station-Id = "00-20-ED-07-7F-0B:GIGABYTE" Calling-Station-Id = "00-0E-35-EE-67-0F" NAS-Port-Type = Wireless-802.11 Connect-Info = "CONNECT 54Mbps 802.11g" EAP-Message = 0x0200000f01746573745f7573657239 NAS-IP-Address = 192.168.1.254 NAS-Port = 1 NAS-Port-Id = "STA port # 1" <.......> rlm_eap_tls: Received EAP-TLS ACK message rlm_eap_tls: ack handshake is finished eaptls_verify returned 3 eaptls_process returned 3 rlm_eap: Freeing handler modcall[authenticate]: module "eap" returns ok for request 13 modcall: leaving group authenticate (returns ok) for request 13 Login OK: [test_user9/] (from client test_ap port 1 cli 00-0E-35-EE-67-0F) Sending Access-Accept of id 6 to 192.168.1.254 port 2048 Framed-IP-Address = 255.255.255.254 Framed-MTU = 576 Service-Type = Framed-User MS-MPPE-Recv-Key = 0xefdb50b0db0cc990710<.......> MS-MPPE-Send-Key = 0x43f35a2b6a83afc716e<.......> EAP-Message = 0x03060004 Message-Authenticator = 0x00000000000000000000000000000000 User-Name = "test_user9" Finished request 13 #=====================================================

Как видно, подключение к беспроводной сети с использованием сертификата test_user9 прошло успешно.

Теперь попробуем отозвать этот сертификат.

5. Отзыв сертификата.

Отзываем сертификат test_user9: #===================================================== ./sign_cert.sh revoke_cert test_user9 revoke certificate test_user9.crt Using configuration from ca.config Enter pass phrase for ./../tmp_org-ca.key: # # необходимо ввести пассфразу на корневой сертификат нашего CA # DEBUG[load_index]: unique_subject = "no" Revoking Certificate 0B. Data Base Updated # # сертификат был отозван и помечен в базе # regen crl # # теперь генерируем CRL-список заново # Using configuration from ca.config Enter pass phrase for ./../tmp_org-ca.key: # # еще раз вводим пассфразу для корневого CA. # #=====================================================

Посмотрим на полученный новый CRL-файл:

Как видно, у него, по сравнению со старым, немного изменилось время, с которого он действителен (с текущего момента — то есть момента создания).

А в списке отзыва появился еще один элемент, с индексом 0b. Это и есть отозванный нами сертификат test_user9:

Посмотрим серийный номер нашего отозванного сертификата:

Все верно, test_user9 имеет серийный номер 0b.

Так как crl-файл был сгенерирован заново, нужно обновить файл, содержащий crl-список и корневой сертификат для Radius-а. То есть действуем аналогично уже написанному.

Не забываем после этого рестартовать Radius.

6. Кратко о формате хранения данных по сертификатам

А база данных по сертификатам у OpenSSL выглядит очень просто — это текстовый файл (в нашем случае — ca.db.index), который содержит следующее: #---------------------------------------------------- V 071209120518Z 01 unknown /C=RU/ ST=Euro/L=Moscow/O=TempOrg/OU=network IT/ CN=radius.tmp_org.ru/emailAddress=email@tmp_org.ru V 071209123124Z 02 unknown /C=RU<.......> R 071209123227Z 051213115133Z 03 unknown /C=RU<.......> V 071209143947Z 04 unknown /C=RU<.......> V 071213113137Z 05 unknown /C=RU<.......> R 071213115005Z 051213120125Z 06 unknown <.......> V 071216103544Z 07 unknown /C=RU<.......> V 080829140940Z 08 unknown /C=RU<.......> V 080829141011Z 09 unknown /C=RU<.......> R 080830151400Z 060831151547Z 0A unknown /C=RU<.......> R 080830151821Z 060831165555Z 0B unknown /C=RU /ST=Euro/L=Moscow/O=TempOrg/OU=network IT /CN=test_user9/emailAddress=email@tmp_org.ru #----------------------------------------------------

В этом файле построчно перечислены все сертификаты с их индексами. В данном случае нас интересует первая буква — R или V. Если "R" — значит, сертификат помечен, как отозванный. Если "V" — значит сертификат валиден. На основе этой информации OpenSSL и создает CRL-список.

7. Попытка подключения с использованием отозванного сертификата.

Попробуем вновь подключиться к беспроводной сети, используя все тот же сертификат test_user9. Но на этот раз сертификат фигурирует в CRL списке. #===================================================== <.......> rad_recv: Access-Request packet from host 192.168.1.254:2051, id=5, length=248 Message-Authenticator = 0xd2825733a3dbe4e316263d0c2e21b2a3 Service-Type = Framed-User User-Name = "test_user9" Framed-MTU = 1488 State = 0xfd12e050711787dd6917fe4de35abef9 Called-Station-Id = "00-20-ED-07-7F-0B:GIGABYTE" Calling-Station-Id = "00-0E-35-EE-67-0F" NAS-Port-Type = Wireless-802.11 Connect-Info = "CONNECT 54Mbps 802.11g" EAP-Message = 0x0205003f0d0030a8fbf<.......> NAS-IP-Address = 192.168.1.254 NAS-Port = 1 NAS-Port-Id = "STA port # 1" Processing the authorize section of radiusd.conf modcall: entering group authorize for request 5 modcall[authorize]: module "preprocess" returns ok for request 5 modcall[authorize]: module "chap" returns noop for request 5 modcall[authorize]: module "mschap" returns noop for request 5 rlm_realm: No '@' in User-Name = "test_user9", looking up realm NULL rlm_realm: No such realm "NULL" modcall[authorize]: module "suffix" returns noop for request 5 rlm_eap: EAP packet type response id 5 length 63 rlm_eap: No EAP Start, assuming it's an on-going EAP conversation modcall[authorize]: module "eap" returns updated for request 5 users: Matched entry DEFAULT at line 152 users: Matched entry DEFAULT at line 171 modcall[authorize]: module "files" returns ok for request 5 modcall: leaving group authorize (returns updated) for request 5 rad_check_password: Found Auth-Type EAP auth: type "EAP" Processing the authenticate section of radiusd.conf modcall: entering group authenticate for request 5 rlm_eap: Request found, released from the list # # переходим к проверке клиентского сертификата # rlm_eap: EAP/tls rlm_eap: processing type tls rlm_eap_tls: Authenticate rlm_eap_tls: processing TLS eaptls_verify returned 7 rlm_eap_tls: Done initial handshake rlm_eap_tls: <<< TLS 1.0 Handshake [length 03c5], Certificate --> verify error:num=23:certificate revoked rlm_eap_tls: >>> TLS 1.0 Alert [length 0002], fatal certificate_revoked TLS Alert write:fatal:certificate revoked # # ошибка — клиентский сертификат содержится в списке отозванных # TLS_accept:error in SSLv3 read client certificate B 27670:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:2015 : rlm_eap_tls: SSL_read failed in a system call (-1), TLS session fails. In SSL Handshake Phase In SSL Accept mode eaptls_process returned 13 modcall[authenticate]: module "eap" returns handled for request 5 modcall: leaving group authenticate (returns handled) for request 5 Sending Access-Challenge of id 5 to 192.168.1.254 port 2051 Framed-IP-Address = 255.255.255.254 Framed-MTU = 576 Service-Type = Framed-User EAP-Message = 0x010600110d80000000071503010002022c Message-Authenticator = 0x00000000000000000000000000000000 State = 0x49a47117763404fa043e38b3ffc9d750 Finished request 5 Going to the next request Waking up in 5 seconds… rad_recv: Access-Request packet from host 192.168.1.254:2051, id=6, length=191 Message-Authenticator = 0x19bca273353b9936cbd0a07ae47df289 Service-Type = Framed-User User-Name = "test_user9" Framed-MTU = 1488 State = 0x49a47117763404fa043e38b3ffc9d750 Called-Station-Id = "00-20-ED-07-7F-0B:GIGABYTE" Calling-Station-Id = "00-0E-35-EE-67-0F" NAS-Port-Type = Wireless-802.11 Connect-Info = "CONNECT 54Mbps 802.11g" EAP-Message = 0x020600060d00 NAS-IP-Address = 192.168.1.254 NAS-Port = 1 NAS-Port-Id = "STA port # 1" Processing the authorize section of radiusd.conf modcall: entering group authorize for request 6 modcall[authorize]: module "preprocess" returns ok for request 6 modcall[authorize]: module "chap" returns noop for request 6 modcall[authorize]: module "mschap" returns noop for request 6 rlm_realm: No '@' in User-Name = "test_user9", looking up realm NULL : modcall[authorize]: module "suffix" returns noop for request 6 modcall[authorize]: module "suffix" returns noop for request 6 rlm_eap: EAP packet type response id 6 length 6 rlm_eap: No EAP Start, assuming it's an on-going EAP conversation modcall[authorize]: module "eap" returns updated for request 6 users: Matched entry DEFAULT at line 152 users: Matched entry DEFAULT at line 171 modcall[authorize]: module "files" returns ok for request 6 modcall: leaving group authorize (returns updated) for request 6 rad_check_password: Found Auth-Type EAP auth: type "EAP" Processing the authenticate section of radiusd.conf modcall: entering group authenticate for request 6 rlm_eap: Request found, released from the list rlm_eap: EAP/tls rlm_eap: processing type tls rlm_eap_tls: Authenticate rlm_eap_tls: processing TLS rlm_eap_tls: Received EAP-TLS ACK message rlm_eap_tls: ack alert eaptls_verify returned 4 eaptls_process returned 4 rlm_eap: Handler failed in EAP/tls rlm_eap: Failed in EAP select modcall[authenticate]: module "eap" returns invalid for request 6 modcall: leaving group authenticate (returns invalid) for request 6 auth: Failed to validate the user. Login incorrect: [test_user9/] (from client test_ap port 1 cli 00-0E-35- EE-67-0F) # # в доступе клиенту отказано # Delaying request 6 for 1 seconds Finished request 6 #=====================================================

Таким образом, если Radius видит, что клиентский сертификат отозван, то клиенту отказывают в доступе — именно то, что нам надо. Главное — не забывать вовремя перегенерировать CRL-списки и не ждать их устаревания. 

На этом, полагаю, цикл статей о настройке WPA шифрования с использованием Radius сервера под Linux можно завершить. Разумеется, если появится дополнительная информация, не отраженная в этом материале, свет увидит и седьмая, а возможно и последующие статьи… а пока — поставим в материале точку. 

Навигация

 

12 октября 2006 Г.