Причина сообщений «HTB: quantum of class 10001 is big. Consider r2q change»

Однажды на сервере доступа Ubuntu Server 16.04 и Accel-ppp заметил в файле /var/log/kern.log следующие сообщения:

kernel: [365970.550498] HTB: quantum of class 10001 is big. Consider r2q change.
kernel: [365970.550547] HTB: quantum of class 10A49 is big. Consider r2q change.
kernel: [365979.545580] HTB: quantum of class 10001 is big. Consider r2q change.
kernel: [365979.545621] HTB: quantum of class 10BD6 is big. Consider r2q change.
kernel: [365995.601973] HTB: quantum of class 10001 is big. Consider r2q change.
kernel: [365995.602031] HTB: quantum of class 11705 is big. Consider r2q change.

Сначала попробовал отследить какие в этот момент поднимаются интерфейсы:

tail -f /var/log/kern.log | grep "quantum of class 10001 is big"
tail -f /var/log/accel-ppp/accel-ppp.log | grep "create interface"

Но как оказалось, в конфигурации /etc/accel-ppp.conf, в секции шейпера, не был указан quantum, а если его не указать, то он высчитывается.
По этому я открыл файл конфигурации Accel-ppp:

sudo nano /etc/accel-ppp.conf

И указал его:

[shaper]
quantum=1500
#moderate-quantum=1

Также изменил up-limiter с «htb» на «police» для лучше производительности, а также чтоб правильно резалась скорость при большом количестве сессий (при 3000+ ipoe сессиях с htb начались проблемы, скорость отправки падала до 1 Мб/сек):

#up-limiter=htb
up-limiter=police

Чтобы применить изменение для новых сессий не обрывая активные, заставим Accel-ppp перечитать файл конфигурации:

telnet 127.0.0.1 2000
reload

Или перезагрузим Accel-ppp, но при этом оборвутся все сессии:

sudo /etc/init.d/accel-ppp restart

После этого ошибка исчезла.

Смотрите также мою статью — Сборка и установка accel-ppp

SQL запросы для ABillS

В этой статье я приведу примеры некоторых SQL запросов для базы биллинговой системы ABillS.

Первым делом подключимся к MySQL серверу и перейдем к базе abills (либо можно использовать phpmyadmin или внешний MySQL клиент):

mysql -u root
use abills;

Указать DNS и очистить во всех IP POOLs (Настройка>Сервер доступа>IP POOLs) можно sql такими запросами:

update ippools SET dns='8.8.8.8,8.8.4.4';
update ippools SET dns='';

Изменить логин пользователю можно так:

update users set id='new_login' where id='old_Login';

Посчитать количество пользователей:

SELECT count(*) FROM users;

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

SELECT count(*) FROM users WHERE credit>0 AND credit_date="0000-00-00";

Количество пользователей с указанной скидкой без даты окончания скидки:

SELECT count(*) FROM users WHERE reduction>0 AND reduction_date="0000-00-00";

Количество пользователей с указанной датой активации для учетной записи:

SELECT count(*) FROM users where activate<>0000-00-00;

Количество сервисов для пользователей и количество сервисов в которых указана маска 255.255.255.255:

SELECT COUNT(*) FROM internet_main;
SELECT count(*) FROM internet_main where netmask=4294967295;

Количество сервисов в которых маска не равна 255.255.255.255:

SELECT count(*) FROM internet_main where netmask<>4294967295;

Количество сервисов в которых не указана дата активации:

SELECT count(*) FROM internet_main WHERE activate=0000-00-00;

Количество учетных записей в которых указана дата активации:

SELECT count(*) FROM users where activate<>0000-00-00;

Чтобы абонентов не отключало если на счету 0 и тариф оплачен:

SELECT * FROM tarif_plans where credit=0.00 LIMIT 200;
UPDATE tarif_plans SET credit='0.01' where credit=0.00;

Подсчет количества тарифов на которых не разрешено устанавливать скидку и включение скидки на всех тарифах:

SELECT count(*) FROM tarif_plans WHERE reduction_fee=0;
UPDATE tarif_plans SET reduction_fee=1 WHERE reduction_fee=0;

Тарифы в которых не выбрано действие при недостаточном депозите, и тарифы в котором выбрано «Приостановление»:

SELECT * FROM tarif_plans WHERE small_deposit_action=0;
SELECT count(*) FROM tarif_plans WHERE small_deposit_action='-1';

Тарифы в которых указан или не указан фильтр негативного депозита:

SELECT count(*) FROM tarif_plans WHERE neg_deposit_filter_id='NEG_DEPOSIT';
SELECT count(*) FROM tarif_plans WHERE neg_deposit_filter_id='';
SELECT * FROM tarif_plans WHERE neg_deposit_filter_id='';

Просмотр всего списка платежей и по конкретному типу (например 65 это Privat-Terminal):

SELECT * FROM payments LIMIT 750;
SELECT * FROM payments WHERE method=65;

Просмотр логинов и паролей в расшифрованном виде («secretkey» смотрим в config.pl):

SELECT id, DECODE(password, 'secretkey') FROM users;
SELECT id, DECODE(password, 'secretkey') FROM users WHERE uid=11;

Количество Zap сессий:

SELECT count(*) FROM internet_online WHERE status=2;

Количество гостевых сессий:

SELECT count(*) FROM internet_online where guest=1;

Количество всех сессий:

SELECT count(*) FROM internet_online WHERE (status=1 or status>=3);

Количество сессий без гостевых и Zap:

SELECT count(*) FROM internet_online WHERE (status=1 or status>=3) AND guest=0;

Выборка IP из онлайн сессий:

SELECT INET_NTOA(framed_ip_address) FROM internet_online WHERE (status=1 or status>=3) AND guest=0;

Смотрите также мой скрипт ipset — Скрипт добавления IP адресов из файла в ipset

Размер базы данных:

SELECT SUM( data_length + index_length ) AS 'size' FROM information_schema.TABLES WHERE table_schema = 'abills' LIMIT 1;

Количество сервисов для пользователей с определенным статусом (0 — Активно, 1 — Отключено, 2 — Не активизирован, 3 — Приостановление, 4 — Отключено: Неуплата, 5 — Cлишком маленький депозит):

SELECT count(*) FROM internet_main WHERE disable=0;

Изменение формата телефонов:

UPDATE users_pi SET phone=REPLACE(phone, '+38050', '050') WHERE phone like '+38050%';

Скрипт добавления IP адресов из файла в ipset

Понадобилось однажды написать скрипт чтобы добавить в ipset все IP для которых били подняты сессии на сервере доступа, использовался биллинг Abills, поэтому я решил взять IP адреса из MySQL таблицы биллинга.

Первым делом создадим тестовый ipset:

ipset create test iphash

Создадим файл скрипта:

nano iplist.sh

Добавим в него содержимое:

mysql -u root -e "SELECT INET_NTOA(framed_ip_address) FROM abills.internet_online WHERE (status=1 or status>=3) AND guest=0;" -s -N > iplist.txt
iplist_data=$(cat iplist.txt)
for row_data in $iplist_data; do ipset -exist add test ${row_data}; done
rm iplist.txt

Выполняем скрипт и проверяем:

chmod +x iplist.sh
./iplist.sh
ipset list test | wc -l
ipset -L

Решение ошибки «Another app is currently holding the xtables lock»

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

Another app is currently holding the xtables lock. Perhaps you want to use the -w option?

Посмотрев код скрипта обнаружил, что среди iptables правил есть два, которые могут тормозить работу, а именно выполнялся поиск ipoe интерфейсов двумя командами:

IPTABLES="/sbin/iptables"
EXIST=`${IPTABLES} -t nat -L PREROUTING -v | grep "${IFNAME} ";  ${IPTABLES} -L -v | grep DROP | grep "${IFNAME} "`

Для поднятия 3000 сессий, уходило более 30 минут и часть правил могла вовсе не добавится или не удалится скриптом.
По умолчанию если используется ключ -L то iptables резолвит IP адреса и пытается отобразить вместо них DNS имена, что занимает много времени, и чтобы это не происходило, нужно добавить еще ключ -n, а также на всякий случай я добавил ключ -w 20, который заставит отложить выполнение новых правил до 20 секунд если iptables уже занят выполнение другой команды:

IPTABLES="/sbin/iptables"
IPTABLES_WAIT="-w 20"
EXIST=`${IPTABLES} $IPTABLES_WAIT -t nat -n -L PREROUTING -v | grep "${IFNAME} ";  ${IPTABLES} $IPTABLES_WAIT -n -L -v | grep DROP | grep "${IFNAME} "`

