Настройка биллинговой системы abills + VPN + radius + mysql

Материал из Медиа Вики
Перейти к: навигация, поиск

Попытка адаптировать документацию по биллинговой системе ABILLS применительно к использованию ее под ОС Linux
Примечание: Эта статья написана для abills V0.35 и Mandriva 2007.1.При использовании других версий настройка может немного отличаться. Что замечу, то внесу, а что нет так нет.

Постепенно документация изменяется. В данный момент уже проверена работа с Mandriva 2010.1 + radius 2.1.8 + abills 0.51b. Все замечания прошу присылать мне

Этот документ базируется на оригинальной документации по ABILLS от Asmodeus’а http://www.abills.net.ua/wiki/doku.php

Здесь будет описана установка биллинга для VPN сервера (abills + pppd + pptpd) Пути установки программ и расположения конфигурационных файлов несколько изменены по сравнению с оригинальной документацией. Вы можете их изменять, однако отдавайте себе отчет, что при этом потребуется изрядно переконфигурировать весь комплекс программ. Все компоненты (NAS, radius, web-сервер, база данных) расположены на одном сервере, хотя это не исключает возможности вынести например NAS или базу данных на другую машину.

Итак- устанавливаем пакеты, нужные для настройки биллинга freeradius-*.rpm, libfreeradius1-*.rpm, freeradius-mysql-*.rpm, libradius0-*.rpm, ppp-radius-*.rpm, pptpd-server-*.rpm, radiusclient-utils-*.rpm, webmin*.rpm

Возможности ABillS

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

pppd

Создаем файл /etc/ppp/options.pptpd со следующим содержимым:

mtu 1490
mru 1490
ms-dns 172.16.130.1             # ip адресс DNS сервера
ipcp-accept-local
ipcp-accept-remote
lcp-echo-failure 30
lcp-echo-interval 5
auth
+mschap-v2
defaultroute
mppe required,stateless
#plugin radius.so
#plugin radattr.so
#debug

Более детальное описание опций здесь - http://mppe-mppc.alphacron.de/

Примечание: в последнее время я пришел к выводу, что MPPE и MPPC в домашней сети не такая уж и полезная фича. Ресурсов отъедает прилично. По этому если вы строите NAS на недостаточно производительном железе, подумайте, нужно ли оно вам. Возможно лучшим выходом будет отключить обязательное шифрование в виндовом клиенте.

pptpd

pptpd, (подпольная кличка - PopTop) можете взять из своего дистрибутива

Правим файл /etc/pptpd.conf :

ppp /usr/sbin/pppd
option /etc/ppp/options.pptpd
#debug
# stimeout 10
# noipparam
logwtmp
bcrelay eth0
localip ***.***.***.*** # Здесь IP адрес интерфейса вашего pptpd сервера, например, 192.168.20.1
#remoteip 192.168.0.234-238,192.168.0.245 # Закоментировать, назначается
				 	  #радиусом
Редактируем файл /etc/ppp/chap-secret
# Secrets for authentication using CHAP
# client        server  secret                  IP addresses
vova    *       vova            192.168.200.5
Перезапускаем pptpd демон и пробуем войти по VPN c Win машины с авторизацией CHAP, или MS-CHAP V2 c шифрацией трафика с именем vova и паролем vova. Если все ок, снимаем ремарки со строк
plugin radius.so
plugin radattr.so
в файле options.pptpd и идем дальше.

Ошибки и их устранение

После установки и настройки pptpd демона в системный лог посыпались сообщения GRE: accepting packet #1

В Mandriva 2010.1 данная проблема решена. Надо в файле /etc/pptpd.conf закоментировать опцию debug (по умолчанию она закоментирована).

Настройка Iptables (фаервола)

Хотя настройка фарвола это совсем другая история (см тут ), но для проверки, как работает инет через данную систему, привожу тут несколько правил, которые помогут проверить работу всей системы.

#!/bin/sh
#
# Сначала сбросим все правила, которые были до этого
/etc/init.d/iptables stop
###########################################################################
#
# Configuration options.
#
#
# Internet Configuration.
#
INET_IP="213.54.25.11"          # Арес интерфейса, который смотрит в интернет
LAN_VPN_RANGE="192.168.10.0/24" # Диапазон адресов VPN сети, имеющей доступ
                                # в инет
# IPTables Configuration.
#
# Путь, где находится iptables.
IPTABLES="/usr/local/sbin/iptables"

# Включаем форвардинг
echo "1" > /proc/sys/net/ipv4/ip_forward
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT

# Делаем NAT
$IPTABLES -t nat -A POSTROUTING  -s $LAN_VPN_RANGE -j SNAT --to-source $INET_IP
Ну вот и все. Этого достаточно для проверки. Но на рабочем сервере такое использование я бы очень не рекомендовал.

Perl modules

Для работы системы нужны модули.

DBI 	
DBD::mysql	
Digest-MD5	для Chap авторизации
Digest-MD4	для MS-Chap авторизации
Crypt-DES 	для MS-Chap авторизации
Digest-SHA1	для MS-ChapV2 авторизации
libnet 	Нужен только при авторизации из UNIX passwd
Time-HiRes	Нужен только для тестирования скорости выполнения авторизации,
 		акаунтинга, и страниц веб интерфейса.
