20.07.2011

PPTP с авторизацией в LDAP через RADIUS

Жизнь штука интересная. Всегда преподносит сюрпризы. К сожалению, прекрасный VPN продукт, лучший в мире из софтверных, - OpenVPN, оказался плох тем, что не поддерживается на нативном уровне ни одной популярной операционной системой. А ставить клиента, сертификаты и конфиги оказалось непосильной задачей для особо "интеллектуальных" людей (и это при простейшем мануале в три клика).
"Искаропки" и Windows и Ubuntu и MacOS и Symbian и Android поддерживают только PPTP.

Итак приступим. Схема будет такая:
клиент соединяется по PPTP с PPTP-сервером. Организуется тоннель. Внутри этого тоннеля соединяются PPP-клиент и PPP-сервер и первый запрашивает у второго логин с паролем в форме MS-CHAPv2 (почему именно его - опишу ниже). PPP-сервер берет эти данные и просит RADIUS-сервер провести аутентификацию. Так как наши пользователи хранятся в LDAP-каталоге, то RADIUS обращается к этому каталогу, биндится от имени администратора, берет из него хэши пользователя и сравнивает с теми, что ему дал PPP-сервер. После чего дает ответ PPP-серверу пускать клиента или не пускать.


Теперь маленькая ремарка о том, почему единственно возможный вариант передачи пароля - MS-CHAPv2 (v2 - вторая версия). Есть четыре основных варианта: PAP (без шифрования), CHAP (с шифрованием), MS-CHAPv1/v2 (с шифрованием, совместимым с NT/LM) и EAP.
PAP для нас не подходит потому, что по умолчанию при создании PPTP-подключения Windows требует шифрования. Можно это изменить в свойствах настройки, но это требует целых два клика мышью, что опять таки делает задачу невыполнимой для многих.
CHAP для нас не подходит потому, что по умолчанию в LDAP хранятся только NT/LM хэши паролей, а CHAP-хешей там нет. Провести аутентификацию RADIUS не сможет. Можно было позаботиться об этом при разворачивании LDAP-сервера, чтобы были и CHAP-пароли, но теперь уже поздно. Если добавить это поле, что нужно заставлять клиентов сменить пароль, чтобы это поле заполнилось.
EAP, если я не путаю, не будет работать с LDAP по каким-то другим причинам, описанным в конфиге его модуля. Могу ошибаться. Не суть важно.
Остается настраивать MS-CHAPv2.



Подразумевается, что LDAP-сервер уже у Вас настроен. В нем есть следующие поля (ну это не все поля, а только нужные нам):
dn: uid=test,ou=people,dc=nodesquad,dc=com
uid: test
sambaLMPassword: C2265B23734E0DACAAD3B435B51404EE
sambaNTPassword: 69943C5E63B4D2C104DBBCC15138B72B
userPassword:: e0NSWVBUfSQxJEU0ekouMlBNJHNkMk1QUUtrVWNoTXMwQlNhMWZYSS4=


Поставим FreeRADIUS-cервер:
apt-get install freeradius freeradius-ldap

Теперь нужно немножко его отконфигурировать. Все клиенты RADIUS-сервера, в том числе и PPP-демон, должны подключаться не просто как хотят, а по правилам, описанным для клиентов и при этом из этих правил они должны взять секретный ключ. Так как у нас оба этих сервиса на одной машине, то править будем описание клиента, который пришел с localhost.
Сделаем секретный ключ:
pwgen 20 1
EetasiegoolahH2giP6c
и внесем его в файл описания клиентов (заменить строчку "testing123" на "EetasiegoolahH2giP6c"):
vim /etc/freeradius/clients.conf

Теперь  настроим подключение RADIUS-сервера к LDAP:
vim /etc/freeradius/modules/ldap

server = "ldap-server.nodesquad.com"
identity = "cn=admin,dc=nodesquad,dc=com"
password = niequ8iqueung9ea1vi2ooY5we8uzo
basedn = "ou=people,dc=nodesquad,dc=com"
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"

Внимание! Если Вы думаете, что у Вас можно биндиться к LDAP-серверу и как гость (без указания админа), то Вы очень ошибаетесь. RADIUS-сервер не будет спрашивать у LDAP можно пропустить клиента или нет - он нагло берет оттуда данные и принимает решение сам. Если Вы не укажете identity и password, то Вас ждет ошибка "No Cleartext-Password configured." и замучаетесь гуглить, что это такое. Я потратил двое суток, чтобы это понять.

