VPN-сервер (pptpd/xl2tpd+mysql+radius) на CentOS 6

Здесь я постараюсь описать процесс установки и настройки VPN-сервера на CentOS6 с пользователями в MySQL и авторизацией через radius по chap для xl2tpd и для шифрованного соединения по ms-chap-v2 и mppe для pptpd.

Дано

Виртуальная машина на KVM со свежеустановленной CentOS6 x86_64 minimal.

Задача

1. Установить и настроить в связке pptpd/xl2tpd, freeradius2, radiusclient-ng и mysql.
2. Создать 2-х клиентов для подключения к настроенному VPN-серверу, с выходом в нет через NAT. Один клиент с динамическим получением адреса, второй с постоянным IP.
3. Перенести pool адресов для раздачи динамическим клиентам из pptpd в radius.

Решение

Первым делом необходимо установить все необходимые пакеты. radiusclient-ng, pptpd и xl2tpd нет в стандартных репозиториях, поэтому для radiusclient-ng и xl2tpd мы подключим EPEL-репозиторий, а pptpd-пакет скачаем напрямую.

# rpm -Uhv http://fedora-epel.mirror.lstn.net/6/x86_64/epel-release-6-5.noarch.rpm
# yum install freeradius freeradius-mysql xl2tpd radiusclient-ng radiusclient-ng-utils freeradius-utils mysql mysql-devel mysql-server
# rpm -Uhv http://poptop.sourceforge.net/yum/stable/packages/pptpd-1.3.4-2.el6.x86_64.rpm

далее настроим mysql и зададим пароль:

# mysql_secure_installation

Собственно, перейдем к настройке pptpd. Приводим файлы настройки к следующему виду:

# cat /etc/pptpd.conf
option /etc/ppp/options.pptpd
logwtmp
localip 192.168.80.1
remoteip 192.168.80.5-35

# cat /etc/ppp/options.pptpd
name pptpd
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
proxyarp
ms-dns 8.8.8.8
ms-dns 8.8.4.4
lock
nobsdcomp
novj
novjccomp
nologfd
lcp-echo-failure 30
lcp-echo-interval 5
ipcp-accept-local
ipcp-accept-remote
plugin radius.so
plugin radattr.so

если решили использовать не pptpd , а xl2tpd, то файлы будут иметь следующий вид:

# cat /etc/xl2tpd/xl2tpd.conf
[global]
port = 1701
auth file = /etc/xl2tpd/l2tp-secrets
access control = no
rand source = dev
[lns default]
exclusive = no
ip range = 192.168.80.5-192.168.81.35
local ip = 192.168.80.1
require chap = yes
refuse pap = yes
require authentication = yes
name = VPNserver
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
flow bit = yes

# cat /etc/ppp/options.xl2tpd
ipcp-accept-local
ipcp-accept-remote
lcp-echo-failure 30
lcp-echo-interval 5
ms-dns 8.8.8.8
ms-dns 8.8.4.4
noccp
nodeflate
auth
crtscts
idle 1800
mtu 1410
mru 1410
defaultroute
debug
proxyarp
connect-delay 5000
lock
plugin radius.so
plugin radattr.so

с pptpd/xl2tpd закончено, переходим к настройке radiusclient-ng:
Первая проблема с которой мы столкнулись, это нежелание pptpd работать с radiusclient-ng из-за путей куда он установлен, поэтому создаем софт-линк следующим образом

# ln -s /etc/radiusclient-ng /etc/radiusclient

и закоментируем в файле /etc/radiusclient-ng/radiusclient.conf строчку

#bindaddr *

иначе ругается на неизвестный параметр.
редактируем /etc/radiusclient-ng/servers , добавляем локальный radius-сервер, к которому будет обращаться клиент

localhost YouRsUpErpAAs

Вторая проблема, с которой нам пришлось столкнуться, это отсутствие в пакете radiusclient-ng атрибутов от mircosoft, после гугления, необходимые артибуты были найдены. Копируем имеющиеся файлы с атрибутами из /usr/share/radiusclient-ng/ в /etc/radiusclient-ng/

cp /usr/share/radiusclient-ng/diction* /etc/radiusclient-ng/

в /etc/radiusclient-ng/ создаем файл dictionary.microsoft со следующим содержимым:

VENDOR          Microsoft       311     Microsoft

