Ключевые слова:freebsd, vpn, mpd, limit, traffic, pf, firewall, (найти похожие документы)
From: Vit <artemrts@ukr.net.>
Newsgroups: email
Date: Mon, 15 Jul 2009 14:31:37 +0000 (UTC)
Subject: Раздача Интернета через VPN (mpd) с ограничением траффика по пользователям средствами PF
В этой статье хочу описать как я настроил vpn-сервер для раздачи Инета
на базе mpd5.3 в связке с пакетным фильтром PF с ограничением трафика.
Почему именно такая конструкция? Просто мне необходимо было решение
раздачи интернета пользователям с шифрованием, и плюс ограничивать и
приоретизировать трафик дабы всем хватало. Можно было использовать
функции mpd для "нарезки" канала, но мне не хотелось заморачиваться с
радиусом и т.д. Поэтому было принято решение строить из того з чем умею
работать :-). В PF будем использовать такие фичи как anchors и Packet
Tagging (Policy Filtering).
Разжевывать каждый параметр не буду, поэтому читающий должен иметь некий
опыт работы в сетевом администрировании в общем и во FreeBSD в
частности.
Настройка vpn будет показана на примере виртуальной машины на базе
VMWare, на которой я всю эту систему отрабатывал.
Имеем:
Inet <---- 10.0.10.182/16:le0 [FreeBSD VPN-server] le1:172.16.1.1/24<-------------->LAN
ng0:192.168.1.1<------------>192.168.1.2
ng1:192.168.1.1<------------>192.168.2.3
......
OS: FreeBSD 7.2-RELEASE
LAN: 172.16.1.0/24
External IP:10.0.10.182/16
IP адреса, которые будут назначаться vpn-клиентам: 192.168.1.2, 192.168.1.3
1. Подготовка системы
1.1 Перед обновлением дабы удобнее было работать установим МС:
pkg_add -r mc-lite
Так же необходимо запустить DNS-сервер и "повесить" его на внутренний
интерфейс. Объяснение как это сделать выходят за рамки статьи.
1.2. Обновляем исходники, как это сделать - читаем handbook.
1.3. Далее создаем файл /etc/src.conf и исключаем все, что не требуется
для работы сервера.
WITHOUT_ATM=true
WITHOUT_BLUETOOTH=true
WITHOUT_GAMES=true
WITHOUT_I4B=true
WITHOUT_INET6=true
WITHOUT_INET6_SUPPORT=true
WITHOUT_IPFILTER=true
WITHOUT_PROFILE=true
WITHOUT_USB=true
WITHOUT_ZFS=true
WITHOUT_IPX=true
WITHOUT_IPX_SUPPORT=true
WITHOUT_LPR=true
WITHOUT_NCP=true
WITHOUT_RCMDS=true
WITHOUT_RCS=true
WITHOUT_HTML=true
WITHOUT_SENDMAIL=true
1.4. Далее правим /etc/make.conf
Здесь я приведу только то, что изменял в этом файле, комментарии удалены.
CPUTYPE?=pentium4
CFLAGS= -O2 -fno-strict-aliasing -pipe
CXXFLAGS+= -fconserve-space
MAKE_SHELL=sh
COPTFLAGS= -O2 -pipe
BOOT_COMCONSOLE_SPEED= 115200
PERL_VERSION=5.8.9
WANT_FORCE_OPTIMIZATION_DOWNGRADE=1
1.5. Для бересборки ядра редактируем GENERIC. Его я переименовал в MYGENERIC1.
Понятное дело, что каждый сам должен править конфиг под свое железо, я приведу
только то что необходимо для работы.
Закоментируем следующие строчки:
#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
#options INET6 # IPv6 communications protocols
#options SCTP # Stream Control Transmission Protocol
#options NFSCLIENT # Network Filesystem Client
#options NFSSERVER # Network Filesystem Server
#options NFSLOCKD # Network Lock Manager
#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
И добавим:
### for mpd
options NETGRAPH
options NETGRAPH_BPF
options NETGRAPH_IFACE
options NETGRAPH_KSOCKET
options NETGRAPH_MPPC_ENCRYPTION
options NETGRAPH_MPPC_COMPRESSION
options NETGRAPH_PPP
options NETGRAPH_PPTPGRE
options NETGRAPH_SOCKET
options NETGRAPH_TCPMSS
options NETGRAPH_VJC
options NETGRAPH_ETHER
options NETGRAPH_TEE
options NETGRAPH_ONE2MANY
options NETGRAPH_NETFLOW
### for PF
device pf
device pflog
#device pfsync
#device carp
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_CDNR
options ALTQ_PRIQ
options ALTQ_NOPCC
### others
options IPSTEALTH
В базовую систему не включен код MPPC compression, поэтому нужно его добавить.
Сам код и инструкция что куда копировать находятся на сайте http://www.mavhome.dp.ua/MPPC/
1.6. Далее делаем пересборку мира и ядра.
Из /usr/src/makefile:
# 1. 'd /usr/src' (or to the directory containing your source tree).
# 2. 'make buildworld'
# 3. 'make buildkernel KERNCONF=YOUR_KERNEL_HERE' (default is GENERIC).
# 4. 'make installkernel KERNCONF=YOUR_KERNEL_HERE' (default is GENERIC).
# [steps 3. & 4. can be combined by using the "kernel" target]
# 5. 'reboot' (in single user mode: boot -s from the loader prompt).
# 6. 'mergemaster -p'
# 7. 'make installworld'
# 8. 'make delete-old'
# 9. 'mergemaster' (you may wish to use -U or -ai).
# 10. 'reboot'
# 11. 'make delete-old-libs' (in case no 3rd party program uses them anymore)
Лично я последний пункт не делал.
Если все прошло успешно, получаем:
FreeBSD gw1.local 7.2-RELEASE-p2 FreeBSD 7.2-RELEASE-p2 #3: Mon Jul 6 16:28:52 EEST 2009
root@gw1.local:/usr/obj/usr/src/sys/MYGENERIC1 i386
Более подробно про обновление системы смотрим здесь2. Устанвливаем MPD
Ставим из портов.
cd /usr/ports/net/mpd5
make
make install clean
Нам понадобиться 2 конфига в /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 172.16.1.1 5006
#set web open
#
default:
load pptp_server
pptp_server:
set ippool add pool1 192.168.1.2 192.168.1.10
# Create clonable bundle template named B
create bundle template B
set iface up-script /usr/local/etc/mpd5/if-up.sh
set iface down-script /usr/local/etc/mpd5/if-down.sh
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 192.168.1.1/32 ippool pool1
set ipcp dns 172.16.1.1
# The five lines below enable Microsoft Point-to-Point encryption
# (MPPE) using the ng_mppc(8) netgraph node type.
set bundle enable compression
set bundle enable crypt-reqd
set ccp yes mppc
set mppc yes compress e40 e56 e128 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 disable pap chap eap
set link enable chap chap-msv1 chap-msv2 chap-md5
# 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
set link mru 1460
# Configure PPTP
set pptp self 172.16.1.1
# Allow to accept calls
set pptp disable windowing
set link enable incoming
б) mpd.secret
test1 "test1" 192.168.1.2
test2 "test2" 192.168.1.3
в) Скрипты, которые будут запускаться при старте и шатдауне интерфейсов ng
if-up.sh
#!/bin/sh
echo "nat on le0 tag from_$4 tagged from_$4 -> le0" | pfctl -a mpd-nat/$4 -f -;
echo "pass out quick on le0 inet tagged from_$4 queue $4_up" | pfctl -a ext_if-out/$4 -f -;
echo "pass in quick on $1 inet from $1:peer $4 to any tag from_$4 queue $4_down" | pfctl -a ng-in/$4 -f -;
if-down.sh
#!/bin/sh
pfctl -a mpd-nat/$4 -F all;
pfctl -a ext_if-out/$4 -F all;
pfctl -a ng-in/$4 -F all;
Пояснения: $1 - обозначает интерфейс (ng0, ng1, ...)
$4 - IP-адрес, выдаваемый клиенту.
Скрипт if-up.sh будет добавлять правило для NATa, назначать нужную нам
очередь на внешнем интерфейсе и назначать тег и очередь на внутреннем.
Скрипт if-down.sh удаляет все правила, кроме самих очередей.
3. Настройка PF
3.1. Добавляем запись в /etc/rc.conf
pf_enable="YES"
pflog_enable="YES"
3.2. Создаем файл /etc/pf.conf с таким содержанием
ext_if="le0"
int_if="le1"
lan="172.16.1.0/24"
pc1="172.16.1.2"
pc2="172.16.1.3"
set skip on lo
set loginterface le0
set ruleset-optimization basic
set block-policy return
set limit { states 20000 frags 20000 }
set timeout {adaptive.start 15000 adaptive.end 45000}
set state-policy if-bound
scrub on $ext_if all random-id min-ttl 128 reassemble tcp fragment reassemble
scrub on $int_if all
### ALTQ
altq on $int_if cbq bandwidth 100Mb qlimit 50 queue { def_download }
queue def_download bandwidth 100% cbq(default) {192.168.1.2_down,192.168.1.3_down, ...}
queue 192.168.1.2_down bandwidth 512Kb cbq(ecn)
queue 192.168.1.3_down bandwidth 1024Kb cbq(ecn)
......
altq on $ext_if cbq bandwidth 10Mb qlimit 50 queue { def_upload }
queue def_upload bandwidth 100% cbq(default) {192.168.1.2_up,192.168.1.3_up, ...}
queue 192.168.1.2_up bandwidth 128Kb cbq(ecn)
queue 192.168.1.3_up bandwidth 128Kb cbq(ecn)
......
### NAT
nat-anchor "mpd-nat/*"
### RULES
block in
block out
antispoof quick for { lo $int_if } inet
### EXT_IF_OUT
anchor "ext_if-out/*"
pass out quick on $ext_if inet proto {tcp udp} from $ext_if to any port 53
### EXT_IF_IN
pass in quick on $ext_if inet proto tcp from any to $ext_if port ssh synproxy state
### INT_IF_IN
anchor "ng-in/*"
pass in quick on $int_if inet proto {tcp udp} from $lan to $int_if port {53 1723}
### INT_IF_OUT
pass out quick on $int_if inet proto gre from $int_if to $lan
### THE END
4. И на последок немного тюнинга
### secur
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_proc_debug=0
security.bsd.conservative_signals=0
net.inet.ip.portrange.first=1025
net.inet.ip.portrange.last=65535
net.inet.ip.ttl=128
net.inet.ip.stealth=1
net.inet.ip.forwarding=1
net.inet.ip.check_interface=1
net.inet.ip.random_id=1
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
net.inet.icmp.maskfake=1
net.inet.ip.redirect=0
### inet
kern.ipc.maxsockbuf=1048576 #default 262144
kern.ipc.somaxconn=1024 #deault 128
net.inet.tcp.sendspace=65536
net.inet.tcp.recvspace=65536
net.inet.tcp.sendbuf_max=1048576 #default 262144
net.inet.tcp.recvbuf_max=1048576 #default 262144
net.local.stream.sendspace=65536
net.local.stream.recvspace=65536
net.inet.ip.intr_queue_maxlen=4096
net.inet.tcp.nolocaltimewait=1
Для работы системы необходимо записать Логин\Пароль и назначаемый
клиенту IP-адрес в mpd.secret. В файле pf.conf сразу надо забить очереди
с нужными ограничениями для даного IP-адреса.
5. Проверяем, что получилось.
5.1. Нам понадобиться утилита pftop. Устанавливаем, как всегда, из портов:
cd /usr/ports/sysutils/pftop
make
make install clean
rehash
Подключимся с первого ПК (172.16.1.2)
Вывод ifconfig:
ng0: flags=88d1<UP,POINTOPOINT,RUNNING,NOARP,SIMPLEX,MULTICAST> metric 0 mtu 1218
inet 192.168.1.1 --> 192.168.1.2 netmask 0xffffffff
Вывод команды pfctl -sq:
queue root_le1 on le1 bandwidth 10Mb priority 0 cbq( wrr root ) {def_download}
queue def_download on le1 bandwidth 10Mb cbq( default ) {192.168.1.2_down, 192.168.1.3_down}
queue 192.168.1.2_down on le1 bandwidth 512Kb cbq( red ecn )
queue 192.168.1.3_down on le1 bandwidth 1.02Mb cbq( red ecn )
queue root_le0 on le0 bandwidth 10Mb priority 0 cbq( wrr root ) {def_upload}
queue def_upload on le0 bandwidth 10Mb cbq( default ) {192.168.1.2_up, 192.168.1.3_up}
queue 192.168.1.2_up on le0 bandwidth 256Kb cbq( red ecn )
queue 192.168.1.3_up on le0 bandwidth 256Kb cbq( red ecn )
Смотрим состояние очередей в pftop:
Клиент закачивает. Видно, что скорость ограничивается 512Кбитами
pfTop: Up Queue 1-8/8, View: queue, Cache: 10000 11:30:33
QUEUE BW SCH PR PKTS BYTES DROP_P DROP_B QLEN BORR SUSP P/S B/S
root_le1 10M cbq 0 4829 3853K 0 0 0 0 0 109 63K
def_download 10M cbq 31 1522 0 0 0 0 0 1.0 72
192.168.1.2_do 512K cbq 4798 3851K 44 36483 6 0 1207 108 63K <--
192.168.1.3_do 1024K cbq 0 0 0 0 0 0 0 0 0
root_le0 10M cbq 0 2841 173K 0 0 0 0 0 63 3821
def_upload 10M cbq 86 22388 0 0 0 0 0 1.0 245
192.168.1.2_up 256K cbq 2755 151K 0 0 0 0 0 62 3575
192.168.1.3_up 256K cbq 0 0 0 0 0 0 0 0 0
Клиент закачивает, скорость ограничивается 256Кбитами.
pfTop: Up Queue 1-8/8, View: queue, Cache: 10000 11:32:31
QUEUE BW SCH PR PKTS BYTES DROP_P DROP_B QLEN BORR SUSP P/S B/S
root_le1 10M cbq 0 577 45074 0 0 0 0 0 29 2198
def_download 10M cbq 198 9136 0 0 0 0 0 10 497
192.168.1.2_do 512K cbq 379 35938 0 0 0 0 0 18 1700
192.168.1.3_do 1024K cbq 0 0 0 0 0 0 0 0 0
root_le0 10M cbq 0 665 561K 0 0 0 0 0 37 30K
def_upload 10M cbq 37 17882 0 0 0 0 0 1.0 277
192.168.1.2_up 256K cbq 628 544K 9 6834 9 0 150 36 30K <--
192.168.1.3_up 256K cbq 0 0 0 0 0 0 0 0 0
Ниже приведу результаты вывода команды pfctl, демонстрирующие, что
правила для NAT и фильтрации загрузились правильно с помощью якорей.
pfctl -a ext_if-out/192.168.1.2 -sr
pass out quick on le0 inet all flags S/SA keep state queue 192.168.1.2_up tagged from_192.168.1.2
pfctl -a mpd-nat/192.168.1.2 -sn
nat on le0 inet all tag from_192.168.1.2 tagged from_192.168.1.2 -> 10.0.10.182
pfctl -a ng-in/192.168.1.2 -sr
pass in quick on ng0 inet from 192.168.1.2 to any flags S/SA keep state queue 192.168.1.2_down tag from_192.168.1.2
После того, как клиент отключился, все правила удаляются.
6. Выводы.
Какие вижу минусы?
Необходимость прописывать в конфиге pf.conf очереди для всех
пользователей, и они не дожны удаляться. Тоже касается и mpd.secret.
Думаю написать скриптик, запустив который, будет запрашиваться IP-адрес,
ширина канала, логин\пароль и назначаемый mpd IP-адрес, а далее скрипт
будет записывать введенные данные в соответствующие места
конфиграционных файлов.
При большом кол-ве пользователей большое кол-во правил для фаервола, что
может снизить производительность.
Уважаемый ононим. Я Вам поясню.
Во-первых данная статья предполагает, что читающий имеет некий опыт работы с данной ОС и прочитал перед этим хендбук. А те параметры make.conf, что я указал не привязаны к конкретному железу.
>1. Генерик мы не редактируем.
нет, именно генерик, переименованный в MYGENERIC1 мы и редактируем
>2. Закомментированные строчки _нужны_ для работы? Что за бред? Зачем опять же частную >реализацию выдавать за "необходимо для работы"? Без отключения INET6 или NFS оно работать >не будет?
Вы какой-то странный. Почему частная реализация? Скажите, зачем IPv6 в реализации с нат??? Или NFS на пограничном фаерволле? Я же не показывал какие сетевые девайсы закомментировать в конфиге.
Вы, извините, сколько дней админите?
Хочу queue anchor и правила в стиле "каждой твари - по харе", a-la "queue XYZ bandwidth 1Mb cbq(ecn each32)" (чтобы каждому хосту давалось по 1Mb) или "queue SDF bandwidth 8Mb cbq(ecn each24)" (чтобы каждой подсети с маской 24 бита давалось по 8Mb)
sРРРРРРРРРррррррр блин ну чё я не так делаю у мя всё вроде маркирует норм но всеравно в очередях которых я прописал не режит трафик всеравно забирает всю полосу
Журнал "Linux Format" (Линукс Формат)- Единственный в России и странах СНГ журнал на русском языке,
посвящённый Linux и свободному ПО. Журнал для IT-директоров, IT-менеджеров, программистов, системных
администраторов, учителей школ и преподавателей ВУЗов и всех пользователей ПК. В каждом выпуске: Новости
индустрии OpenSource, обзоры новинок свободного ПО, обучающие и методические статьи.
Каждый, кто оформит подписку, получает бонус- объёмные наклейки на системный блок и подарки: с одним из
первых выпусков журнала в 2012 году- диск с архивом номеров за 2005-2011 г.г. и ежемесячно электронную
версию журнала в pdf-формате.
Подробнее о проведении акции вы можете прочитать на
странице сайта.