Далее разрешаем RADIUS-серверу проводить аутентификацию через LDAP:
vim /etc/freeradius/sites-available/default
нужно расскомментировать упоминания об LDAP в секциях authorize и authenticate.

Перегружаем демон, чтобы он подхватил настройки:
invoke-rc.d freeradius restart
И проверяем любую учетку из LDAP:
radtest testuser testpass localhost 0 EetasiegoolahH2giP6c
Правильный ответ будет оканчиваться строчкой rad_recv: Access-Accept packet from host 127.0.0.1 с дополнительной служебной информацией.


С FreeRadius закончили. Теперь ставим PPTP и PPP серверы:
apt-get install pptpd ppp

Смотрим куда нас направили PPTP-шные настройки за опциями PPP:
grep option /etc/pptpd.conf | grep -v '#'

И идем ковырять их:
vim /etc/ppp/pptpd-options

выключаем pap, chap и mschap, но включаем mschap-v2 и шифрование
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128


и в самом низу добавляем плагины
# Authenticate against RADIUS
plugin radius.so
plugin radattr.so

Таким образом мы сказали PPP-серверу, что нужно взять пароль от пользователя по MS-CHAPv2 и в таком виде передать его RADIUS-серверу.

Когда мы проверяли работоспособность связки RADIUS-LDAP, подключаясь к RADIUS-серверу утилитой radtest, то указали ключ из clients.conf прямо в командной строке. Попросить тоже самое сделать PPP-сервер, когда он обращается к RADIUS-серверу мы не можем. Поэтому для таких вот существует комплект настроек под названием RADIUS-клиент. Поставим его:
apt-get install radiusclient1
 

Теперь в настройке клиентской части впишем ключик сервера, который мы когда то вписали в настройке серверной части для доступа клиентов (/etc/freeradius/сlients.conf):
vim /etc/radiusclient/servers


localhost     EetasiegoolahH2giP6c

Далее выключаем возможность аутентифицироваться локально:
vim /etc/radiusclient/radiusclient.conf
auth_order      radius

Теперь следует подключить библиотеки, которые помогут RADIUS-клиенту передавать MS-CHAPv2 от PPTP к FreeRADIUS. Особое внимание хочу уделить тому, что вообще эти библиотеки уже есть в директории /usr/share/freeradius/ , но они не подходят, потому что рассчитаны на новый FreeRADIUS (потому и идут с ним в комплекте) и там другая разметка. А PPTP, а точнее его radius-плагин, не умеет использовать новые библиотеки.
Поэтому подключим стандартный старый merit-словарь, а также скачанный отсюда microsoft-словарь:

wget -O/etc/radiusclient/dictionary.microsoft https://sites.google.com/site/nodesquad/dictionary.microsoft

И добавим оба словаря в самый конец файла определения словарей (внимание!!! никаких $INCLUDE как во FreeRADIUS, только INCLUDE - иначе не заработает):
vim /etc/radiusclient/dictionary


INCLUDE /etc/radiusclient/dictionary.microsoft
INCLUDE /etc/radiusclient/dictionary.merit

Теперь рестартуем все сервисы:
invoke-rc.d freeradius restart
invoke-rc.d pptpd restart

Все, осталось разобраться с раутингом.

Ремарка: DHCP умеет раздавать не только IP, DNS и WINS, но и много другое. Например рауты.

Есть четыре способа раздавать настройки сети подключившемуся клиенту:

1) Средствами PPTP:
    a) "PPTP-server ---> PPTP-client" Жестко прописать настройки в /etc/pptpd.conf (в самом низу). Недостаток: невозможно раздать рауты.
    b) "DHCP-server ---> PPTP-server ---> PPTP-client" Транслировать DHCP изнутри сети через себя при помощи плагина ppp-dhcp и отдавать клиенту.

2) Средствами FreeRADIUS сквозь PPTP:
    a) "RADIUS-server ---> PPTP-server ---> PPTP-client". Использовать параметр Framed-Route (не путать с Framed-Routing) и Framed-Pool из RADIUS. Вот здесь даже лучше описано.
    b)  "DHCP-server ---> RADIUS-server ---> PPTP-server ---> PPTP-client". Это там какая-то экспериментальная функция есть в файле /etc/freeradius/sites-available/dhcp




О ПРОБЛЕМАХ:

