Wi-Fi с логином и паролем для каждого пользователя или делаем WPA2-EAP/TLS подручными средствами

  • Tutorial
С практической точки зрения было бы удобно управлять Wi-Fi сетями, выдавая пароль каждому пользователю. Это облегчает задачу с доступом к вашей беспроводной сети. Используя так называемую WPA2 PSK авторизацию, чтобы предотвратить доступ случайному пользователю, нужно менять ключ, а также заново проходить процесс авторизации на каждом отдельном Wi-Fi устройстве. Кроме того, если вы имеете несколько точек доступа, ключ нужно менять на всех из них. А если Вам надо скрыть пароль от кого-нибудь, придется раздать всем сотрудникам новый.

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

Мы сделаем удобную схему, применяемую в корпоративных сетях, но полностью из подручных средств с минимальными финансовыми и аппаратными вложениями. Ее одобрит служба безопасности и руководство.

Немного теории


Когда-то давно инженерами IEEE был придуман стандарт 802.1x. Этот стандарт отвечает за возможность авторизации пользователя сразу при подключении к среде передачи данных. Иными словами, если для соединения, например, PPPoE, вы подключаетесь к среде(коммутатору), и уже можете осуществлять передачу данных, авторизация нужна для выхода в интернет. В случае же 802.1x вы не сможете делать ничего, пока не авторизуетесь. Само конечное устройство вас не допустит. Аналогичная ситуация с Wi-Fi точками доступа. Решение же о допуске вас принимается на внешнем сервере авторизации. Это может быть RADIUS, TACACS, TACACS+ и т.д.

Терминология


Вообще авторизация пользователя на точке может быть следующих видов:
  • Open — доступна всем
  • WEP — старое шифрование. Уже у всех плешь проедена о том, что его ненадо использовать вообще
  • WPA — Используется TKIP в качестве протокола шифрования
  • WPA2 — Используется шифрование AES


А теперь рассмотрим варианты того, как точка доступа узнает сама, можно ли предоставлять пользователю доступ к сети или нет:
  • WPA-PSK, WPA2-PSK — ключ к доступу находится в самой точке.
  • WPA-EAP, WPA2-EAP — ключ к доступу сверяется с некоторой удаленной базой данных на стороннем сервере


Также существует довольно большое количество способов соедининея конечного устройства к серверу авторизации (PEAP, TLS, TTLS...). Я не буду их здесь описывать.

Общая схема сети


Для наглядного понимания приведем общую схему работы нашей будущей схемы:


Если словами, то клиенту, при подключении к Wi-Fi — точке предлагается ввести логин и пароль. Получив логин и пароль Wi-Fi точка передает эти данные RADIUS-серверу, на что сервер отвечает, что можно делать с этим клиентом. В зависимости от ответа, точка решает, дать ему доступ, урезать скорость или что-то еще.
За авторизацию пользователей будет отвечать наш сервер с установленным freeradius. Freeradius является реализацией протокола RADIUS, который в свою очередь является реализацией общего протокола AAA. AAA — это набор средств для осуществления следующих действий:
Authentication — проверяет допустимость логина и пароля.
Authorization — проверяет наличие прав на выполнение некоторых действий.
Accounting — учитывает ваши дейсвия в системе.
Сам протокол передает имя пользователя, список атрибутов и их значений для него. То есть, например, атрибут Auth-Type := Reject — отклонить этого клиента, а Client-Password == «password» — сравнить атрибут в запросе со значением password.
Вообще говоря, база аккаунтов и прав для них не обязательно должна храниться на RADIUS-сервере, да и базой может быть что угодно — никсовые пользователи, пользователи домена Windows… да хоть текстовый файлик. Но в нашем случае все будет в одном месте.

Базовая настройка


В этой статье нас будут интересовать в первую очередь WPA2-EAP/TLS способ авторизации.
Практически все современные точки доступа Wi-Fi стоимостью больше 3 тыс. рублей поддерживают нужную нам технологию. Клиентские устройства поддерживают и подавно.
В статье я буду использовать следующее оборудование и програмное обеспечение:
  • Точка доступа Ubiquiti NanoStation M2
  • Сервер Gentoo и Freeradius
  • Клиентское оборудование с установленным програмным обеспечением Windows 7, Android, iOS