ATTRIBUTE       MS-CHAP-Response        1       string  Microsoft
ATTRIBUTE       MS-CHAP-Error           2       string  Microsoft
ATTRIBUTE       MS-CHAP-CPW-1           3       string  Microsoft
ATTRIBUTE       MS-CHAP-CPW-2           4       string  Microsoft
ATTRIBUTE       MS-CHAP-LM-Enc-PW       5       string  Microsoft
ATTRIBUTE       MS-CHAP-NT-Enc-PW       6       string  Microsoft
ATTRIBUTE       MS-MPPE-Encryption-Policy 7     string  Microsoft
ATTRIBUTE       MS-MPPE-Encryption-Type 8       string  Microsoft
ATTRIBUTE       MS-MPPE-Encryption-Types  8     string  Microsoft
ATTRIBUTE       MS-RAS-Vendor           9       integer Microsoft
ATTRIBUTE       MS-CHAP-Domain          10      string  Microsoft
ATTRIBUTE       MS-CHAP-Challenge       11      string  Microsoft
ATTRIBUTE       MS-CHAP-MPPE-Keys       12      string  Microsoft
ATTRIBUTE       MS-BAP-Usage            13      integer Microsoft
ATTRIBUTE       MS-Link-Utilization-Threshold 14 integer        Microsoft
ATTRIBUTE       MS-Link-Drop-Time-Limit 15      integer Microsoft
ATTRIBUTE       MS-MPPE-Send-Key        16      string  Microsoft
ATTRIBUTE       MS-MPPE-Recv-Key        17      string  Microsoft
ATTRIBUTE       MS-RAS-Version          18      string  Microsoft
ATTRIBUTE       MS-Old-ARAP-Password    19      string  Microsoft
ATTRIBUTE       MS-New-ARAP-Password    20      string  Microsoft
ATTRIBUTE       MS-ARAP-PW-Change-Reason 21     integer Microsoft
ATTRIBUTE       MS-Filter               22      string  Microsoft
ATTRIBUTE       MS-Acct-Auth-Type       23      integer Microsoft
ATTRIBUTE       MS-Acct-EAP-Type        24      integer Microsoft
ATTRIBUTE       MS-CHAP2-Response       25      string  Microsoft
ATTRIBUTE       MS-CHAP2-Success        26      string  Microsoft
ATTRIBUTE       MS-CHAP2-CPW            27      string  Microsoft
ATTRIBUTE       MS-Primary-DNS-Server   28      ipaddr  Microsoft
ATTRIBUTE       MS-Secondary-DNS-Server 29      ipaddr  Microsoft
ATTRIBUTE       MS-Primary-NBNS-Server  30      ipaddr  Microsoft
ATTRIBUTE       MS-Secondary-NBNS-Server 31     ipaddr  Microsoft
VALUE           MS-BAP-Usage            Not-Allowed     0
VALUE           MS-BAP-Usage            Allowed         1
VALUE           MS-BAP-Usage            Required        2
VALUE   MS-ARAP-PW-Change-Reason        Just-Change-Password            1
VALUE   MS-ARAP-PW-Change-Reason        Expired-Password                2
VALUE   MS-ARAP-PW-Change-Reason        Admin-Requires-Password-Change  3
VALUE   MS-ARAP-PW-Change-Reason        Password-Too-Short              4
VALUE           MS-Acct-Auth-Type       PAP             1
VALUE           MS-Acct-Auth-Type       CHAP            2
VALUE           MS-Acct-Auth-Type       MS-CHAP-1       3
VALUE           MS-Acct-Auth-Type       MS-CHAP-2       4
VALUE           MS-Acct-Auth-Type       EAP             5
VALUE           MS-Acct-EAP-Type        MD5             4
VALUE           MS-Acct-EAP-Type        OTP             5
VALUE           MS-Acct-EAP-Type        Generic-Token-Card      6
VALUE           MS-Acct-EAP-Type        TLS             13

редактируем файл /etc/radiusclient-ng/radiusclient.conf на предмет

dictionary /etc/radiusclient-ng/dictionary

редактируем файл /etc/radiusclient-ng/dictionary , добавляя в конец

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

с клиентом тоже закончили, переходим к настройке mysql:
пакет freeradius-mysql содержит необходимые файлы для импорта их в mysql, находятся они в /etc/raddb/sql/mysql/
подредактируем файл admin.sql , что бы задать пароль отличный от стандартного

vim admin.sql
:%s/radpass/radpass235/g
:wq

подключаемся к mysql, создаем DB, импортируем таблицы и создаем пользователей

mysql -p
mysql> create database radius;
mysql> \. admin.sql
mysql> use radius;
mysql> \. schema.sql

далее создаем пользователей и их настройки