если вдруг соединение не происходит, то лучше остановить freeradius и запустить его в консоли руками так, чтобы видеть вывод:
/usr/sbin/freeradius -f -X
При подключении этот вывод покажет исходные данные, с которыми к нему пришел PPTP (в самом начале портянки). Если Вы специально в подключении не указывали PAP, то по умолчанию Windows будет подключаться по MS-CHAPv2, а значит вместо пароля будет хэш. Выглядеть все должно так:
rad_recv: Access-Request packet from host 127.0.0.1 port 50403, id=24, length=149
        Service-Type = Framed-User
        Framed-Protocol = PPP
        User-Name = "macabi"
        MS-CHAP-Challenge = 0x303d80e552dc5a187485b3
        MS-CHAP2-Response = 0xf199685f80e9b176900000000000000d72e47394c5196ef0abf54e
        Calling-Station-Id = "185.24.37.32"
        NAS-IP-Address = 91.75.34.171
        NAS-Port = 0
Если вдруг секции MS-CHAP-Challenge нет (а это 99% ошибок при настройке такой связки), значит ковырять надо либо PPTP либо radiusclient, но не freeradius-сервер. Потому что freeradius ни в чем не виноват - к нему уже пришли с недостаточным количеством данных. 



Еще одна проблема:
часть сайтов открывается, часть нет, а иногда открывается только часть сайта.
Причина: при туннелировании, размер MTU должен быть меньше MTU канала. То есть не 1500, а 1400. И потому часть пакетов режется после проверки checksum. Лечится просто:
iptables -t mangle -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu







13 комментариев:

  1. А можно подробнее об пункте 2а? Не до конца понятно как пропсывать роуты, а главное - куда?.. (((

    ОтветитьУдалить
    Ответы
    1. Ну вот более менее наглядный пример есть:
      http://www.stat.ufl.edu/system/man/portmaster/RADIUS/guide/4user.html

      bob Auth-Type = System
      Service-Type = Framed-User,
      Framed-Protocol = PPP,
      Framed-IP-Address = 150.128.1.1,
      Framed-Route = "150.128.1.0 150.128.1.1 1"

      Удалить
    2. А пишется это все в users? правильно?

      если так, то вопрос: а можно такие данные как IP хранить в ldap? чтобы автоматизировать процесс.

      Удалить
    3. Да, в users (если конечно речь не идет о LDAP).

      Что касается того, как затолкать это в LDAP, а главное потом оттуда выдрать - никих идей. Вообще не уверен, что FreeRadius на такое способен.
      Но вроде как способен Radiator.
      http://en.wikipedia.org/wiki/Radiator_RADIUS_server

      Удалить
    4. Речь идет как раз об ldap авторизации... а если такая, то куда?

      Удалить
    5. Я не понял вопрос. Так нужна авторизация или выдача IP после нее из LDAP?

      Удалить
    6. перепробовал уже многие варианты... не присваивает IP клиенту хоть ты тресни(((

      rad_recv: Accounting-Request packet from host 127.0.0.1 port 60648, id=214, length=151
      Acct-Session-Id = "51FB77B7256200"
      User-Name = "testuser"
      Acct-Status-Type = Stop
      Service-Type = Framed-User
      Framed-Protocol = PPP
      Acct-Authentic = RADIUS
      Acct-Session-Time = 18
      Acct-Output-Octets = 0
      Acct-Input-Octets = 0
      Acct-Output-Packets = 0
      Acct-Input-Packets = 0
      Calling-Station-Id = "27.18.78.16"
      NAS-Port-Type = Async
      Acct-Terminate-Cause = User-Request
      Framed-IP-Address = 192.168.1.1
      NAS-IP-Address = 127.0.1.1
      NAS-Port = 0
      Acct-Delay-Time = 0

      Удалить
    7. Этот комментарий был удален автором.

      Удалить
    8. присваивается только Framed-IP-Address = 192.168.1.1

      Удалить
  2. я там выше писал:

    если вдруг соединение не происходит, то лучше остановить freeradius и запустить его в консоли руками так, чтобы видеть вывод:
    /usr/sbin/freeradius -f -X
    ====

    Тогда скорее всего ошибка вылезет и будет понятна.

    ОтветитьУдалить
    Ответы
    1. Соединение прекрасно проходит) все нормально) все авторизуется, VPN показывает что подключен, выдается IP сервера, выдается IP клиента... только IP клиента не то что мне нужно.

      А так все ок, спасибо за статью.

      Удалить
    2. Как присвоить клиенту pptpd IP через радиус та?

      Удалить