Настройка под FreeBSD 7.0 mpd5 (pptp-server) и OpenVPN

Задача: настроить VPN- и OpenVPN-сервисы. Желательно - с одним и тем же выданным нами IP конкретный пользователь может использовать как подключение через VPN, так и через OpenVPN; в связи с этим возникла необходимость в нетривиальной настройке OpenVPN-сервера, т.к. выдавать сети /30 - это макс.64 пользователя на сеть /24, что нас совершенно не устраивает.
Ещё замечание - пользователям незачем ломиться на (и вообще знать) адрес 100.100.232.17, должны использоваться адреса из сети .235.0/24

1. Пусть наш сервер имеет адрес 100.100.232.17
Вешаем на интерфейс алиас.
Разрешаем форвардинг пакетов, прописываем дефолтовый роутер

# ee /etc/rc.conf

ifconfig_fxp0="polling media 100baseTX mediaopt full-duplex"
ifconfig_fxp0="inet 100.100.232.17 netmask 255.255.255.252"
ifconfig_fxp0_alias0="100.100.235.1 netmask 255.255.255.255"
gateway_enable="YES"
defaultrouter="100.100.232.18"
named_enable="YES"

(настройка named - чуть ниже)

Прописываем DNS:

# echo "nameserver 127.0.0.1" > /etc/resolv.conf

2. Добавлем в ядро опции:

# эта опция скорее всего есть и так, но проверьте
device bpf
# ipfw - как же без него %)
# netgrapf - нужен для снятия нетфлоу-потока с сервера
options DEVICE_POLLING
options IPFIREWALL
options IPFIREWALL_NAT
options DUMMYNET
options IPFIREWALL_FORWARD
options IPFIREWALL_DEFAULT_TO_ACCEPT
options NETGRAPH
options NETGRAPH_NETFLOW
options NETGRAPH_ETHER
options NETGRAPH_TEE
options NETGRAPH_ONE2MANY
device tun
device tap
# кажется, и без if_bridge обойтись можно, но пусть будет
device if_bridge
options LIBALIAS
# recommended HZ=1000 или больше
options HZ=2000

пересобираем ядро, устанавливаем его, ребут

2. VPN

Устанавливаем mpd5 из портов.
Добавляем в /etc/rc.conf

mpd_enable="YES"

конфиги в /usr/local/etc/mpd5/:
(внимательно отслеживаем табуляцию - никаких пробелов!)

# ee /usr/local/etc/mpd5/mpd.conf

startup:
     # configure mpd users
     set user foo bar admin
     set user foo1 bar1
     # configure the console
     set console self 127.0.0.1 5005
     set console open
     # configure the web server
     set web self 127.0.0.1 5006
     set web open

default:
     load pptp_server

pptp_server:
     # Define dynamic IP address pool.
     # почему диапазон начинается не с 2, а с 3 - см.ниже в секции OpenVPN
     set ippool add pool1 100.100.235.3 100.100.235.255
     # Create clonable bundle template named B
     create bundle template B
     set iface enable proxy-arp
     set iface idle 1800
     set iface enable tcpmssfix
     set ipcp yes vjcomp
     # Specify IP address pool for dynamic assigment.
     set ipcp ranges 100.100.235.1/32 ippool pool1
     set ipcp dns 100.100.235.2
     set ipcp nbns 100.100.235.2
     # The five lines below enable Microsoft Point-to-Point encryption
     # (MPPE) using the ng_mppc(8) netgraph node type.
     # set bundle enable compression
     # set ccp yes mppc
     # set mppc yes e40
     # set mppc yes e128
     # set mppc yes stateless

     # Create clonable link template named L
     create link template L pptp
     # Set bundle template to use
     set link action bundle B
     # Multilink adds some overhead, but gives full 1500 MTU.
     set link enable multilink
     set link yes acfcomp protocomp
     set link no pap chap
     set link enable chap
     # We can use use RADIUS authentication/accounting by including
     # another config section with label 'radius'.
     # load radius
     set link keep-alive 10 60
     # We reducing link mtu to avoid GRE packet fragmentation.
     set link mtu 1460
     # Configure PPTP
     set pptp self 100.100.235.1
     # Allow to accept calls
     set link enable incoming