mysql> INSERT INTO radusergroup (username,groupname) values ('user1','static-ip-vpn');
mysql> INSERT INTO radusergroup (username,groupname) values ('user2','dinamic-ip-vpn');

должно получится следующее

mysql> select * from radusergroup;

+----------+----------------+----------+
| username |   groupname    | priority |
+----------+----------------+----------+
| user1    | static-ip-vpn  | 1        |
| user2    | dinamic-ip-vpn | 1        |
+----------+----------------+----------+

mysql> INSERT INTO radcheck (username,attribute,op,value) values ('user1','User-Password','==','pass1');
mysql> INSERT INTO radcheck (username,attribute,op,value) values ('user2','User-Password','==','pass2');

mysql> select * from radcheck;

+----+----------+---------------+----+-------+
| id | username | attribute     | op | value |
+----+----------+---------------+----+-------+
|  1 | user1    | User-Password | == | pass1 |
|  2 | user2    | User-Password | == | pass2 |
+----+----------+---------------+----+-------+

заполняем таблицу radgroupreply

mysql> INSERT INTO radgroupreply (groupname, attribute, op, value) values ('dinamic-ip-vpn','Service-Type',':=','Framed-User');

и так далее, чтоб получить следующее

mysql> select * from radgroupreply;

+----+----------------+--------------------+----+---------------------+
| id | groupname      | attribute          | op | value               |
+----+----------------+--------------------+----+---------------------+
|  1 | dinamic-ip-vpn | Service-Type       | := | Framed-User         |
|  2 | dinamic-ip-vpn | Framed-Protocol    | := | PPP                 |
|  3 | dinamic-ip-vpn | Framed-Compression | := | Van-Jacobsen-TCP-IP |
|  4 | static-ip-vpn  | Framed-Compression | := | Van-Jacobsen-TCP-IP |
|  5 | static-ip-vpn  | Framed-Protocol    | := | PPP                 |
|  6 | static-ip-vpn  | Service-Type       | := | Framed-User         |
+----+----------------+--------------------+----+---------------------+

заполняем таблицу radreply чтобы задать постоянный ip для первого клиента user1

mysql> INSERT INTO radreply (username, attribute, op, value) values ('user1','Framed-IP-Netmask',':=','255.255.255.255');
mysql> INSERT INTO radreply (username, attribute, op, value) values ('user1','Framed-IP-Address',':=','192.168.80.90');
mysql> select * from radreply;

+----+----------+-------------------+----+-----------------+
| id | username |     attribute     | op |     value       |
+----+----------+-------------------+----+-----------------+
| 1  | user1    | Framed-IP-Netmask | := | 255.255.255.255 |
| 2  | user1    | Framed-IP-Address | := | 192.168.80.90   |
+----+----------+-------------------+----+-----------------+

В итоге, мы занесли в базу данный 2-х клиентов, user1 с паролем pass1 и статическим ip — 192.168.80.90, и user2 с паролем pass2 и получением динамического ip из пула указанного в настройках pptpd. Здесь намеренно пользователи разнесены по группам, с учетом дальшейшего увеличения клиентов, можно было просто создать все атрибуты для обоих клиентов в таблице radreply, но при большом количестве клиентов, удобнее использовать группы, где указываются одинаковые для клиентов группы атрибуты. Так же, в группах можно указывать разные пулы адресов и еще многое другое, но об этом сейчас не будем.

Переходим к настрокам radius. Здесь я приведу примеры файлов, в которых производились изменения:

/etc/raddb/clients.conf
client 127.0.0.1 {
secret = YouRsUpErpAAs
shortname = localhost
nastype = other
}

Третья проблема, на момент отладки, когда еще radius не был подключен к mysql, столкнулись с тем, что если в файле /etc/raddb/users , если клиенты оказывались прописанными не в начале файла, ничего не работало.

/etc/raddb/users
DEFAULT Simultaneous-Use := 1
Fall-Through = 1

Это необходимо прописать, чтоб не было нескольких подключений с одним и тем же логином одновременно

/etc/raddb/radiusd.conf
в секции modules уберем комментарии с

$INCLUDE sql.conf

/etc/raddb/sql.conf
прописываем данные для подключения к mysql

password = "radpass235"

/etc/raddb/sites-enabled/default
в секциях authorize, session, post-auth и accounting включаем sql
в секции authorize включаем mschap

/etc/raddb/modules/mschap
mschap {
use_mppe = yes
require_encryption = yes
require_strong = yes
}

Пожалуй, задача практически решена, остались некоторые штрихи:

Настроить iptables и разрешить форвард, чтоб выпустить клиентов в мир