Настройка точки доступа


Главное, чтоб точка поддерживала нужный способ аутентификации. Оно может называться по разному в разных устройствах: WPA-EAP, WPA2 Enterprise и т.д. Во всяком случае выбираем аутентификацию, устанавливаем IP-адрес и порт RADIUS-сервера и ключ, который мы вводили в clients.conf при настройке Freeradius.
Приведу картинку с настроенной точки Ubiquiti. Помечено галкой то, что нужно менять.
image

RADIUS-сервер


Зайдем на наш компьютер с Linux и установим RADIUS-сервер. Я брал freeradius, и ставил я его на gentoo. К моему удивлению, в рунете нет материалов, относящихся к настройке Freeradius 2 для наших целей. Все статьи довольно стары, относятся к старым версиям этого програмного обеспечения.
root@localhost ~ # emerge -v freeradius

Все:) RADIUS-сервер уже может работать:) Вы можете проверить это так:
root@localhost ~ # radiusd -fX

Это debug-mode. Вся информация вываливается на консоль. Приступем к его настройке.
Как это водится в Linux, настройка выполняется через конфигурационные файлы. Конфигурационные файлы хранятся в /etc/raddb. Сделаем подготовительные действия — скопируем исходные конфиги, почистим конфигурация от всякого мусора.
root@localhost ~ # cp -r /etc/raddb /etc/raddb.olg
root@localhost ~ # find /etc/raddb -type f -exec file {} \;  | grep 'text' | cut -d':' -f1 | xargs sed -i '/^ *\t* *#/d;/^$/d'

Далее добавим клиента — точку доступа. Добавляем в файлик /etc/raddb/clients следующие строки:
root@localhost ~ # cat /etc/raddb/clients.conf | sed '/client test-wifi/,/}/!d'
client test-wifi {
        ipaddr = 192.168.0.1 #IP адрес точки, которая будет обращаться к радиусу
        secret = secret_key #Секретный ключик. Такой же надо будет поставить на Wi-Fi точке.
        require_message_authenticator = no  #Лучше так, с каким-то D-Linkом у меня не получилось иначе
}

Далее добавляем домен для пользователей. Сделаем дефолтовый.
root@localhost ~ # cat /etc/raddb/proxy.conf | sed '/realm DEFAULT/, /^}/!d'
realm DEFAULT {
        type = radius
        authhost = LOCAL
        acchost = LOCAL
}

Домены в RADIUS
Здесь надо заметить, что можно делить пользователей по доменам. А именно, в формате имени пользователя может указываться домен(например user@radius). DEFAULT означает любой неопределенный домен. NULL — без домена. В зависимости от домена(можно сказать префикса в имени пользователя) можно осуществлять различные действия, как то отдать право аутентифицировать другому хосту, отделять ли имя от домена во время проверки логина и т.д.

И, наконец, добавляем пользователей в файл /etc/raddb/users:
root@localhost ~ # cat /etc/raddb/users | sed '10,$!d'
user1 Cleartext-Password := "password1"
user2 Cleartext-Password := "password2"
user3 Cleartext-Password := "password3"

Ух, можно стартовать!
root@localhost ~ # radiusd -fX

Наш сервер запущен и ждет подключений!

Настройка клиентов


Пробежимся по настройке основных пользовательских устройств. У наших сотрудников есть клиенты, работающие на Android, iOS и Windows 7. Оговоримся сразу: так как мы используем самосозданные сертификаты, то нам нужно несколько раз вносить всевозможные исключения и подтверждать действия. Если бы мы пользовали купленные сертификаты, возможно, все было бы проще.

Всех проще дело обстоит на iOS-устройствах. Вводим логин и пароль, нажимаем «Принять сертификат», и вперед.
Скриншот с IOS
image