Логины и пароли для юзеров + привязка к IP:

# less mpd.secret

dragon "dragon" 100.100.235.50
test1 "test2"
test2 "test2" 100.100.235.8

3. OpenVPN
опять же, ставим из портов (версия 2.0.6)

Добавляем в /etc/rc.conf

openvpn_enable="YES"
openvpn_if="tap"
openvpn_configfile="/usr/local/etc/openvpn/server.conf"

О создании ключей и настройке openssl можно почитать по адресу http://senatum.blogspot.com/2008/04/openvpn-freebsd-windows.html

Конфиг OpenVPN.
Вообще-то, не рекомендуется, чтобы local был в той же подсети, что и server-bridge, но... у нас как-то всё это работает.

# ee /usr/local/etc/openvpn/server.conf
# комментарии в основном убраны
local 100.100.235.1
port 1194
proto udp
dev tap
ifconfig 100.100.235.2 255.255.255.0
ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/server.crt
key /usr/local/etc/openvpn/keys/server.key
dh /usr/local/etc/openvpn/keys/dh1024.pem
server-bridge 100.100.235.2 255.255.255.0 100.100.235.3 100.100.235.254
client-config-dir /usr/local/etc/openvpn/ccd
push "redirect-gateway"
push "dhcp-option DNS 100.100.235.2"
keepalive 10 120
#tls-auth /usr/local/etc/openvpn/keys/ta.key 0
#comp-lzo
user nobody
group nobody
persist-key
#persist-tun
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 4
mute 20

Примечание: согласно статье
http://www.mired.org/home/mwm/papers/FreeBSD-OpenVPN-Bridging.html , нужно было настраивать bridge,
но с ним у нас нифига не работало.

Индивидуальные настройки для пользователей:

# less /usr/local/etc/openvpn/ccd/test2
ifconfig-push 100.100.235.8 255.255.255.0

4. А теперь - настройки на маршрутизаторе ("основной" IP 100.100.232.33, через VLAN542 настраиваем интерфейс между роутером и нашим подопытным сервером 100.100.232.17), добавляем в /etc/rc.conf на 100.100.232.33:

ifconfig_vlan542="inet 100.100.232.18 netmask 255.255.255.252 vlan 542 vlandev fxp0"

и, естественно, там же добавляем vlan542 в список cloned_interfaces

Добавляем на маршрутизаторе маршрут на сеть 100.100.235.0

# vtysh
# conf t
(config)# ip route 100.100.235.0/24 100.100.232.17
(config)# exit
# wr
# exit

Проверяем наличие маршрута:

# netstat -rn | grep 100.100.235.0/24

   100.100.235.0/24   100.100.232.17   UG1   0   588979   vlan542

5. Настраиваем локальный DNS на нашем сервере

# ee /etc/namedb/named.conf

options {
// Relative to the chroot directory, if any
auth-nxdomain no;
allow-query { 100.100.232.0/24; 100.100.235.0/24; 127.0.0.1; };
allow-recursion { 100.100.232.0/24; 100.100.235.0/24; 127.0.0.1; };
directory "/etc/namedb";
pid-file "/var/run/named/pid";
dump-file "/var/dump/named_dump.db";
statistics-file "/var/stats/named.stats";
/*
listen-on { 127.0.0.1; };
Комментируем listen-on, чтобы named слушал на всех адресах, какие у нас будут, так как интерфейс 100.100.235.2 поднимается уже после того, как стартует named.
Для работы OpenVPN в нашей конфигурации нужно слушать 100.100.235.2, иначе у клиента нифига не резолвится: DNS-сервер его провайдера не разрешает запросы от IP из чужой для него сети 100.100.235.0/24, а резолв от 100.100.235.1 не получим потому, что маршрут на 100.100.235.1 идет через "старый" гейтвей, т.е. и в этом случае для DNS-сервера IP будет из "неразрешенного диапазона".
*/
disable-empty-zone "255.255.255.255.IN-ADDR.ARPA";
disable-empty-zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";
disable-empty-zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";

forward only;
forwarders {
100.100.232.34;
};

// query-source address * port 53;
};
// If you enable a local name server, don't forget to enter 127.0.0.1
// first in your /etc/resolv.conf so this server will be queried.
// Also, make sure to enable it in /etc/rc.conf.
// The traditional root hints mechanism. Use this, OR the slave zones below.
[.... дальше - неизмененный текст примера стандартного конфиг-файла]