DB_File

Все модули, кроме DBI есть в rpm-ax.

Установить модуль perl-devel-*.rpm

Установить модули Perl-DBD-mysql-*.rpm и Perl-DB_File-*.rpm

Очень удобно эти модули загрузить с сайта | www.cpan.org или установка с консоли. Вот способ установки:

# cd /root 
# perl -MCPAN -e shell 
o conf prerequisites_policy ask 
install    DBI      
install    Digest::MD5 
install    Digest::MD4 
install    Crypt::DES 
install    Digest::SHA1 
install    Bundle::libnet 
install    Time::HiRes 
quit

Закачка дистрибутива Abills

Тк далее в настройках будут ссылки на этот дистрибутив, то для последовательного изложения, нужно его выкачать
Скачиваем и распаковываем последний релиз версии в отдельный каталог:

cd /usr/src/abills_distr
wget http://puzzle.dl.sourceforge.net/sourceforge/abills/abills-0.xx.tgz
tar -xvzf abills-0.xx.tgz

Установка freeradius

Настройка для Mandriva 2008.1 с FreeRadius v1.7.1

Настройку в Mandriva 2009.1 с данной версией радиуса я не проверял, так что если что не так, то извините.
Для настройки биллинга с FreeRadius v1.7.1, я переустановил все пакеты Radius сервера V1.7.1, из Mandriva 2008.
Для этого нужны пакеты freeradius-1.1.7-2mdv2008.0.i586.rpm, libradius0-devel-0.3.2-7mdv2008.0.i586.rpm, libradius0-static-devel-0.3.2-7mdv2008.0.i586.rpm, libfreeradius1-1.1.7-2mdv2008.0.i586.rpm, ppp-radius-2.4.4-1mdv2008.0.i586.rpm, libfreeradius1-mysql-1.1.7-2mdv2008.0.i586.rpm, radiusclient-utils-0.3.2-7mdv2008.0.i586.rpm, libradius0-0.3.2-7mdv2008.0.i586.rpm. Их можно взять тут.
Сначала удаляем соответствующие пакеты, с помощью urpme, например

# urpme freeradius
# urpme libfreeradius
и другие ...

А потом устанавливаем выше указанные, через rpm, например

rpm -i libradius0-0.3.2-7mdv2008.0.i586.rpm

Пакет libfreeradius1-1.1.7-2mdv2008.0.i586.rpm устанавливать с ключами -i --nodeps.

Настройка для freeradius 1.7.*

Переименовываем файл

#mv /etc/raddb/users  /etc/raddb/users.old 

Создаем новый файл /etc/raddb/users и вставляем туда строки

DEFAULT Auth-Type = Accept
		Exec-Program-Wait = "/usr/abills/libexec/rauth.pl"

Правим файл /etc/raddb/acct_users

#Перед Exec-Program должен быть пробел
#Если каждого аккаунтинг-запроса в памяти оставались зомби-процессы racct.pl, то замените
#замените в файле acct_users Exec-Program на Exec-Program-Wait
DEFAULT Acct-Status-Type == Start
 		Exec-Program = "/usr/abills/libexec/racct.pl"
 DEFAULT Acct-Status-Type == Alive
 		Exec-Program = "/usr/abills/libexec/racct.pl"
DEFAULT Acct-Status-Type == Stop
 		Exec-Program = "/usr/abills/libexec/racct.pl"

Не забываем про пробелы перед Exec-Program

У большинства такая конфигурация работает нормально, а в моем случае после каждого аккаунтинг-запроса в памяти оставались зомби-процессы racct.pl. Проверить это можно командой:

ps ax|grep racct

Если у вас тоже остаются зомби, то рекомендую заменить в файле acct_users Exec-Program на Exec-Program-Wait

/etc/raddb/clients.conf В этот файл нужно вписать IP адрес или имя NAS сервера с которого будут поступать данные для радиуса и пароль доступа, те исправить строки secret.

client localhost {
   # Ниже пароль для доступа к радиусу. Запомните его, он 
   # понадобится в п. 8 
   secret = radsecret     
   shortname = shortname
}

