Ещё один компьютерный пост.
Недавно построил WiFi-сетку с аутентикацией по 802.1x, использующую сертификаты для опознания юзеров. В числе прочего, пришлось настраивать для работы с ней устройства на Android - смартфоны и планшетки. Тут-то и выяснилось, что нормального howto, как это сделать, найти не получается - те, которые были, касались сценариев с паролями, а мне от них-то и хотелось избавиться. Потому и решил свести информацию по вопросу в один пост.
Что такое
802.1x и как его использовать на
Windows и
Linux, написано предостаточно, поэтому тут будет только про настройку клиента на Android.
Итак, в чём цель? Надо создать сетку с приличным шифрованием и надёжной аутентикацией, при этом требуется, чтобы аутентикация была как можно более удобна для юзера, но при этом защищена от юзера же. То есть я, в качестве админа, не хочу, чтобы юзер мог передать кому другому свой пароль или файл с секретным ключом, или же подключился с устройства, с которого я не хочу позволять ему подключаться - например, личного лэптопа. В общем, мрак и диктатура.
Для этого делаем следующее: на устройство (телефон, планшетку) ставится сертификат с секретным ключом (на каждый девайс - отдельный ключ). Управление ключами в Андроиде весьма примитивно, однако даёт ровно тот минимум, какой нам требуется - даёт импортировать ключ и использовать его, но не извлекать обратно (по крайней мере, без пароля, который мы выдавать не собираемся). Эти ключи и будут выдаваться access point’у в ответ на требование представиться.
Процедурка вся укладывается в 4 шага:
1. Подготовка “credential storage”:
Перед тем, как заводить в девайсину какие-либо секретные ключи, надо подготовить для них хранилище, где ключи будут сохраняться в зашифрованном виде. Шифрование будет происходить на основе пароля, который вводится лишь при создании хранилища. Для использования секретного ключа пароль вводить не нужно - лишь для его экспорта (который к тому же невозможно осуществить через обычный андроидный UI). Посему пароль мы этот оставим у себя, а юзеру выдавать отнюдь не будем. Evil laughter прилагается.
[Update: увы, не выйдет. При выключении девайса пароль уходит, и для использования ключей его придётся вводить заново. У этого есть и хорошие, и плохие стороны:
* Сохранять пароль в тайне от юзера не выйдет - иначе придётся вводить его всякий раз при включении.
* Это значит, что теоретически юзер может скопировать из девайса секретный ключ - что с админской точки зрения плохо. Но, насколько я понимаю, ему для этого требуется рутовый доступ. Получение такого доступа хлопотно, но возможно.
* Хорошая сторона в том, что сам пароль в флэш-памяти не сохраняется - а криптоключи, которые сохраняются, шифруются этим паролем по AES.
* Ну и к тому же, если пароль при включении введён ещё не был, то это даёт защиту от кого-то постороннего, кто попытается использовать ключ, пароля не зная.
]
Пароль можно впоследствии сменить - но лишь при знании нынешнего. Можно и обнулить всё хранилище - при этом пароль уйдёт, и юзер сможет выставить свой, но с ним погибнет безвозвратно также и секретный ключ, прямо как тайна верескового мёда.
Собственно процесс: Settings --> Location and security --> Set password. Ввести пароль дважды. После чего галочка “Use secure credentials” включится автоматически.
Чтобы поменять пароль: “Set password” повторно.
Чтобы обнулить всё нафиг: “Clear storage” там же.
2. Импорт корневого сертификата:
Нужно забросить в девайс файл с расширением .crt (.cer не принимается) и в формате PEM, также известном как Base-64. Можно это сделать через USB, можно через Bluetooth. Файл должен быть скопирован в директорию /sdcard - та, что видна как корень при подключении девайса через USB или при просмотре файлов через “My Files”.
Затем: Settings --> Location and security --> Install encrypted certificates (хоть в данном случае сертификат и не encrypted). Сертификат будет добавлен в список доверяемых, а файл в /sdcard стёрт.
Более удобный способ: опубликовать сертификат на каком-нибудь веб-сайте и просто открыть его URL в родном андроидном браузере (для пущей надёжности, использовать известный вебсервис через https или же сугубо внутренний сайт). Тот сразу запросит, добавить ли сертификат в список доверяемых, или нет. Чтобы не набивать URL руками, можно
сгенерировать QR-code с ним, и затем просто отсканить его.
3. Импорт сертификата юзера с секретным ключом:
Файл с секретным ключом в формате PKCS#12 и с расширением .p12 кладётся в /sdcard (.pfx, опять же, игнорируется). Способов создать такой файл множество - не буду их перечислять, но отмечу, что обязательно стоит задать для него одноразовый пароль, шифрующий ключ.
Затем, опять же, Settings --> Location and security --> Install encrypted certificates. На этот раз будет запрошен пароль. Это не тот, что задавался при создании хранилища, а тот, который нужен для расшифровки ключа из файла. После введения пароля, ключ будет дешифрован и сохранён зашифрованным заново - на этот раз, паролем от хранилища. Файл же будет стёрт из /sdcard, что нас вполне устраивает.
Можно также забросить файл .p12 через URL, но я бы не стал - в отличие от сертификатов, расползания ключей, хоть и в шифрованном виде, стоит избегать.
4. Подключение к собственно сети:
После того, как ключ задан, остались лишь настройки WiFi-сети. Ничего секретного в этом этапе нет, можно оставить его юзерам, выслав инструкцию.
Итак: Settings --> Wireless and network --> Wi-Fi settings. Найти сеть в списке, либо, если SSID скрыт, жмякнуть на “Add Wi-Fi network”.
Затем:
Network SSID:
если нужно
Security:
802.1x EAP
EAP method:
TLS
[1] Phase 2 authentication:
None
CA certificate:
корневой сертификат, введённый на шаге 2.
User certificates:
юзерский сертификат с секретным ключом, введённый на шаге 3.
Identity:
юзернейм в полном формате, типа user@domain.full.name
[2] Anonymous identity:
не нужно
Password:
не нужно
На более продвинутых устройствах можно задать также для каждой сети настройки proxy, что очень удобно.
Всё. После этого юзеру останется только жмякнуть по названию сетки и подключиться. Если же он по недомыслию как-нибудь нажмёт на “Forget network” и сотрёт настройки, для восстановления достаточно лишь пройти заново шаг 4 - процедура несекретная, юзер её может проделать сам.
Примечания:
[1] В принципе, есть также опция PEAP. Протокол PEAP-EAP-TLS считается чуть более защищённым - к примеру, юзерский сертификат в нём пересылается в зашифрованном виде по установленному туннелю TLS. Однако мои усилия заставить Андроид работать в этом режиме ни к чему не привели. Подозреваю, что дело в том, что поле “Phase 2 authentication” не содержит опции для использования юзерского сертификата - поэтому приходится удолетворяться EAP-TLS, которому никакой phase 2 не нужен. Но разница минимальна и несущественна.
[2] Понятия не имею, зачем нужен. В принципе, юзер должен опознаваться по полю CN в сертификате.