Чуть сложнее выглядит, но на практике все тоже просто на Android. Там немного больше полей для ввода.
Скриншот с Android
image


Ну и на Windows 7 приедтся немного понастраивать. Осуществим следующие шаги:
Идем в центр беспроводных подключений.
  1. Устанавливаем необходимые параметры в свойствах Вашего беспроводного подключения
  2. Устанавливаем необходимые параметры в расширенных настройках EAP
  3. Устанавливаем необходимые параметры в расширенных настройках Дополнительных параметрах
  4. Подключаемся в панели задач к Wi-Fi сети и вводим логин-пароль, наслаждаемся доступом к Wi-Fi


Далее представлю скриншоты диалоговых окон специально для похожих на меня людей, у которых глаза разбегаются от диалоговых окон Windows.
Скриншоты Windows
Шаг 1

Шаг 2

Шаг 3

Шаг 4

Шаг 5



Собственный мини-биллинг


Теперь осталась одна проблема — если вы захотите добавить-удалить нового пользователя, то вам придется изменить users и перезапустить radius. Чтобы этого избежать подключим базу данных и сделать свой собственный мини-биллинг для пользователей. Используя БД, вы всегда сможете набросать простенький скрипт для добавления, блокировки, изменения пароля пользователя. И все это произойдет без останова всей системы.

Для себя я использовал Postgres, вы же можете выбрать по своему усмотрению. Я привожу базовую настройку Postgres, не углубляясь в различные права доступа, пароли и прочие хитрости и удобства.

Для начала создаем саму базу данных:

root@localhost ~ # psql -U postgres
radius_wifi=> create user radius_wifi with password 1111;
radius_wifi=> create database radius_wifi with owner=radius_wifi;
radius_wifi=> \q


Далее надо создать нужные таблицы. Вообще с Freeradius идет документация по схемам таблиц для различных баз данных, правда в различных дистрибутивах находятся они в разных местах. У меня лично это лежит в /etc/raddb/sql/postgresql/schema.sql. Просто вставьте эти строки в psql, либо просто запустите

root@localhost ~ # cat /etc/raddb/sql/postgresql/schema.sql | psql -U radius_wifi radius_wifi


