Opensource биллинг ABillS — установка на FreeBSD

Опубликовано admin в Втр, 21/09/2010 - 22:14
0. Предыстория
Около двух лет назад перед сравнительно небольшой, но развивающейся сетью, в которой я, волею судеб, оказался системным администратором, встала задача внедрения нового биллинга. Требования оказались просты и довольно банальны для тех мест, где Интернет стоит не копейки и далеко не все готовы платить за безлимиты:
  • Возможность создания помегабайтных тарифных планов и безлимитов
  • Возможность учета трафика по направлениям (бесплатный-город-страна-мир)
  • Бесплатное решение (слово opensource тогда еще мало интересовало)
  • Вменяемый web-интерфейс пользователя и администратора
  • Возможность расширения функционала на будущее
  • Поддержка различных систем оплаты (в частности интересовала оплата карточками пополнения


Из большого количества кандидатов, как-то резко осталось всего лишь два: NeTAMS (_http://www.netams.com) и ABillS (_http://abills.net.ua).
После детального рассмотрения отпал и NeTAMS — его методы работы ну уж никак не подходили для меня, да и ощутимо чувствовалось что биллинг для него — всего лишь модуль. Более того, пользовательский web-интерфейс мягко говоря не работал. Не имея альтернатив, я приступил к установке ABillS.
Пожалуй я воздержусь от рассказа всех перипетий изучения нового софта, и предложу вам квинтэссенцию моих знаний по установке лучшего, по моему мнению, opensource-биллинга.

1. Установка
В этой записи я буду рассматривать установку исключительно для FreeBSD, притом версии 7.0 (установка на 6.х имеет незначительные, но различия). Если Вы счастливый обладатель Linux на сервере — советую обратиться к этой статье (_http://alexandr.sysoev.ru/node/104) хабрачеловека Glooom (_http://glooom.habrahabr.ru/).

1.1 Готовим ядро
Поскольку биллинг — все-таки достаточно серьезная система, я предпочитаю все используемые в работе функции иметь в ядре, а не в модулях. Поэтому добавляем в наш конфиг сборки ядра следующие опции:
options NETGRAPH #подключаем NETGRAPH в ядро
options NETGRAPH_IPFW #узел ng_ipfw

options LIBALIAS # нужен для работы ng_nat
options NETGRAPH_NAT #узел ng_nat
options NETGRAPH_NETFLOW #узел ng_netflow для сбора статистики
### Требуется для работы MPD ###
options NETGRAPH_SPLIT
options NETGRAPH_KSOCKET

options NETGRAPH_SOCKET
options NETGRAPH_BPF
options NETGRAPH_IFACE
options NETGRAPH_MPPC_ENCRYPTION
options NETGRAPH_PPP
options NETGRAPH_PPTPGRE
options NETGRAPH_TCPMSS
options NETGRAPH_VJC
options NETGRAPH_TEE
options NETGRAPH_CAR
### --- ###

options IPFIREWALL #ipfw. Куда же без него
options IPFIREWALL_VERBOSE # Поможет в отладке
options IPFIREWALL_FORWARD # Пригодится к примеру для transparent-proxy
options IPFIREWALL_DEFAULT_TO_ACCEPT #Дело привычки

1.2 ng_nat и все-все-все
К сожалению на данный момент мы не можем предоставить каждому пользователю реальный IP. Поэтому передо мной стояла задача организации NAT. После ознакомления с существующими вариантами выбор пал на ng_nat+ng_ipfw.
Для начала допишем в /etc/rc.conf следующие строки:
gateway_enable="YES" # без комментариев :)
firewall_enable="YES" # включаем ipfw
firewall_script="/usr/scripts/ipfw_load.sh" #файл с правилами

Создадим файл /usr/script/ipfw_load.sh с таким содержимым:
#!/bin/sh
fwcmd="/sbin/ipfw"
ngctl="/usr/sbin/ngctl"

ext_if="re0" # имя внешнего интерфейса
ext_ip="1.2.3.4" #внешний IP в который будут NAT'ится пользователи

#Создаем узел ng_nat
${ngctl} mkpeer ipfw: nat 60 out
${ngctl} name ipfw:60 nat
${ngctl} connect ipfw: nat: 61 in
${ngctl} msg nat: setaliasaddr ${ext_ip}

# Правила фаерволла
${fwcmd} -f flush #сбрасываем все правила фаерволла

# Создаем табличку для ната (номер 127)
${fwcmd} table 127 flush #чистим табличку
${fwcmd} table 127 add 10.39.0.0/16 # добавляем сети серых ip пользователей

#разрешаем все на loopback
${fwcmd} add 00001 allow ip from any to any via lo0
# все что пришло с внешнего интерфейса заворачиваем в NAT
${fwcmd} add 00003 netgraph 61 all from any to ${ext_ip} in via ${ext_if}
#Все что идет от Интернет-юзеров - в NAT
${fwcmd} add 60021 netgraph 60 ip from "table(127)" to any

В этом скрипте мы организовываем NAT пользователей с IP 10.39.0.0/16 в IP 1.2.3.4. Все это реализовано на таблицах, поскольку порой возникает необходимость NAT'ить несмежные диапазоны

1.3 Необходимое ПО

Для нормальной работы биллинга я использую следующее ПО (все из портов):
  • apache22 (версия — дело вкуса)
  • flow-tools (набор утилит для сбора netflow-потоков)
  • freeradius (RADIUS-сервер)
  • mpd5 (будем использовать его как VPN-сервер)
  • mysql-server, mysql-client (назначение, я надеюсь, пояснять не надо)
  • p5-DBD-mysql (для доступа к mysql из Perl)
  • p5-Digest-MD4, p5-Digest-SHA1 (используются для шифрования в биллинге)sudo (некоторые команды надо будет запускать от непривелегированного пользователя)

    Конфигурация по умолчанию, предлагаемая во FreeBSD вполне меня устраивает. Единственное — соберите mpd5 с ng_car из портов, если вы всё таки решились ставить на FreeBSD 6.x.

    1.4 Установка ABillS

    Несмотря на то, что любой человек в здравом уме и трезвой памяти для такой серьезной системы как биллинг выберет stable-ветку, я настоятельно не рекомендую делать это. Дело в том, что в понимании автора stable является «относительно стабильным релизом» и даже обнаруженные в нем ошибки исправляются в current а не stable. На личном опыте скажу, что в течении 1.5 лет использовал в работе ветку current без особых проблем.
    Поэтому, вперед за current!
    # cd /usr/local/
    # cvs -d:pserver:anonymous @ abills.cvs.sourceforge.net:/cvsroot/abills login
    # cvs -z3 -d:pserver:anonymous @ abills.cvs.sourceforge.net:/cvsroot/abills checkout -r rel-0-4 abills
    # ln -s /usr/local/abills /usr/abills

    Последнюю строчку я сделал, поскольку в конфиге довольно часто встречается упоминания папки /usr/abills в то время как в BSD ABillS я устанавливаю в /usr/local/abills.
    Теперь перейдем в папку libexec. Там мы обнаружим файл config.pl.default который скопируем в config.pl — он станет основой для нашей будущей конфигурации.

    2. Конфигурирование

    Настройка ABillS «от и до» — сложный процесс, неизбежно связанный с чтением исходных кодов. А всё дело в том, что документация, размещенная на сайте безнадежно отстает от версии в CVS. Во многом нежелание автора обновлять документацию связано с тем, что установка и конфигурирование ABillS — один из источников его дохода. Более того, всего за 300$ предлагается пакет «полноценной» документации. Но судить о нём не могу — я его не видел.
    К счастью для решения наших задач вполне хватит стандартных конфигов, которые поставляются с ABillS (хотя это сам автор не афиширует). Мы же воспользуемся его дарами. В данной статье я рассматриваю ситуацию, когда все сервисы (mysql,radius и netflow-коллектор) находятся на одной машине, но я уверен, что читателю не составит труда в случае чего изменить настройки для нескольких систем.

    2.1. RADIUS
    Итак, не мудрствуя лукаво, заглянем в папку contrib/freeradius ABillS'а и скопируем в папку freeradius'а (по умолчанию это /usr/local/etc/raddb) файлы acct_users, clients.conf, eap.conf, rlm_perl.conf и users. Файл rlm_perl.conf не забудем переименовать в radiusd.conf, а в файл clients.conf впишем IP и пароль для доступа к радиусу (В примере будут использоваться значения 127.0.0.1 и radsecret).

    Для того чтобы заработало ограничение скорости средствами MPD, которое мы собираемся использовать, допишем в конец dictionary словарь для MPD:
    VENDOR mpd 12341

    ATTRIBUTE mpd-rule 1 string mpd
    ATTRIBUTE mpd-pipe 2 string mpd
    ATTRIBUTE mpd-queue 3 string mpd
    ATTRIBUTE mpd-table 4 string mpd
    ATTRIBUTE mpd-table-static 5 string mpd
    ATTRIBUTE mpd-filter 6 string mpd
    ATTRIBUTE mpd-limit 7 string mpd
    ATTRIBUTE mpd-drop-user 154 integer mpd

    На этом настройка завершена. Запускаем radiusd -X и внимательно читаем вывод на наличие ошибок. Если ошибок нет — дописываем в /etc/rc.conf магическую строку radiusd_enable="YES" и запускаем радиус как демона.

    2.2 MPD
    5 версия MPD была выбрана по одной простой причине — именно в ней разработчики наконец ввели понятие шаблона, избавив от необходимости копировать 1000 раз одни и ти же строки.
    Приведенный мною конфиг позволяет подключение как с mppe+mppc (привет Windows) так и без него.
    startup:
    #задаем пользователей админки MPD
    set user xanf somepass admin
    # По этому порту будет доступна консоль MPD
    # она нужна ABillS для завершения сессии
    set console self 127.0.0.1 5005
    set console open
    # Веб-сервер. Полезен админу поэтому открыт наружу
    set web self 0.0.0.0 5006
    set web open
    #IP адрес и порт системы, которая собирает netflow поток
    set netflow peer 127.0.0.1 9996
    set netflow self 127.0.0.1 9990
    set netflow timeouts 15 15
    set netflow hook 9000

    default:
    load pptp_server

    pptp_server:
    #чисто косметически. IP принудительно выдает RADIUS
    set ippool add pool1 10.39.0.1 10.39.255.255
    create bundle template B
    set iface idle 1800
    #"Исправляем" реализацию TCP/IP Microsoft
    set iface enable tcpmssfix
    #На интерфейсах собирается статистика трафика
    set iface enable netflow-in
    set iface enable netflow-out
    set ipcp yes vjcomp
    #VPN Server IP
    #он будет светится в подключении со стороны пользователя
    #как "удаленный сервер". Почти ни на что не влияет
    #в то же время если не хотите доставить проблем *nix-юзерам
    #сделайте его отличным от IP адреса самого VPN сервера
    set ipcp ranges 172.16.0.1/32 ippool pool1
    set ipcp dns 172.16.0.1
    set bundle enable compression
    set ccp yes mppc
    set mppc yes e40
    set mppc yes e128
    set mppc yes stateless
    set bundle yes crypt-reqd

    create link template L pptp
    set link action bundle B
    set link enable multilink
    set link yes acfcomp protocomp
    set link no pap chap
    set link enable chap
    set link yes crypt-reqd
    set link mtu 1460
    #здесь задаем локальный IP на котором MPD будет
    #ждать соединений
    set pptp self 10.37.254.253
    set link enable incoming
    #IP, пароль и порты RADIUS-сервера
    set radius server 127.0.0.1 radsecret 1812 1813
    set radius timeout 10
    set auth acct-update 300
    set auth enable radius-auth
    set auth enable radius-acct
    set radius retries 3

    Настройка MPD завершена. Не забудьте добавить в /etc/rc.conf строчку mpd_enable="YES"

    Внимание!Если ваша система ведет себя нестабильно и умирает с «double fault» обязательно обновите исходные коды ядра. В свежей версии это проблема уже решена. Мой PR kern/125314 по этому поводу (_http://www.freebsd.org/cgi/query-pr.cgi?pr=125314)

    2.3 Настраиваем Netflow коллектор
    Прежде всего, пара слов почему из всех вариантов подсчета трафика был выбран Netflow:
    • Стандартность решения — MPD потом можно с легкостью заменить на Mikrotik или аппаратный VPN-сервер (к примеру CISCO)
    • Связка IPN+Netflow решает две проблемы бесплатной версии ABillS'а — снятие денег со счета пользователя производится только по окончанию сессии и разрыв сессии на границе временных интервалов

    Прежде всего необходимо создать ссылки в самом ABillS
    # cd /usr/abills/libexec/
    # ln -s ../Abills/modules/Ipn/trafdstats trafdstats
    # ln -s ../Abills/modules/Ipn/traffic2sql traffic2sql

    Дадим права пользователю flowtools на папку, в которую будет собирать трафик
    #chown flowtools /usr/local/abills/var/log/ipn/

    Если папки /usr/local/abills/var/log/ipn не существует — создайте ее

    Редактируем /etc/rc.conf
    flow_capture_enable="YES"
    flow_capture_datadir="/usr/local/abills/var/log/ipn/"
    flow_capture_port="9996"
    flow_capture_flags="-S 5 -n 1300 -N 0 -d 5"

    Единственный интересующий нас параметр — это -n 1300 — ротация логов будет 1300 раз в сутки, что составляет порядка одной минуты.

    2.4 Настройка Apache
    Настройка web-интерфейса настолько банальна, что я позволю себе лишь привести рабочий конфиг и сказать, что для генерирования сертификатов вы можете воспользоваться скриптом sslcerts.sh в папке contrib ABillS'а.
    <VirtualHost 0.0.0.0:443>
    SSLEngine on
    SSLOptions +StrictRequire
    SSLProtocol -all +TLSv1 +SSLv3
    SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM
    SSLCertificateFile /usr/local/abills/Certs/server.crt
    SSLCertificateKeyFile /usr/local/abills/Certs/server.key
    SSLVerifyClient none
    SSLProxyEngine off
    SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

    DocumentRoot /usr/local/abills/cgi-bin
    ServerName stat.example.com
    #ServerAlias com
    ServerAdmin xanf@example.com
    ErrorLog /var/log/error_log
    TransferLog /var/log/access_log

    Alias / "/usr/local/abills/cgi-bin/"
    <Directory "/usr/local/abills/cgi-bin">
    <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule ^(.*) - [E=HTTP_CGI_AUTHORIZATION:%1]
    Options Indexes ExecCGI SymLinksIfOwnerMatch

    AddHandler cgi-script .cgi
    Options Indexes ExecCGI FollowSymLinks
    AllowOverride none
    DirectoryIndex index.cgi
    Order allow,deny
    Allow from all

    <Files ~ "\.(db|log)$">
    Order allow,deny
    Deny from all


#Admin interface
<Directory "/usr/local/abills/cgi-bin/admin">
AddHandler cgi-script .cgi
Options Indexes ExecCGI FollowSymLinks
AllowOverride none
DirectoryIndex index.cgi
order deny,allow
allow from all




В случае получения 500-й ошибки — обязательно смотрите в error.log — почти наверняка либо что-то с базой данных, либо Perl'у не хватает какого-то модуля.

2.5 Настройка ABillS
Вот мы и подошли к самому вкусному. Тем не менее я позволю себе не останавливаться детально на всех особенностях. Приведенные конфиги позволят в минимальное время получить работоспособную систему.
Загрузим в созданную базу данных с именем abills файлы для работы с биллингом
# mysql -D abills < abills.sql
# mysql -D abills < db/Ipn.sql

Второй файл активирует расширение IPN, которым мы и воспользуемся

Прежде всего модифицируем config.pl
@MODULES = ('Dv',
'Abon',
# 'Docs',
'Sqlcmd',
'Ipn',
# 'Cards');
);

Модуль Ipn нам важен для подсчета трафика. Модуль Cards платный (60$), поэтому я его оставил закомментированным.
$conf{default_language}='russian'; #большинство по-русски :)
$conf{default_charset}='windows-1251';
$conf{periodic_check}='yes';
$conf{IPN_DEPOSIT_OPERATION}=1; #считать у нас будет именно модуль IPN
$conf{IPN_USERMENU}=1; #включаем меню пользователя

Также обратите внимание на $conf{IPN_FW_START_RULE} и $conf{IPN_FW_STOP_RULE}. Здесь вы можете задать скрипты, выполняющиеся при открытии и закрытии соединения. На всякие $conf{IPN_FW_FIRST_RULE} можете не обращать внимание — мы с Вами организуем нарезку скорости другим методом. Я лично после неудачных экспериментов вообще отказался от управления фаерволлом из ABillS и поэтому в принципе не использую скрипт linkupdown идущий с ABillS.

Одним из эффективных методом ограничения скорости клиентов при использовании MPD является возврат в Start-пакете RADIUS'а соответствующих фильтров. Таким образом к примеру для создания ограничения по тарифному плану 64 достаточно в RADIUS-параметры этого тарифного плана включить следующую строку:
mpd-limit+=out#1=all shape 64000 pass,mpd-limit+=in#1=all shape 64000 pass

При этом ограничение скорости будет производится посредством узла ng_car, что, как показала моя практика, гораздо эффективнее нарезки средствами ipfw+dummynet.
К сожалению, по непонятным причинам, ABillS «из коробки» неправильно обрабатывает оператор "+=" в тарифных планах. Чтобы исправить сие досадное недоразумение найдите в Auth.pm следующие строки:
$RAD_PAIRS->{"$left"} =~ s/\"//g;
$RAD_PAIRS->{"$left"}="\"". $RAD_PAIRS->{"$left"} .",$right\"";
}
else {
$RAD_PAIRS->{"$left"}="\"$right\"";
}

и замените на следующие:

$RAD_PAIRS->{"$left"} =~ s/\"//g;
push( @ {$RAD_PAIRS->{"$left"} }, $right );
}
else {
$RAD_PAIRS->{"$left"}= [ $right ];
}

После этого ABillS будет корректно передавать аттрибуты в формате "+="

Теперь осталось зайти в админку ABillS'а с логином и паролем abills и в разделе «System» — «NAS» (он же «Система — »Серверы доступа" в русской версии) создать новый NAS с типом «mpd4» и адресом «127.0.0.1:5005»

NAS получит номер (скорее всего это будет «1»). Теперь откройте crontab и впишите в него следующую строку:
*/5 * * * * /usr/local/abills/libexec/traffic2sql 1
flowdir=/usr/local/abills/var/log/ipn

не забыв заменить 1 на номер Вашего NAS. Теперь все данные о трафике ваших пользователей будут учитываться биллингом.
Также можете дописать в crontab вызов periodic скриптов:
1 0 * * * root /usr/abills/libexec/periodic daily
1 0 * * * root /usr/abills/libexec/periodic monthly

Не вносите как рекомендовано руководством вызов billd -all в Cron. В нашем случае он не нужен — и более того, вреден, — он будет разъединять пользователей на границах временных интервалов.

На этом базовая настройка завершена, и ваш VPM-сервер должен быть готов к работе.

3. Личные впечатления — бочка мёда
Я использую ABillS в качестве боевого сервера уже более 2 лет. За это время не случалось ни одного серьезного сбоя, а общий downtime не составил в сумме наверное и 2 часов, из которых час — переход на новые версии биллинга. Всего лишь раз, в новогоднюю ночь, из-за незначительной ошибки, биллинг стал дропать всех пользователей по time-limit. На устранение этой ошибки у меня ушло 15 минут.
В целом система предоставляет очень удобные отчеты по пользователям, вся нужная информация хранится в БД, куча различных модулей облегчают жизнь — одни приятные впечатления. Наши друзья купили себе UTM (_http://www.netup.ru) и с ним у них проблем было гораздо больше, даже при наличии у них платной поддержки

4. Личные впечатления — ложка дёгтя
Тем не менее ABillS не идеален. Много функционала (linkupdown, periodic-скрипты) я вообще не использую, а точнее использую собственные «заменители», поскольку авторские меня не устраивают по тем или иным причинам.
Порой в current случаются достаточно глупые ошибки. Так после одного из обновлений (в среднем мы обновляем биллинг раз в полгода) пользователи с кредитом потеряли возможность выходить в Интернет из-за поставленного не в ту сторону знака ">" при проверки кредитного лимита тарифного плана и пользователя. Сам traffic2sql работает в исходном виде довольно медленно (патч на форуме ABillS (_http://abills.net.ua/forum/viewtopic.php?t=4133&start=15)), а при динамической выдаче IP из пула трафик может считаться не правильно (багрепорт+патч на форуме ABillS (_http://abills.net.ua/forum/viewtopic.php?t=4162)).
Также, однажды при включении модуля Msgs, предоставляюшего базовый функционал «обращения в техподдержку» из биллинга, я через два дня с ужасом обнаружил, что в сообщениях не режутся никакие теги вообще, что позволяет к примеру с помощью IFRAME сменить тарифный план пользователю как только администратор посмотрит его сообщение.
Особенно это огорчает по той причине, что 95% модулей, «появляющихся» для ABillS — это отнюдь не дешевые коммерческие заказы, которые потом выпускаются «для всех».


DISCLAIMER вместо послесловия Все написанное выше есть мой личный опыт в использовании этой системы. Мое мнение является сугубо субъективным, я не гарантирую абсолютную правильность и беспроблемность предлагаемых решений. Также я, как и любой человек, могу ошибаться. Если Вам есть чем дополнить и улучшить эту статью — я всегда рад конструктивной критике в комментариях или электропочте (есть в профиле)


Статья взята с http://habrahabr.ru (_http://habrahabr.ru/blogs/bsdelniki/30174/)

( categories: )