После этого скрипт с iptables правилами начал отрабатывать мгновенно.
Так как старые правила не все выполнились, я проверил это посчитав некоторые командой:

iptables -n -L -t nat -v | grep DNAT | wc -l

И сверил с количеством сессий, правил явно было меньше, поэтому пришлось очистить все правила и перезапустить сессии чтобы скрипт /etc/ppp/ip-up отработал правильно, на этот раз при 3000 сессиях он сделал свою работу менее чем за минуту.
Замечу что в скриптах /etc/ppp/ лучше не использовать правила iptables.

Установка модуля Netlist для ABillS

На тесте установлю модуль Netlist для ABillS в Ubuntu Server.

Импортируем таблицы в базу:

mysql -D abills --default-character-set=utf8 < /usr/abills/db/Netlist.sql

Откроем файл конфигурации биллинга:

nano /usr/abills/libexec/config.pl

Убедимся что активирован модуль:

@MODULES = (
          'Netlist'
          );

Установим nmap и Perl модуль для него:

sudo apt-get install nmap
sudo cpanm Nmap::Parser

Посмотрим где находится nmap:

which nmap

Снова откроем файл конфигурации биллинга:

sudo nano /usr/abills/libexec/config.pl

Укажем путь к nmap:

$conf{'NMAP_LOCATION'}="/usr/bin/nmap";

Добавим в sudoers:

echo 'www-data ALL=(ALL) NOPASSWD: /usr/bin/nmap' >> /etc/sudoers.d/abills_sudoers

После установки модуль будет доступен в меню /Настройка/Netlist

Настройка FreeRADIUS DHCP для ABillS

Допустим установлен FreeRADIUS 2 как написано в этой статье — Установка и настройка биллинговой системы ABillS
Теперь скопируем файл dhcp.conf в конфигурацию FreeRADIUS:

sudo cp /usr/abills/misc/freeradius/v2/dhcp.conf /usr/local/freeradius/etc/raddb/sites-enabled/

Читать далее Настройка FreeRADIUS DHCP для ABillS

Сброс пароля администратора ABillS

Для сброса пароля администратора необходимо выполнить следующий SQL запрос в базу данных ABillS:

UPDATE admins SET password=ENCODE('NEW_PASSWORD', 'test12345678901234567890') WHERE aid=1;

Где test12345678901234567890 переменная $conf{secretkey} в файле /usr/abills/libexec/config.pl.

Настройка маскарадинга (NAT) в Ubuntu

Для примера выполню настройку маскарадинга IPv4 (NAT) на Ubuntu Server.
Сначала нужно включить поддержку пересылки пакетов в /etc/sysctl.conf, чтобы трафик мог ходить между разными сетевыми интерфейсами.
Проверим текущее состояние:

sysctl net.ipv4.conf.all.forwarding
cat /proc/sys/net/ipv4/ip_forward

Если оно равно 0, то включим следующей командой:

sysctl -w net.ipv4.conf.all.forwarding=1

Чтобы после перезапуска системы оно не сбросилось, откроем файл /etc/sysctl.conf например в редакторе nano (Ctrl+X для выхода, y/n для сохранения или отмены изменений):

nano /etc/sysctl.conf

И добавим строку:

net.ipv4.conf.all.forwarding=1

При необходимости можно очистить существующие NAT правила:

iptables -t nat --flush

Теперь осталось в iptables добавить правило маскарадинга, например:

iptables -t nat -A POSTROUTING -s 192.168.99.0/24 -j SNAT --to-source 172.16.16.94

Где, 192.168.99.0/24 внутренняя сеть, а 172.16.16.94 адрес через который нужно идти в интернет, аналогично прописываются другие внутренние сети.
Не забываем сохранить добавленные правила iptables.
Например можно открыть файл конфигурации сетевых интерфейсов (его содержимое подгружается при запуске системы):

nano /etc/network/interfaces

И в конце добавлять правила iptables, например укажу маскарадинг этой сети сразу на несколько IP адресов, а также с указанием сетевого интерфейса:

post-up /sbin/iptables -t nat -A POSTROUTING -s 192.168.99.0/24 -o eth3 -j SNAT --to-source 172.16.90.1-172.16.90.5 --persistent