На всякий случай добавлю сюда схему для Postgres:
Схема для Postgres
root@localhost ~ # cat /etc/raddb/sql/postgresql/schema.sql | sed '/^--/d;/\/\*/d;/\*/d;/^$/d;'
CREATE TABLE radacct (
        RadAcctId               BIGSERIAL PRIMARY KEY,
        AcctSessionId           VARCHAR(64) NOT NULL,
        AcctUniqueId            VARCHAR(32) NOT NULL UNIQUE,
        UserName                VARCHAR(253),
        GroupName               VARCHAR(253),
        Realm                   VARCHAR(64),
        NASIPAddress            INET NOT NULL,
        NASPortId               VARCHAR(15),
        NASPortType             VARCHAR(32),
        AcctStartTime           TIMESTAMP with time zone,
        AcctStopTime            TIMESTAMP with time zone,
        AcctSessionTime         BIGINT,
        AcctAuthentic           VARCHAR(32),
        ConnectInfo_start       VARCHAR(50),
        ConnectInfo_stop        VARCHAR(50),
        AcctInputOctets         BIGINT,
        AcctOutputOctets        BIGINT,
        CalledStationId         VARCHAR(50),
        CallingStationId        VARCHAR(50),
        AcctTerminateCause      VARCHAR(32),
        ServiceType             VARCHAR(32),
        XAscendSessionSvrKey    VARCHAR(10),
        FramedProtocol          VARCHAR(32),
        FramedIPAddress         INET,
        AcctStartDelay          INTEGER,
        AcctStopDelay           INTEGER 
);
CREATE INDEX radacct_active_user_idx ON radacct (UserName, NASIPAddress, AcctSessionId) WHERE AcctStopTime IS NULL;
CREATE INDEX radacct_start_user_idx ON radacct (AcctStartTime, UserName);
CREATE TABLE radcheck (
        id              SERIAL PRIMARY KEY,
        UserName        VARCHAR(64) NOT NULL DEFAULT '',
        Attribute       VARCHAR(64) NOT NULL DEFAULT '',
        op              CHAR(2) NOT NULL DEFAULT '==',
        Value           VARCHAR(253) NOT NULL DEFAULT ''
);
create index radcheck_UserName on radcheck (UserName,Attribute);
CREATE TABLE radgroupcheck (
        id              SERIAL PRIMARY KEY,
        GroupName       VARCHAR(64) NOT NULL DEFAULT '',
        Attribute       VARCHAR(64) NOT NULL DEFAULT '',
        op              CHAR(2) NOT NULL DEFAULT '==',
        Value           VARCHAR(253) NOT NULL DEFAULT ''
);
create index radgroupcheck_GroupName on radgroupcheck (GroupName,Attribute);
CREATE TABLE radgroupreply (
        id              SERIAL PRIMARY KEY,
        GroupName       VARCHAR(64) NOT NULL DEFAULT '',
        Attribute       VARCHAR(64) NOT NULL DEFAULT '',
        op              CHAR(2) NOT NULL DEFAULT '=',
        Value           VARCHAR(253) NOT NULL DEFAULT ''
);
create index radgroupreply_GroupName on radgroupreply (GroupName,Attribute);
CREATE TABLE radreply (
        id              SERIAL PRIMARY KEY,
        UserName        VARCHAR(64) NOT NULL DEFAULT '',
        Attribute       VARCHAR(64) NOT NULL DEFAULT '',
        op              CHAR(2) NOT NULL DEFAULT '=',
        Value           VARCHAR(253) NOT NULL DEFAULT ''
);
create index radreply_UserName on radreply (UserName,Attribute);
CREATE TABLE radusergroup (
        UserName        VARCHAR(64) NOT NULL DEFAULT '',
        GroupName       VARCHAR(64) NOT NULL DEFAULT '',
        priority        INTEGER NOT NULL DEFAULT 0
);
create index radusergroup_UserName on radusergroup (UserName);
CREATE TABLE radpostauth (
        id                      BIGSERIAL PRIMARY KEY,
        username                VARCHAR(253) NOT NULL,
        pass                    VARCHAR(128),
        reply                   VARCHAR(32),
        CalledStationId         VARCHAR(50),
        CallingStationId        VARCHAR(50),
        authdate                TIMESTAMP with time zone NOT NULL default 'now()'
);



Отлично, база подготовлена. Теперь законфигурим Freeradius.
Добавьте, если ее там нет, в /etc/raddb/radiusd.conf строку

 $INCLUDE  sql.conf


Теперь отредактируйте /etc/raddb/sql.conf под вашу реальность. У меня он выглядит так:

Мой sql.conf
root@localhost ~ # cat /etc/raddb/sql.conf
sql {
        database = "postgresql"
        driver = "rlm_sql_${database}"
        server = "localhost"
        login = "radius_wifi"
        password = "1111"
        radius_db = "radius_wifi"
        acct_table1 = "radacct"
        acct_table2 = "radacct"
        postauth_table = "radpostauth"
        authcheck_table = "radcheck"
        authreply_table = "radreply"
        groupcheck_table = "radgroupcheck"
        groupreply_table = "radgroupreply"
        usergroup_table = "radusergroup"
        deletestalesessions = yes
        sqltrace = no
        sqltracefile = ${logdir}/sqltrace.sql
        num_sql_socks = 5
        connect_failure_retry_delay = 60
        lifetime = 0
        max_queries = 0
        nas_table = "nas"
        $INCLUDE sql/${database}/dialup.conf
}


Добавим несколько новых пользователей test1, test2, test3, и… заблокируем test3