/etc/raddb/radiusd.conf- Если вы желаете использовать MPPE, MPPC, MS-Chap V2 (протоколы шифрования и компрессии от M$ - для VPN очень желательно) то в файл /etc/raddb/radiusd.conf вносятся следующие изменения: В секции mschap {

use_mppe = yes
require_encription = yes
require_strong = yes

Cоздаются функции для преавторизации и поставторизации в секции modules {

exec pre_auth { 
  wait = yes 
  program = "/usr/abills/libexec/rauth.pl pre_auth" 
  input_pairs = request 
  output_pairs = config 
}
 
exec post_auth {
  wait = yes
  program = "/usr/abills/libexec/rauth.pl post_auth"
  input_pairs = request
  output_pairs = config
}

В секции ‘authorize’ внести ‘pre_auth’ и раскоментировать ‘mschap’.
Внимание В Mandriva 2008.1 секции authorize и post-auth вынесены в отдельный файл /etc/raddb/sites-inabled/default

authorize { 
  pre_auth 
  preprocess
 # auth_log 
 # attr_filter 
   chap 
  mschap 
  suffix 
  files 
} 

Для оповещения о неавторизированых пользователях правим секцию post-auth

post-auth {
  Post-Auth-Type REJECT {
     post_auth
  }
}

Настройка для freeradius 2.*

Огромное спасибо пользователю Andrushka с форума abills
Переименовываем файл

#mv /etc/raddb/users  /etc/raddb/users.old 

Создаем новый файл /etc/raddb/users и вставляем туда строку

DEFAULT Auth-Type = Accept

Файл /etc/raddb/clients.conf В этом файле нужно исправить строки secret.

   # Ниже пароль для доступа к радиусу. Запомните его, он 
   # понадобится в п. 8 
   secret = radsecret     

Файл /etc/raddb/modules/mschap- Если вы желаете использовать MPPE, MPPC, MS-Chap V2 (протоколы шифрования и компрессии от M$ - для VPN очень желательно) то в этот файл вносятся следующие изменения:

mschap{
use_mppe = yes
require_encription = yes
require_strong = yes
}

Файл radiusd.conf в секции modules описываем такие секции:

abills_preauth 
exec abills_preauth { 
program = "/usr/abills/libexec/rauth.pl pre_auth" 
wait = yes 
input_pairs = request 
shell_escape = yes 
#output = no 
output_pairs = config 
} 

abills_postauth 
exec abills_postauth { 
program = "/usr/abills/libexec/rauth.pl post_auth" 
wait = yes 
input_pairs = request 
shell_escape = yes 
#output = no 
output_pairs = config 
} 

abills_auth 
exec abills_auth { 
program = "/usr/abills/libexec/rauth.pl" 
wait = yes 
input_pairs = request 
shell_escape = yes 
output = no 
output_pairs = reply 
} 

abills_acc 
exec abills_acc { 
program = "/usr/abills/libexec/racct.pl" 
wait = yes 
input_pairs = request 
shell_escape = yes 
output = no 
output_pairs = reply 
}

Файл /etc/raddb/sytes-inable/default - правим секции authorize, preacct, post-auth. Остальное в этих секциях ремарим.

authorize { 
preprocess 
abills_preauth 
mschap 
files 
abills_auth 
} 

preacct { 
preprocess 
abills_acc 
} 

post-auth { 
Post-Auth-Type REJECT { 
abills_postauth 
} 
} 

В файле /etc/raddb/modules/exec

exec {
     wait = yes
     input_pairs = request
     shell_escape = yes
     output = none
     output_pairs = reply
  }

В версии Abills 0.4.3 и больше, что написано ниже делать не надо. А надо только добавить строчку в файл /usr/abills/libexec/config.pl

$conf{RADIUS2}=1;

Правим файл /usr/abills/Abills/mysql/Auth.pm
Было строка ~1452

    my $list = $self->{list}->[0];
    my $password = $list->[0];
    $self->{'RAD_CHECK'}{'User-Password'}="$password";
    print "User-Password == \"$password\"";
    return 0;
Стало
    my $list = $self->{list}->[0];
    my $password = $list->[0];
    $self->{'RAD_CHECK'}{'User-Password'}="$password";
    # freeeradius 1xx 
    #print "User-Password == \"$password\""; 
    # freeradius v2 
    print "Cleartext-Password := \"$password\"";
    return 0;

Radiusclient

В мандивовском клиенте не хватает нескольких библиотек для работы. Я делал так выкачал с www.samba.org/ppp дистрибутив ppp-2.4.5.tar.gz. Распаковал в /usr/local/src

# ./configure
# make

Далее переписываем содержимое каталога /usr/local/src/ppp-2.4.5/pppd/plugins/radius/etc в каталог /etc/radiusclient/, кроме файла /etc/radiusclient/radiusclient.conf

Правим файл /etc/radiusclient/radiusclient.conf:

authserver      127.0.0.1
acctserver      127.0.0.1

В файл /etc/radiusclient/servers вносим IP адрес радиус-сервера и соответствующий ему пароль (см п.1)

127.0.0.1          radsecret

Настройка библиотек для Радиусов.

Для нормальной работы с NAS на осноаве pppd необходимо добавить в файл словарей freeradius’а /etc/raddb/dictionary и /etc/radiusclient/dictionary следующие строки (между колонками дб табуляции):

# Limit session traffic
 ATTRIBUTE       Session-Octets-Limit            227     integer
 # What to assume as limit - 0 in+out, 1 in, 2 out, 3 max(in,out)
 ATTRIBUTE       Octets-Direction                228     integer
 # Connection Speed Limit
 ATTRIBUTE       PPPD-Upstream-Speed-Limit       230     integer
 ATTRIBUTE       PPPD-Downstream-Speed-Limit     231     integer
 ATTRIBUTE       PPPD-Upstream-Speed-Limit-1     232     integer
 ATTRIBUTE       PPPD-Downstream-Speed-Limit-1   233     integer
 ATTRIBUTE       PPPD-Upstream-Speed-Limit-2     234     integer
 ATTRIBUTE       PPPD-Downstream-Speed-Limit-2   235     integer
 ATTRIBUTE       PPPD-Upstream-Speed-Limit-3     236     integer
 ATTRIBUTE       PPPD-Downstream-Speed-Limit-3   237     integer

Проверка конфигурационных файлов freeradius

check-radiusd-config -level 345 radiusd on

Если все ок, то:

Radius server configuration looks OK.

При отладке останавливаем freeradius, и запускаем freeradius -X

MYSQL

Создаем файл pre_abills.sql следующего содержания:

use mysql;
INSERT INTO user (Host, User, Password) VALUES ('localhost','abills',password('sqlpassword'));
INSERT INTO db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv,
 Index_priv, Alter_priv) VALUES ('%', 'abills', 'abills', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y');
CREATE DATABASE abills DEFAULT CHARSET=cp1251;

Не забудьте исправить sqlpassword на свое усмотрение. Для тех кто не понял, это пароль mysql-пользователя abills, необходимый для доступа к базе данных abills

Cоздаём пользователя и базу.

Далее делаем в консоли.

# mysql -u root -p < pre_abills.sql
# mysqladmin -uroot -p flush-privileges

Я просто создал пользователя в webmin, дал ему полный доступ к базе “abills” и установил пароль.

На этом настройка mysql завершена.

Abills

Правим конфигурационый файл системы /usr/abills/libexec/config.pl:

#DB configuration 
$conf{dbhost}='localhost';
$conf{dbname}='abills'; 
$conf{dbuser}='abills';
#Если Вы используете Radius 2, то
$conf{RADIUS2}=1;

#Здесь нужно подставить пароль mysql-пользователя abills (п.2)
$conf{dbpasswd}='sqlpassword'; 
$conf{ADMIN_MAIL}='info@your.domain'; 
$conf{USERS_MAIL_DOMAIN}="your.domain";
#For MySQL 5 and highter
$conf{dbcharset}='cp1251';
# используется для шифрования паролей администраторов и пользователей.
$conf{secretkey}="test12345678901234567890"; 

#Лимит трафика на сессию, больше нельзя, изза глюка radiusclient'а 
# Не забудте поправить, иначе клиенты Linux коннектится не будут.
$conf{MAX_SESSION_TRAFFIC}=2047; 

При использовании модуля Dv полезно так же добавить в конфиг следующие параметры, и изменить их по своему усмотрению.

$conf{MAC_AUTO_ASSIGN}=0;    # Заполнять поле CID при cоединении, если оно не заполнено
$conf{DV_USER_CHG_TP}=0;     # Разрешить пользователю менять тарифный план из своего веб акаунта
$conf{ERROR_ALIVE_COUNT}=3;  # Количество периодов не пришедших Alive пакетов после которого сесия
                              # автоматом    попадает в Zap таблицу

При изменении значения в $conf{secretkey} поменяйте его также в файле abills.sql из дистрибутива abills. После этого загружаем структуру таблиц в базу:

#mysql -D abills < abills.sql

Для того, чтобы можно было осуществлять hangup подключенного пользователя необходимо добавить в файл /etc/sudoers:

apache   ALL = NOPASSWD: /usr/abills/misc/pppd_kill

И там же закоментируйте строку

#Defaults requiretty

Вносим в cron периодические процессы, /etc/crontab (уберите восклицательный знак в начале первой строки):

*/5 *  *  *  *   root    /usr/abills/libexec/billd -all
 1    0  *  *  *   root    /usr/abills/libexec/periodic daily
 1    0  1  *  *   root    /usr/abills/libexec/periodic monthly

Если хотите, чтоб ежедневно осуществлялось автоматическое резервное копирование базы данных, добавьте туда же:

1    3  *  *  *   root     /usr/abills/libexec/periodic backup

Определяем от имени какого пользователя запускается web-сервер в нашей системе. Для этого надо просмотреть файл httpd.conf и найти в нем директиву User, которая определяет имя владельца процесса. В моем случае:

User apache

Устанавливаем права на чтение и запись вебсервером для файлов веб интерфейса

chown -Rf apache /usr/abills/cgi-bin

Создаем недостающие каталоги:

mkdir /usr/abills/backup
chown -Rf apache /usr/abills/backup
chown -Rf apache /usr/abills/Abills/templates
mkdir /usr/abills/var
mkdir /usr/abills/var/log

Правим файл /usr/abills/Abills/defs.conf. После правки я бы рекомендовал скопировать этот файл в defs.conf.old, что бы после обновления abills не пришлось снова его править.

$SNMPWALK = '/usr/bin/snmpwalk';
$GZIP = '/bin/gzip';
$MYSQLDUMP = '/usr/bin/mysqldump';

В вашем случае пути к этим программам могут быть иными, проверьте командой which.

Еще: freeradius будет ругаться, что у вас нет логов abills, поэтому мы это исправляем.

touch /usr/abills/var/log/abills.log
chown radius /usr/abills/var/log/abills.log

Далее настраиваем apache . Открываем веб интерфейс - https://your.host:9433/abills/admin/ Логин администратора по умолчанию - abills , пароль - abills. От имени этого администратора будут выполняться различные операции в автоматическом режиме, например снятие абонплаты в начале месяца, по этому удалять его не нужно, нужно только изменить пароль на более безопасный. Для реальных администраторов необходимо завести свои аккаунты и назначить им необходимые права: Система → Администраторы

Если впоследствии вам понадобится самая свежая функциональность обновления из CVS можно производить следующим образом:

cd /usr/src/abills_distr
    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-3 abills      
    cp -Rf abills /usr/
chown -Rf apache /usr/abills/cgi-bin

После этого изучаем changelog и выполняем необходимые рекомендации.

Тот кто выполнил все предыдущие пункты и увидел вебинтерфейс заслужил первую бутылку пива. Дальнейшее описание специфично именно для Linux-систем с pppd.

Web server

Для работы web-интерфейса требуется установить и настроить web сервер. Как и в случае с mysql нет особого смысла собирать его из исходников, поскольку любой приличный дистрибутив уже имеет в своем составе web-сервер Apache. Он должен быть собран и сконфигурирован с поддержкой модуля mod_rewrite. Переписываем файл /usr/abills/misc/apache/abills_httpd.conf в каталог /etc/httpd/conf/vhosts.d/
1. В файле /etc/httpd/conf/httpd.conf

Было
#NameVirtualHost *:80
Стало
NameVirtualHost *

Ошибка в версии 0.36b ивыше

Для того, что бы заработало, надо изменить файл abills_httpd.conf
Было

#Abills version 0.4. Default ABillS port is 9443
Listen 9443

#Alias for web report

Стало

#Abills version 0.4. Default ABillS port is 9443
NameVirtualHost *:9443
#Listen 9443

Alias /abills "/usr/abills/cgi-bin/"

#Alias for web report

Создание ssl сертификата

Сертификат для работы apache можно создать двумя способами

Используем скрипт /usr/abills/misk/sslserts.sh

Запускаем скрипт

/usr/abills/misc/sslcerts.sh apache

В новых версиях abills

/usr/abills/misc/certs_create.sh apache

И отвечаем на вопросы, которые будет задавать скрипт.
На вопрос

Common Name (eg, your name or your server's hostname) []:

Если у Вас доступ к серверу будет по IP адресу (Нет DNS имени) -вводим имя сервера, например, ns2.
или DNS имя Вашего сервера, например, volmed.org.ru. В конце получим 2 сертификата, лежащий в папке /usr/abills/Certs
После этого править файл /etc/httpd/conf/vhosts.d/abills_httpd.conf не надо.

С помощью своего скрипта

Делаем следующее:
# cd /etc/ssl
# mkdir db
# mkdir ca
# mkdir clients
# touch /etc/ssl/db/index.txt
# echo "01" > /etc/ssl/db/serial

Создаем скрипт для создания нашего самоподписанного доверенного сертификата (CA) /etc/ssl/make_ca.sh :

#!/bin/sh
openssl req -new -newkey rsa:4096 -nodes -keyout ./ca/ca.key -x509 -days 3650 \
   -subj /C=RU/ST=Russia/L=Vologda/O=EI/OU=IT/CN=mail.volmed.org.ru/emailAddress=misk@volmed.org.ru -out ./ca/ca.crt

Где mail.volmed.org.ru адрес нашего почтового сервера

Запускаем скрипт make_ca.sh. Какое-то время он будет возиться с генерацией секретного ключа длиной в 4096 бит, на слабой машине это займет время... можете уменьшить длину ключа до 1024 или 2048 бит, если очень не терпится все поскорее попробовать. В итоге мы получим два файла в каталоге /etc/ssl/ca:
ca.crt - это наш самоподписанным доверенный сертификат, и
ca.key - его секретный ключ.
Правим файл /etc/httpd/conf/vhosts.d/abills_httpd.conf.
Добавляем строку. Было

Listen 9443
<VirtualHost _default_:9443>
DocumentRoot "/usr/abills/cgi-bin"

Стало

Listen 9443
<VirtualHost _default_:9443>
Alias /abills "/usr/abills/cgi-bin/"
DocumentRoot "/usr/abills/cgi-bin"

Было

   SSLCertificateFile /usr/abills/Certs/server.crt
   SSLCertificateKeyFile /usr/abills/Certs/server.key

Стало

   SSLCertificateFile /etc/ssl/ca/ca.crt
   SSLCertificateKeyFile /etc/ssl/ca/ca.key

И перезапускаем вебсервер

# /etc/init.d/httpd restart

Для доступа к web интерфейсу abills нужно открыть в фаерволе 9443 port и в строку адреса браузера набирать
https://host:9443/abills/admin

Шейпер

Что бы включить шейпер, создаем файл скрипт /etc/ppp/ip-pre-up и пишем в него:

if [ -f /var/run/radattr.$1 ]
   then
   DOWNSPEED=`/bin/awk  '/PPPD-Downstream-Speed-Limit/ {print $2}'  /var/run/radattr.$1`
   UPSPEED=`/bin/awk  '/PPPD-Upstream-Speed-Limit/ {print $2}'  /var/run/radattr.$1`
   FILTERS=`/bin/awk  '/Filter-Id/ {print $2}'  /var/run/radattr.$1`
 #echo $DOWNSPEED
 #echo $UPSPEED
 #echo $FILTERS
    /sbin/tc qdisc del dev $1 root    > /dev/null
    /sbin/tc qdisc del dev $1 ingress > /dev/null

 ##### speed server->client
   if [ "$UPSPEED" != "0" ] ;
   then
     /sbin/tc qdisc add dev $1 root handle 1: htb default 20 r2q 1
     /sbin/tc class add dev $1 parent 1: classid 1:1 htb rate ${UPSPEED}kbit burst 4k
     /sbin/tc class add dev $1 parent 1:1 classid 1:10 htb rate ${UPSPEED}kbit burst 4k prio 1
     /sbin/tc class add dev $1 parent 1:1 classid 1:20 htb rate ${UPSPEED}kbit burst 4k prio 2
     /sbin/tc qdisc add dev $1 parent 1:10 handle 10: sfq perturb 10 quantum 1500
     /sbin/tc qdisc add dev $1 parent 1:20 handle 20: sfq perturb 10 quantum 1500
     /sbin/tc filter add dev $1 parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10
     /sbin/tc filter add dev $1 parent 1:0 protocol ip prio 10 u32 match ip protocol 1 0xff flowid 1:10
     /sbin/tc filter add dev $1 parent 1: protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u160x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid 1:10
   fi 
 ##### speed client->server
   if [ "$DOWNSPEED" != "0" ] ;
   then
     /sbin/tc qdisc add dev $1 handle ffff: ingress
     /sbin/tc filter add dev $1 parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${DOWNSPEED}kbit burst 12k drop flowid :1
   fi
 fi

Конфигурирование NAS

Теперь необходимо сконфигурировать NAS. Заходим в web-интерфейс администратора https://your.host:9433/abills/admin/
Логин - abills
пароль - abills
Идем: Система → Сервер доступа Редактируем Nas, созданный по умолчанию.
В нашем случае:

IP 			127.0.0.1  
Название 		(произвольно, напр. - NAS Server)
Radius NAS-Identifier 	Идентификатор сервера (можно не вписывать)
Опис	 		Описание сервера (Произв)
Type 			pppd:pppd + Radius plugin (linux)
Authorization 		SQL
Alive 			60 
	
IP:PORT 	        удалить	
Пользователь:           удалить  
Пароль:                 удалить 
RADIUS Parameters 	Acct-Interim-Interval=60

Значение Alive и значение параметра Acct-Interim-Interval нужно выбирать одинаковым. Осталось создать тарифные планы и завести юзеров..

Проверяем
# radtest testuser testpassword 127.0.0.1:1812 0 radpasswd 0 127.0.0.1
testuser - имя пользователя из базы
testpassword - его пароль
radpasswd - пароль из файла /etc/radiusclient/servers
Если всё правильно настроено, в файле логов /usr/abills/var/log/abills.log должна появиться строка
2005-02-23 12:55:55 LOG_INFO: AUTH [testuser] NAS: 1 (xxx.xxx.xxx.xxx) GT: 0.03799

Если radius сервер на одной машине, а radius клиент на другой

Допустим, что
ip адрес машины радиус сервера 192.168.1.10
ip адрес машины радиус клиента 192.168.1.20
1. Правим файл /etc/raddb/users.conf

client 192.168.1.20  { 

2. Заходим в http://192.168.1.10/abills/admin
Далее Система ---> Сервер доступа
Выбираем нужный NAS сервер и меняем его IP адрес на 192.168.1.10
3. Проверка - из консоли мфшины 192.168.1.20 запускаем

radtest user passuser 192.168.1.10:1812 0 radpasswd 0 192.168.1.10

Где user и passuser - имя и пароль одного из пользователей abills.
radpasswd - пароль из файла /etc/raddb/users.conf

Добавляем статистику

abills/libexec/config.pl

$conf{s_detalization}='yes'; Более детальная статистика по сесиям
$conf{DV_LOG_CLEAN_PERIOD}=90 Время хранения логов детализации. Задаётся в днях.

В свободной версии нет подробной статистики по alive пакетам.
Для ее добавления делаем следующее (но без гарантии, что все правильно).
Редактируем файл /usr/abills/Abills/mysql/Acct.pm
Строка ~236 Вставляем строки
После

  elsif ($conf->{rt_billing}) {
    $self->rt_billing($RAD, $NAS);
   }

Вставляем

###################my#########################################
    $self->query($db, "SELECT acct_input_octets, acct_output_octets FROM dv_calls
    WHERE user_name='$RAD->{USER_NAME}' and acct_session_id='$RAD->{ACCT_SESSION_ID}';");
    my $a_ref1 = $self->{list}->[0];
       ($self->{INPUT33},
        $self->{OUTPUT33},
        )= @$a_ref1;

##################my########################################

Было. Строка ~264

#detalization for Exppp
if ($conf->{s_detalization} eq 'yes') {
   $RAD->{INTERIUM_INBYTE}=0 if (! defined($RAD->{INTERIUM_INBYTE}));
   $RAD->{INTERIUM_OUTBYTE}=0 if (! defined($RAD->{INTERIUM_OUTBYTE}));
   $RAD->{INTERIUM_INBYTE2}=0 if (! defined($RAD->{INTERIUM_INBYTE2}));
   $RAD->{INTERIUM_OUTBYTE2}=0 if (! defined($RAD->{INTERIUM_OUTBYTE2}));
Стало
#detalization for Exppp
if ($conf->{s_detalization} eq 'yes') {
###########################my###################################
   $self->{INPUT33}=0 if (! defined($self->{INPUT33}));
   $self->{OUTPUT33}=0 if (! defined($self->{OUTPUT33}));
    $RAD->{INBYTE}=0 if (! defined($RAD->{INBYTE}));
    $RAD->{OUTBYTE}=0 if (! defined($RAD->{OUTBYTE}));

    $RAD->{INTERIUM_INBYTE}=$RAD->{INBYTE} - $self->{INPUT33};
    $RAD->{INTERIUM_OUTBYTE} = $RAD->{OUTBYTE} - $self->{OUTPUT33};
############################my###################################

    $RAD->{INTERIUM_INBYTE2}=0 if (! defined($RAD->{INTERIUM_INBYTE2}));
    $RAD->{INTERIUM_OUTBYTE2}=0 if (! defined($RAD->{INTERIUM_OUTBYTE2}));

Как перевести web интерфейс с кодировки cp1251 на utf8

Не удобно, когда файлы хранятся, в отличной от основной кодировке. Я тут опишу, как перевести интерфейс abills в кодировку utf8. База данных при этом остается в cp1251, что вобщем и не важно.
1. Правим файл /usr/abils/libexec/config.pl

#For MySQL 5 and highter 
$conf{dbcharset}='utf8';
$conf{MAIL_CHARSET}='utf8'; 
$conf{default_language}='russian'; 
$conf{default_charset}='utf-8';

2. Файл /usr/abills/Abills/XML.pm строка ~577

my $CHARSET=(defined($attr->{CHARSET})) ? $attr->{CHARSET} : 'utf-8';

3. Файл /usr/abills/Abills/defs.conf строка ~38

$lang_charset='utf-8';

4. Файл /usr/abills/Abills/HTML.pm сторока ~98

$self->{CHARSET}=(defined($attr->{CHARSET})) ? $attr->{CHARSET} : 'utf-8';

5. Спомощью команды iconv перекодируем файлы в директории /usr/abils/language/. Например, для файла russian.pl

iconv -fcp1251 -tutf8 russian.pl -orussian.pl1 
mv russian.pl1 russian.pl

И поменять в них $CHARSET=" windows-1251" на $CHARSET=" utf8", хотя работает и без этого.

Ну вот вроде и все.

Настройка подключения к Totol Control

Totol Control - это такая железяка в которую входят 16 модемов и система управления ими со своей ОС. К ней можно подключиться через сом кабкль эмулятором терминала VT100, а после установок сети и telnet оп сети. Пишу сдесь настройки, которые я делал, что бы не забыть потом.

Настройка сервера доступа

  • Система ---> Сервер доступа
IP IP адрес Totol Control
Название Название сервера (например NAS)
Тип Usr:USR Netserver 8/16
Авторизация SQL
Alive (sec) Обязательно 0
IP:PORT Адрес и порт SNMP Total Сontrol (порт обычно 161), но его можно не ставить
Пароль Пароль для доступа SNMP к Total Сontrol

Остальные настройки теже.

Изменения в коде программы

Правим пути к командам в файле /usr/abills/Abills/defs.conf для команд snmpwalk, bzip, mysqldump, ifconfig
Пути можно найти с помощью команды which, например

# which snmpwalk
/usr/bin/snmpwalk

Все изменения в файле /usr/abills/Abills/nas.pl
Вместо строк

 elsif ($nas_type eq 'usr') {
   hangup_snmp($NAS, $PORT, { OID   => '.1.3.6.1.4.1.429.4.10.13.'. $PORT,
                                 TYPE  => 'integer',
                                 VALUE => 9 });

Вставить

 elsif ($nas_type eq 'usr') {
   hangup_usr($NAS, $PORT, $attr);
  }

Вместо строк

#####################################################################
# USR Netserver 8/16
#*******************************************************************
# Get stats from USR Netserver 8/16
# get_usrns_stats($SERVER, $PORT)
#*******************************************************************
sub stats_usrns  {
  my ($NAS, $PORT) = @_;
  my $SNMP_COM = $NAS->{NAS_MNG_PASSWORD} || '';

#USR trafic taker
 my $in  = `a=\`$SNMPWALK -v 1 -c "$SNMP_COM" $NAS->{NAS_IP} interfaces.ifTable.ifEntry.ifInOctets.$PORT  |\
 awk '{print \$4}'\`; b=\`cat /usr/abills/var/devices/$NAS->{NAS_IP}-$PORT.In\`; c=\`expr \$a - \$b + 0\`;
 echo \$c`;
my $out = `a=\`$SNMPWALK -v 1 -c "$SNMP_COM" $NAS->{NAS_IP} interfaces.ifTable.ifEntry.ifOutOctets.$PORT  |\
 awk '{print \$4}'\`; b=\`cat /usr/abills/var/devices/$NAS->{NAS_IP}-$PORT.Out\`; c=\`expr \$a - \$b + 0\`;
 echo \$c`;
# $SNMPWALK -v 1 -c $SNMP_COM $SERVER interfaces.ifTable.ifEntry.ifInOctets.$PORT |\
awk '{print \$4}' `a=`$SNMPWALK -v 1 -c tstats 192.168.101.130 interfaces.ifTable.ifEntry.ifInOctets.$PORT |\
awk '{print \$4}'`; b=`cat /usr/abills/var/devices/$SERVER-$PORT.In`; c=`expr \$a - \$b + 0`; echo \$c`;
#
  $stats{in} = int($in);
  $stats{out} = int($out);

  return %stats;
}

Вставляем

#*******************************************************************
# HANGUP USR
# hangup_usr($SERVER, $PORT)
#*******************************************************************
sub hangup_usr {
    my ($NAS_IP, $PORT) = @_;
    $telnet_user = "!root";
    $telnet_pass = "passwd_telnet";
    push @commands, "login:\t$telnet_user";
    push @commands, "Password:\t$telnet_pass";
    push @commands, ">\treset S$PORT";
    push @commands, ">exit";

    my $result = telnet_cmd("$NAS->{NAS_IP}", \@commands);
    print $result;

    return 0;
      }


#####################################################################
# USR Netserver 8/16
#*******************************************************************
# Get stats from USR Netserver 8/16
# get_usrns_stats($SERVER, $PORT)
#*******************************************************************
sub stats_usrns  {
    my ($NAS, $PORT) = @_;
    my $SNMP_COM = $NAS->{NAS_MNG_PASSWORD} || '';
    #print  "Port =  $PORT\n";
    $PORT1 = $PORT + 2;
    #USR trafic taker

    my $in  = `a=\`$SNMPWALK -v 1 -c "$SNMP_COM" $NAS->{NAS_IP} interfaces.ifTable.ifEntry.ifInOctets.$PORT1 |awk 'print \$4}'\`;  echo \$a`;
    my $out = `a=\`$SNMPWALK -v 1 -c "$SNMP_COM" $NAS->{NAS_IP} interfaces.ifTable.ifEntry.ifOutOctets.$PORT1  |awk '{print \$4}'\`; echo \$a`;
    $stats{in}  = $in;
    $stats{out} = $out;
    $stats{error} = 0;
     if ( $in eq "\n" ) {
          if ( $out eq "\n" ){
            $stats{error} = 1;
            }
      }
        #elsif (int($in) + int($out) > 0) {
        #$stats{in}  = int($in);
        #$stats{out} = int($out);
        #       }

#print "$in\n$out\n";

    return %stats;
}

}
где passwd_telnet - пароль доступа по telnet

Файл /usr/abills/libexec/billd Была строка ~ 194

       elsif (defined($external_stats->{error})) {
        print "Error:  Login: $line->[0], NAS-IP: $NAS{NAS_IP}, Port: $line->[2], Session-ID: $acct_session_id\n" if ($debug == 1);
        $sessions->online_update({ USER_NAME       => $line->[0],
                                         ACCT_SESSION_ID => $acct_session_id,
                                         STATUS          => 5
                                      });
       }
      elsif (defined($external_stats->{in})) {
        $sessions->online_update({ USER_NAME => $line->[0], ACCT_SESSION_ID => $acct_session_id, %$external_stats });
       }
Стало
       elsif (($external_stats->{error}) == 1 ) {
        print "Error:  Login: $line->[0], NAS-IP: $NAS{NAS_IP}, Port: $line->[2], Session-ID: $acct_session_id\
n" if ($debug == 1);
        # Если и в предыдущий раз была ошибка, то убиваем сессию
            if ( $line->[18] == 5 )  {
                print "Kill session $line->[0]\nTime session $line->[9]\n ";
                print "Input traf  $acct_input_octets\nOutput traf $acct_output_octets\n";
                    my $ACCT_INFO = $sessions->online_info({ NAS_ID          => $nas_row->[0],
                                                    NAS_PORT        => $line->[2],
                                                    ACCT_SESSION_ID => $acct_session_id
                                                  });


                    $ACCT_INFO->{INBYTE}            = $acct_input_octets;
                    $ACCT_INFO->{OUTBYTE}           = $acct_output_octets;
                    $ACCT_INFO->{INBYTE2}           = $acct_input_octets_ext;
                    $ACCT_INFO->{OUTBYTE2}          = $acct_output_octets_ext;
                    $ACCT_INFO->{ACCT_STATUS_TYPE}  = 'Stop';
                    $ACCT_INFO->{ACCT_SESSION_TIME} = $line->[9];
                    $ACCT_INFO->{ACCT_TERMINATE_CAUSE} = 15;

                    my $r = $Acct->accounting($ACCT_INFO, \%NAS);
                    my $info = '';

             }
            # Устанавливаем статус ошибки (5) и пишем его в базу.
            else    {
        #       print "Error session $line->[0]\n";
                $sessions->online_update({ USER_NAME       => $line->[0],
                                 ACCT_SESSION_ID => $acct_session_id,
                                 STATUS          => 5
                                  })
                                  };


       }
      elsif (defined($external_stats->{in})) {
        $sessions->online_update({ USER_NAME => $line->[0],
                                ACCT_SESSION_ID => $acct_session_id,
                                STATUS          => 1,
                                %$external_stats
                                });