iptables -I INPUT -p gre -j ACCEPT
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 1723 -j ACCEPT
iptables -I INPUT -p udp --dport 1701 -j ACCEPT
iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -s 192.168.80.0/24 -o eth0 -j ACCEPT
iptables -I FORWARD -d 192.168.80.0/24 -i eth0 -j ACCEPT
iptables -t nat -I POSTROUTING -s 192.168.80.0/24 -o eth0 -j MASQUERADE

/etc/sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p

Уже на данной стадии, если мы запустим установленные сервисы, мы сможем подключится к нашей машине по vpn, осталось только перенести пул адресов выдаваемых динамическим клиентам из pptpd в radius. Для этого есть несколько вариантов, вплоть до помещения пула в mysql. Мы используем простой вариант.

/etc/raddb/modules/ippool
в секции ippool main_pool , делаем правки для своего пула адресов

range-start = 192.168.80.35
range-stop = 192.168.80.65

в файле /etc/raddb/sites-enabled/default добавляем с соответствующие секции

accounting {
main_pool
}

post-auth {
main_pool
}

далее, создаем файлы, где пул будет храниться

touch /etc/raddb/db.ipindex /etc/raddb/db.ippool
chmod 664 /etc/raddb/db.ipindex /etc/raddb/db.ippool
chown root:radiusd /etc/raddb/db.ipindex /etc/raddb/db.ippool

и добавляем в /etc/raddb/users

DEFAULT Pool-Name := main_pool
Fall-Through = Yes

перезапускаем radius, и пробуем подключится к машине по vpn, все должно работать. Подробную статистику подключений мы можем увидеть в таблице radius.radacct
выделенные адреса из пула, можно посмотреть командой

rlm_ippool_tool -av /etc/raddbdb/db.ippool /etc/raddbdb/db.ipindex

Можно также одновременно использовать и pptpd и xl2tp. И если мы хотим разделить клиентов, мы можем добавить атрибуты, и в MySQL сделать соответствие группам, на основании этих атрибутов, например:
в /etc/ppp/options.pptpd

avpair Connect-Info=pptp

а в /etc/ppp/options.xl2tpd

avpair Connect-Info=l2tp

Соответственно, при запросе к радиусу эти атрибуты будут посланы. Останется только сделать проверку в radcheck таблице, если для конкретного клиента, или в radgroupcheck, если для группы.

IPSec

Вы наверняка захотите прикрутить IPSec к соединению l2tp, ниже представлен один из самых простых вариантов:

В файл /etc/xl2tpd/xl2tpd.conf добавляем в секцию

[global]
ipsec saref = yes

Устанавливаем ipsec-tools

# yum -y install http://wiki.nikoforge.org/download/ipsec-tools/ipsec-tools-0.8.0-3defpsk.el6.x86_64.rpm

Создаем файл /etc/racoon/init.sh

#!/bin/sh
echo -e "flush;\n\
spdflush;\n\
spdadd 0.0.0.0/0[0] 0.0.0.0/0[1701] udp -P in ipsec esp/transport//require;\n\
spdadd 0.0.0.0/0[1701] 0.0.0.0/0[0] udp -P out ipsec esp/transport//require;\n"\
| setkey -c

Устанавливаем на него права

# chmod 750 /etc/racoon/init.sh

И добавляем его старт в /etc/rc.d/rc.local

echo /etc/racoon/init.sh >> /etc/rc.d/rc.local

Создаем файл /etc/racoon/racoon.conf , сохранив старый, если необходимо.

path include "/etc/racoon";
path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/etc/racoon/certs";
path script "/etc/racoon/scripts";
remote anonymous
{
exchange_mode aggressive,main;
passive on;
proposal_check obey;
support_proxy on;
nat_traversal on;
ike_frag on;
dpd_delay 20;
proposal
{
encryption_algorithm aes;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group modp1024;
}
proposal
{
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group modp1024;
}
}
sainfo anonymous
{
encryption_algorithm aes,3des;
authentication_algorithm hmac_sha1;
compression_algorithm deflate;
pfs_group modp1024;
}

Выставляем права на него

chmod 600 /etc/racoon/racoon.conf

Редактируем /etc/racoon/psk.txt , добавляем pre-shared-key

* sUpErkEyPresHared56

Запускаем все ёто дело и рестартим xl2tpd

service racoon start
chkconfig racoon on
/etc/racoon/init.sh
service xl2tpd restart

Вот и все.

Удачи в настройках.
© shadow_alone

вот здесь перевели этот мануал на English.