root@localhost ~ # psql -U postgres
radius_wifi=> insert into radcheck (username, attribute, op, value) values ('test1', 'Cleartext-Password', ':=', '1111');
radius_wifi=> insert into radcheck (username, attribute, op, value) values ('test2', 'Cleartext-Password', ':=', '1111');
radius_wifi=> insert into radcheck (username, attribute, op, value) values ('test3', 'Cleartext-Password', ':=', '1111');
radius_wifi=> insert into radcheck (username, attribute, op, value) values ('test3', 'Auth-Type', ':=', 'Reject');


Ну, перезапускаем freeradius и пробуем подключиться. Должно все работать!

Конечно биллинг получился ущербный — у нас нигде не хранится информации по аккаунтингу(учету действий пользователя), но и нам здесь этого не надо. Чтобы вести аккаунтинг, необходимы еще и Wi-Fi точки подорооже, чем 3 тыс. рублей. Но уже и так мы с легкостью управлять пользователями.

Что дальше


В последнем разделе мы собрали собственный небольшой биллинг! Остается для полноты картины привернуть какой-нибудь WEB-интерфейс управления Базой Данных, добавить обязательное изменение пароля раз в месяц по крону. А если еще разориться сертификат и контроллер Wi-Fi точек доступа, то у вас в руках есть полноценная корпоративная беспроводная сеть. Но даже без этих затрат и при малых усилиях с Вашей стороны сделав своим пользователям такой доступ, они вам скажут огромное спасибо.

Полезные ссылки


Старая, но частично актуальная инструкция на ixbt
WIKI FreeRadius
Используемая точка Wi-Fi Ubiquiti Nanostation M2
Share post

Similar posts