К тому же, чтоб всё-таки слушать на 100.100.235.2, нам нужно, чтоб named стартовал после OpenVPN. Поэтому в /etc/rc.d/named строка REQUIRE должна выглядеть так:

# REQUIRE: SERVERS cleanvar openvpn

6. На машине пользователя user2 настраиваем openvpn как клиент:

# ee cat /usr/local/etc/openvpn/user2.conf

client
dev tap
proto udp
remote 100.100.235.1
nobind
verb 4
ca /usr/local/etc/openvpn/ca.crt
cert /usr/local/etc/openvpn/user2.crt
key /usr/local/etc/openvpn/user2.key
port 1194
persist-key
#tls-client
#tls-auth /usr/local/etc/openvpn/ta.key 1
#cipher BF-CBC
#ns-cert-type server

запускаем:
# kldload if_tap
# openvpn --config /usr/local/etc/openvpn/user2.conf

Под Linux и FreeBSD есть особенность - клиент не получает адрес DNS от сервера.
Поэтому мы или добавляем ручками в /etc/resolv.conf
"nameserver 100.100.235.2"
или же (для Linux) применяем этот рецепт: http://www.phocean.net/2006/12/07/openvpn-and-dns-on-a-linux-client.html (для opensuse 11 нужное ищем в директории /usr/share/doc/packages/openvpn/contrib/pull-resolv-conf).

Проверить, какой теперь у нас IP адрес:
http://2ip.ru

Смотрим таблицу маршрутизации на клиентской машине:

# netstat -rn

Routing tables

Internet:
Destination Gateway Flags Refs Use Netif Expire
default        100.100.235.2    UGS    0    122553    tap0
10.0.0.0/24    link#1            UC    0    0    rl0    
10.0.0.1        00:02:44:b8:28:70    UHLW    2    454    rl0    9
100.100.235.0/24    link#3    UC    0    0    tap0
100.100.235.1/32    10.0.0.1    UGS    0    122647    rl0
100.100.235.2    00:bd:70:b8:c4:00    UHLW    2    0    tap0    1199
127.0.0.1        127.0.0.1    UH    0    4    lo0    
# ifconfig
rl0: flags=8843<up,broadcast,running,simplex,multicast> metric 0 mtu 1500
options=8<vlan_mtu>
ether 00:00:1c:d6:27:5d
inet 10.0.0.194 netmask 0xffffff00 broadcast 10.0.0.255
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
lo0: flags=8049<up,loopback,running,multicast> metric 0 mtu 16384
inet 127.0.0.1 netmask 0xff000000
tap0: flags=8843<up,broadcast,running,simplex,multicast> metric 0 mtu 1500
ether 00:bd:7d:98:cf:00
inet 100.100.235.8 netmask 0xffffff00 broadcast 100.100.235.255
Opened by PID 1929

Просмотреть, через какой интерфейс идёт пакет на заданный нами IP:

# route get 195.214.195.105

route to: 195.214.195.105
destination: default
mask: default
gateway: 100.100.235.2
interface: tap0
flags: <up,gateway,done,static>
recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
0        0        0        0        0      0        1500     0

P.S. Это не я такое умное - всё это хозяйство работать так, как нам надо, заставил Embar.