Смотрите также:
Настройка IPTables
Решение ошибки «nf_conntrack: table full, dropping packet»
Использование Linux ISG

Установка ISC DHCP для ABillS

Приведу пример установки ISC DHCP сервера для ABillS в Ubuntu Server.

Переключимся на root пользователя:

sudo su

Установим пакет:

apt-get install isc-dhcp-server
ln -s /usr/abills/Abills/modules/Dhcphosts/leases2db.pl /usr/abills/libexec/leases2db.pl

Запускаем:

/usr/abills/libexec/leases2db.pl -d LEASES=/var/lib/dhcp/dhcpd.leases

Изменим владельца файла:

chown www-data /etc/dhcp/dhcpd.conf

Откроем config.pl в редакторе:

nano /usr/abills/libexec/config.pl

Добавим параметры:

$conf{DHCPHOSTS_CONFIG}='/etc/dhcp/dhcpd.conf';
$conf{DHCPHOSTS_LEASES}='/var/lib/dhcp/dhcpd.leases';
$conf{DHCPHOSTS_RECONFIGURE}='/usr/bin/sudo /etc/init.d/isc-dhcp-server restart';

Откроем в редакторе:

nano /etc/sudoers

Добавим строку сделав возможность запуска сервиса системой:

www-data   ALL = NOPASSWD: /etc/init.d/isc-dhcp-server

Заходим в веб интерфейс Abills, открываем меню «Настройка» — «IP (DHCP) Сети» — «IP (DHCP) Сети«, добавляем сети если необходимо, потом «Показать dhcp.conf, Переконфигурировать» и «Переконфигурировать«.

Посмотреть запущен ли isc-dhcp-server можно командой:

/etc/init.d/isc-dhcp-server status
netstat -tulpn | grep :67

Логи пишутся в файл /var/log/syslog

Можно также настроить экспорт DHCP истории, чтобы видеть её в меню «Отчёт» — «DHCP История».
Для этого сделаем ссылку:

ln -s /usr/abills/Abills/modules/Dhcphosts/dhcp_log2db.pl /usr/abills/libexec/dhcp_log2db.pl

Отделив DHCP логи в отдельный файл как я писал в статье ниже и добавив в автозагрузку скрипт с командой:

tail -F /var/log/dhcpd.log | /usr/abills/libexec/dhcp_log2db.pl

Смотрите также:
Установка и настройка isc-dhcp-server в Ubuntu

Добавление vlan в Ubuntu для ABillS

Приведу пример добавления VLAN в Ubuntu Server для ABillS.

Переключимся на пользователя root:

sudo su

Первым делом установим пакет vlan и загрузим модуль 8021q:

apt-get install vlan
modprobe 8021q

Для его автозагрузки после перезапуска системы откроем файл /etc/modules, напрмиер в текстовом редакторе nano (Ctrl+X для выхода, y/n для сохранения или отмены изменений):

nano /etc/modules

И добавим если его там нет:

8021q

Создадим скрипт:

nano /etc/network/vlan.sh

Добавим в него содержимое (в IFACE указываем сетевой интерфейс для vlan, во VLANS — перечень VLAN):

#!/bin/bash
IFACE="eth1"
VLANS="51,200-350,700-1000"

  /sbin/vconfig set_name_type VLAN_PLUS_VID_NO_PAD
  VLANS=`echo ${VLANS} | sed 'N;s/\n/ /' |sed 's/,/ /g'`
  for i in $VLANS; do
    if [[ $i =~ - ]]; then
      IFS='-' read -a start_stop <<< "$i"
      for cur_iface in `seq ${start_stop[0]} ${start_stop[1]}`;
      do
        echo "${cur_iface}";
        /sbin/vconfig add ${IFACE} ${cur_iface}
        /sbin/ifconfig vlan${cur_iface} up
      done
    else
    echo "$i";
      /sbin/vconfig add ${IFACE} ${i}
      /sbin/ifconfig vlan${i} up
    fi;
  done

Делаем скрипт исполняемым:

chmod +x /etc/network/vlan.sh

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

/etc/network/vlan.sh

Для автозапуска скрипта откроем конфигурацию сетевых интерфейсов:

nano /etc/network/interfaces

И добавим в конце строку:

post-up /etc/network/vlan.sh

Смотрите также:
Настройка VLAN в Ubuntu Server