Comments 25

    0
    Спасибо. Все доходчиво и понятно.
    Вот еще про DIAMETR ( habrahabr.ru/post/164203/ ) — это развитие стандарта RADIUS.
      0
      Да, про диаметр я слышал. Но железок, работающих с ним, практически нет. Если только дорогой корпоративный сегмент.
      0
      По части вебморды — есть daloradius
        +1
        Хорошая статья, спасибо.
          +4
          Стараюсь придать хабру старый инженерный вид. Четкая тематика без абстрактной болтовни, в стиле opennet.ru, только с картиночками:)
            0
            Вот за это отдельная спасибо.
            Статья хорошая, с чувством, с расстановкой!
              +1
              Это благодаря тому, что все описанное реализовано и ряд людей консультировались со мной, как им сделать что-то похожее. Вообще, мне понравилась такая стратегия написания технических статей: делаешь, рассказываешь другим, собираешь вопросы, пишешь так, чтобы вопросов не осталось.
          0
          Стоило наверное упомянуть, что при использовании самоподписанных сертификатов и отключении проверки (шаг 3), безопасность WPA2-ENT становится в разы слабее чем WPA2-PSK. При отключении проверки и активных клиентах получить доступ к такой сети проще, чем к WEP. Поэтому данная конфигурация, без «разорения на сертификат», не рекомендуется к использованию :)
            0
            Конечно же в теории — да. Но мы живем в немного других условиях. И для маленьких контор до 20 человек с максимум 3-мя хотспотами этот способ отлично подойдет. В таких предприятиях главное то, чтоб мужик из соседнего офиса не пользовал ваш интернет, а потенциальный контрагент мог бы почитать почту с планшета с гостевым логином.
            Если конторе есть что скрывать, она может разориться на подписанный сертификат. Freeradius его отлично проглотит. А если уж совсем захочет, то купит еще и контроллер беспроводных точек с кучей всяких вкусностей.
              0
              Собственно с такой конфигурацией они и займутся:
              мужик из соседнего офиса не пользовал ваш интернет, а потенциальный контрагент мог бы почитать почту с планшета с гостевым логином

              Для таких контор WPA2-PSK намного надежнее, а если уж хочется WPA2-ENT, то стоит не снимать эту пресловутую галку и просто вручную поставить везде ваш корневой сертификат.
                0
                А вот на айфоне я не нашел способа поставить свой корневой сертификат:)
                  0
                  Стандартный способ (как с сертификатами для SSL) разве не работает?
                    0
                    Что-то я про это не подумал. В свободное время попробую. Если подойдет, статью обновлю с дополнительными способами подключения клиентов:)
            0
            Чтобы вести аккаунтинг, необходимы еще и Wi-Fi точки подорооже, чем 3 тыс. рублей.
            А насоветуйте? Что-нибудь минимальное.
              0
              Я бы посоветовал что-то с DD-WRT (какой-нибудь Mikrotik). Но точно не могу сказать. Знаю точно, что есть на Aironet'ах от Cisco.
                0
                Aruba Instant Access Points

                Описание 1
                Описание 2
                  0
                  А какую информацию они могут отдавать по аккаунтингу?
              0
              Есть ли более другие методы авторизации, не требующие добавления сертификата?
                0
                Описанный в статье метод пропускает момент с серьификатами. А с сертификатами тоже есть два варианта: либо просто добавление вашего серверного сертификата в пользовательские телефон — при этом пользователь будет также вводить логин и пароль. Либо добавить на устройство пользователя пользовательский сертификат, при этом не надо будет вводить ничего.

                Как вариант — поставить отдельную точку или, если позволяет устройство, второе SSID, и разрешить с него только доступ к почте. Из почты можно добавлять ключи в любое устройство.
                  +1
                  Можно небольшое занудное замечание?
                  До конца статьи я ещё не дочитал (сама статья интересная, если что), но
                  emerge -vp
                  -p

                  Все:) RADIUS-сервер уже может работать:)

                  :(
                    0
                    Да, надо без -p
                    0
                    P.S. досчитал статью и родился вопрос о том, как в iOS/Android/Win с добавлением в корневое хранилище сертификата своего наколеночного CA?
                    // как в GNU/Linux-то я, например, знаю…
                      0
                      Вот, сейчас как раз пишу статью о генерации сертификатов, и их добавление в разные пользовательские устройства. Объем опять же довольно большо получается, и проверить надо много чего. Думаю, через неделю закончу.
                      0
                      Решил у себя поковырять WPA2-Ent на т.д. Unifi с LDAP-бакэндом для radius'a. В качестве LDAP-а используется Zimbra Collaboration Suite 8.0.
                      Проблема состоит в том, что если тестировать через radtest — все ок, а вот если с устройства (пробовал на своей WP8 и каком-то стареньком андроиде) — не удается подключиться.

                      в дебаге пишет следующее:
                      Кусок дебага
                      [peap] processing EAP-TLS
                      [peap] eaptls_verify returned 7
                      [peap] Done initial handshake
                      [peap] eaptls_process returned 7
                      [peap] EAPTLS_OK
                      [peap] Session established. Decoding tunneled attributes.
                      [peap] Peap state send tlv failure
                      [peap] Received EAP-TLV response.
                      [peap] The users session was previously rejected: returning reject (again.)
                      [peap] *** This means you need to read the PREVIOUS messages in the debug output
                      [peap] *** to find out the reason why the user was rejected.
                      [peap] *** Look for «reject» or «fail». Those earlier messages will tell you.
                      [peap] *** what went wrong, and how to fix the problem.
                      [eap] Handler failed in EAP/peap
                      [eap] Failed in EAP select
                      ++[eap] returns invalid
                      Failed to authenticate the user.
                      Using Post-Auth-Type Reject
                      # Executing group from file /etc/freeradius/sites-enabled/default
                      +- entering group REJECT {...}
                      [attr_filter.access_reject] expand: %{User-Name} -> m0ps
                      attr_filter: Matched entry DEFAULT at line 11
                      ++[attr_filter.access_reject] returns updated
                      Delaying reject of request 15 for 1 seconds
                      Going to the next request
                      Waking up in 0.9 seconds.
                      Sending delayed reject for request 15
                      Sending Access-Reject of id 113 to 192.168.100.210 port 1062
                      EAP-Message = 0x04d10004
                      Message-Authenticator = 0x00000000000000000000000000000000
                      Waking up in 3.5 seconds.


                      Никто не сталкивался?

                      Only users with full accounts can post comments. Log in, please.