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

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


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

    1. Установка
    В этой записи я буду рассматривать установку исключительно для FreeBSD, притом версии 7.0 (установка на 6.х имеет незначительные, но различия). Если Вы счастливый обладатель Linux на сервере — советую обратиться к этой статье хабрачеловека Glooom.

    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 по этому поводу

      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 и с ним у них проблем было гораздо больше, даже при наличии у них платной поддержки

    4. Личные впечатления — ложка дёгтя
    Тем не менее ABillS не идеален. Много функционала (linkupdown, periodic-скрипты) я вообще не использую, а точнее использую собственные «заменители», поскольку авторские меня не устраивают по тем или иным причинам.
    Порой в current случаются достаточно глупые ошибки. Так после одного из обновлений (в среднем мы обновляем биллинг раз в полгода) пользователи с кредитом потеряли возможность выходить в Интернет из-за поставленного не в ту сторону знака ">" при проверки кредитного лимита тарифного плана и пользователя. Сам traffic2sql работает в исходном виде довольно медленно (патч на форуме ABillS), а при динамической выдаче IP из пула трафик может считаться не правильно (багрепорт+патч на форуме ABillS).
    Также, однажды при включении модуля Msgs, предоставляюшего базовый функционал «обращения в техподдержку» из биллинга, я через два дня с ужасом обнаружил, что в сообщениях не режутся никакие теги вообще, что позволяет к примеру с помощью IFRAME сменить тарифный план пользователю как только администратор посмотрит его сообщение.
    Особенно это огорчает по той причине, что 95% модулей, «появляющихся» для ABillS — это отнюдь не дешевые коммерческие заказы, которые потом выпускаются «для всех».


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

    Подробнее
    Реклама

    Комментарии 12

      +2
      Очень интересная статья, спасибо.
      Только есть вот такой вопрос. В какой виде существует сеть, в которой вы этот биллинг ставили и насколько это законно в Украине?
      Опенсурсность подкупает, но, к примеру, в России, ежели сеть — юридическое лицо, отношения с Министерством по связи и информатизации образовываются очень щепетильные и нежные. Т.е. применение несертифицированных решений не только не рекомендуется, но и чревато, так сказать.
      Потому большинство тупо сидит на довольно убогом, но сертифицированном и относительно недорогом Нетапе.
        +3
        Я прекрасно понимаю ситуацию в России (доводилось работать - оттуда и опыт с UTM). К счастью (или к сожалению) в Украине пока все не так - не существует единой процедуры сертифицирования биллинга. Существует некая мифическая процедура "поверки биллинга" органом госповерки - но насколько я знаю ни у одной сети в городе её нет.
        Естественно, что со стороны Российских пользователей все чаще просят сертификат на ABillS. Автор обещает это - оговорившись когда-то, что в таком случае решение будет платным от 2к долларов, что, ИМХО, перечеркивает все его преимущества перед UTM
          0
          УТМ довольно таки хорошо работает, после полугодовой доработки его напильником.
          0
          В статье вижу
          < Directory>
          < IfModule>
          , хабр голодный и опять откусил кусок )

          >Не вносите как рекомендовано руководством вызов billd -all в Cron. В нашем случае он не нужен - и более того,
          >вреден, - он будет разъединять пользователей на границах временных интервалов.
          Но в этоже время если на разные интервалы установлены разные скоростные ограничения, то этот скрипт нужен.
            +1
            OpensouRce в заголовке.
              0
              В своё время ставил abills на линуксе, ох и намучался при связывании его с радиусом и pppoed.
                0
                Да. Во FreeBSD с этим как-то проще
                0
                А слона то я и не заметил! Спасибо!
                  +1
                  "К сожалению на данный момент..." — там должна быть запятая.
                  0
                  В свое время лень было разбираться с ABillS, по-тихоньку написал свою считалку, позднее переросла в биллинг по функционалу соответствующий условиям, которые описал топикстартер (% но со временем разработка затормозилась, называлось SUBBilling, может кто слышал(:
                    0
                    О. Я на него даже смотрел внимательно очень :)) Было ровно то что мне надо - но оно уже тогда не сильно шевелилось.
                    А вообще умение написать свое - это очень похвально
                    0
                    толково, но биллинг довольно специфический.

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое