полезное по линуксу и iphone собрано все интересное мне лично (методом copy-paste из инета и не пыхтите насчет копирайта я ссылки на источник ставлю)

вторник, 30 ноября 2010 г.

Еще один способ отбиться от небольшого DDOS

Все нижеописанное относится к GNU/Linux 2.6.x. ДДОС совершенно тупой, разномастный: syn/tcp/udp/icmp flood тупо на все открытые порты, мегабит на 60. UDP срали вообще куда попало. Но основная атака конечно на HTTP. По этому, тушим сервисы и пишем….

Немного sysctl…

vm.min_free_kbytes=70000
net.core.somaxconn=65536
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.ip_local_port_range = 2000 61000
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_timestamps = 0
net.core.rmem_max=16777216
net.core.wmem_max=32777216
net.ipv4.tcp_no_metrics_save=0
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 187380 32777216
net.core.netdev_max_backlog=16384
net.ipv4.tcp_max_syn_backlog=4096
net.ipv4.ip_conntrack_max=600000
net.ipv4.icmp_echo_ignore_all=1
net.ipv4.netfilter.ip_conntrack_max=500000
net.netfilter.nf_conntrack_max=500000
Не забываем перезапустить Network.

Немного iptables….

# Форвард нам нэ нада
iptables -P FORWARD DROP
# BAN – цепочка для помещения туда айпи хостов, ведущих себя не правильно ) Ну типа
# iptables – I BAN -s 123.123.123.123 -j DROP
iptables -N BAN
# TRUSTED – цепочка для помещения туда правильных хостов и хостов откуда мы сидим в шелле. Типа
# iptables -I TRUSTED -s 111.111.111.111 -j ACCEPT
iptables -N TRUSTED
# Стандартный заголовок, eth1 – наш интерфейс внешний
# если есть еще интерфейсы, надо их тоже запрячь правилами разрешения как у lo
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -m state –state ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth1 -m state –state RELATED -j ACCEPT
# Проход по белым и черным цепочкам
iptables -A INPUT -i eth1 -j TRUSTED
iptables -A INPUT -i eth1 -j BAN
# У меня висит только сервис http, по этому здесь такая себе мини защита по данному порту
# Насчет –seconds 10 –hitcount 10, курим маны, экспериментируем, ставим то, что подойдет.
# Режем всех TCP на порту 80, которые за последние 10 секунд сделали 10 попыток открыть соединение
# (кому то может не подойти!)
iptables -A INPUT -p tcp -m tcp –dport 80 -m state –state NEW -m recent –update –seconds 10 –hitcount 10 –name httpd –rsource -j DROP
# А остальных разрешаем
iptables -A INPUT -i eth1 -p tcp -m tcp –dport 80 -j ACCEPT
# Вот по этой теме ддосеры тоже затрахали, по этому был категоричен
iptables -A OUTPUT -p udp -j DROP
iptables -A OUTPUT -p icmp -j DROP
# Здесь добавить разрешения на прочие порты, у меня прочих не было
# …
# Здесь добавить (!!!) свои айпи, с которых сидишь в шелле
iptables -A TRUSTED -s 111.111.111.111 -j ACCEPT
# Хорошо подумаем, покурим, затаим дыхание и напишем….
iptables -P INPUT DROP
# Что означает зарезать все, что не разрешили на INPUT’е
А теперь запускаем nginx/httpd и прочую лабуду. Надеюсь заработает. У меня заработало, как будто ничего и не происходило :) 
 
Оригинал: http://www.pentarh.com/wp/2010/08/11/%d0%95%d1%89%d0%b5-%d0%be%d0%b4%d0%b8%d0%bd-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1-%d0%be%d1%82%d0%b1%d0%b8%d1%82%d1%8c%d1%81%d1%8f-%d0%be%d1%82-%d0%bd%d0%b5%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be%d0%b3/

Отбил небольшой DDOS ;)

DDOS на HTTP 20 Мбит входящего. Отбито софтварным костылем 8-)
Конфигурация машины: Quad Core Xeon / 4G RAM, CentOS 5.3 x86_64
Сервисы: apache(back) + nginx(front)
Sysctl:
kernel.shmall = 4294967296
vm.min_free_kbytes=70000
net.core.somaxconn=65536
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.ip_local_port_range = 2000 61000
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_timestamps = 0
net.core.rmem_max=8388608
net.core.wmem_max=16777216
net.ipv4.tcp_no_metrics_save=0
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
net.core.netdev_max_backlog=65536
net.ipv4.tcp_max_syn_backlog=4096
net.ipv4.ip_conntrack_max=300000
nginx:
worker_rlimit_nofile 80000;
events {
worker_connections  65536;
use epoll;
}
http {
gzip off; # ;)
keepalive_timeout  0;
server_tokens off;
reset_timedout_connection on;
server {
listen x.x.x.x default deferred;
log_format IP $remote_addr;
location / {
proxy_pass http://127.0.0.1/;
….
access_log /var/log/nginx/ipban IP;
apache: ServerLimit и MaxClients установить так, чтобы не засрало более чем 80% памяти. (В top’е можно глянуть сколько памяти потребляет каждый процесс).
Собсно скрипт. Запускается по крону раз в минуту и банит нах айпи, которые за эту минуту обратились к скриптовой части более 20 раз.
#!/usr/bin/perl
system(‘mv /var/log/nginx/ipban /var/log/nginx/ipban.proc’);
system(‘touch /var/log/nginx/ipban’);
system(«/etc/init.d/nginx reload»);
open $f,’/var/log/nginx/ipban.proc’;
%h=();
while(<$f>) {
chomp;
if (/\d+\.\d+\.\d+\.\d+/) {
unless ($h{$_}) {
$h{$_}=1;
} else {
$h{$_}++;
}
}
}
close $f;
foreach $k (keys(%h)) {
if ($h{$k} > 20) {
system(«iptables -I INPUT -s $k -j DROP»);
print «$k banned\n»;
}
}
20 -число вычисленное в ходе проб и ошибок применительно к этому серверу и location’у nginx. После того как скрипт беспощадно побанил 2к хостов, сервер начал подавать внешние признаки жизни, после 3к забаненых зомби начала грузицца морда.
В процессе работы мой рабочий комп был дважды забанен в ходе экспериментов ))
Более серъезный DDOS конечно будет трудно отбивать тупой банилкой.
АПДЕЙТ. Время шло, таблица бана росла, ддосеры не унимались.
Поставил вот эту хрень http://www.configserver.com/cp/csf.html
Софтина умеет вообще много чего. Но практически все что она умеет бесполезно. Кроме temporary ban ip address.
В конфигах отключил практически все, ибо оно (все) мешало. Мне надо было от этой проги только то, чтобы она банила айпи с TTL. Т.е. на время. И крон стал пускать раз в 5 минут.
Соответственно, в кроновом скрипте поменял
if ($h{$k} > 20) {
system(«iptables -I INPUT -s $k -j DROP»);
На
if ($h{$k} > 60) {
system(«/usr/sbin/csf –tempdeny $k 28800″);
Так же цель атаки – страницу, сделал статичной.  ДДОС просел, сайт ожил.

Оригинал  http://www.pentarh.com/wp/2009/05/02/%d0%9e%d1%82%d0%b1%d0%b8%d0%bb-%d0%bd%d0%b5%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be%d0%b9-ddos/

пятница, 26 ноября 2010 г.

IPoE, а также Client-VLAN и DHCP Option 82

В этой статье я опишу что из себя представляет технология доступа в Интернет IPoE, которой на самом деле не существует. А также расскажу про схему Client-VLAN и про опцию 82 DHCP (DHCP Option 82), которые стали неотъемлемой частью этой несуществующей технологии. Все это, конечно же, с технической точки зрения и с примерами конфигов.

Существует множество технологий доступа в Интернет для конечных абонентов. В России особенно популярны две: PPTP и PPPoE. В обоих случаях создается PPP-туннель, производится аутентификация, и внутри туннеля ходит абонентский IP-трафик. Основное отличие этих протоколов – они работают на разных уровнях сетевой модели OSI. PPPoE работает на втором (канальном) уровне, добавляя специальные теги, идентифицирующие конкретный туннель, в Ethernet-фреймы. PPTP работает на третьем (сетевом) уровне, упаковывая IP-пакеты в GRE.


IPoE


IPoE принципиально отличается от PPTP и PPPoE. Вообще этой технологии не существует. Нет RFC, нет никаких стандартов ее описывающих. Сам термин придуман, скорее всего, в России и является абстрактным. Означает он следующее: IP over Ethernet. Смысл именно такой, как и расшифровка – IP-трафик поверх Ethernet, грубо говоря, обычная локалка. Абоненту выдается в лучшем случае статический или динамический белый IP-адрес, в худшем случае серый IP с NAT. Контроль доступа в данном случае может осуществляется при помощи привязок IP-MAC на коммутаторах доступа или на BRAS или выделения VLAN на каждого абонента (так называемый Client-VLAN).

Client-VLAN


При использовании технологии Client-VLAN возникает проблема: как сэкономить IP-адреса? Ведь, если подумать, каждому клиенту надо выделять /30 подсеть. На самом деле проблема легко решаема. Привожу пример для маршрутизатора на базе Linux:
ip route add unreachable 192.0.2.0/24
ip addr add 192.0.2.1/32 dev lo

vconfig add eth0 101
ip link set eth0.101 up
ip route add 192.0.2.101/32 dev eth0.101 src 192.0.2.1

Подсеть 192.0.2.0/24 рекомендована IANA для использования в примерах.

Это классический Cisco'вский ip unnumbered в Linux'овой реализации. IP шлюза (192.0.2.1) вешается на loopback-интерфейс, делается unreachable для всей подсети, чтобы пакеты ходили только на хосты, для которых прописан роутинг. Далее поднимается VLAN и прописывается роутинг на конкретный хост (маска /32) с src шлюза. А можно сделать немного иначе (это лишний раз демонстрирует гибкость Linux):
ip route add unreachable 192.0.2.0/24

vconfig add eth0 101
ip link set eth0.101 up
ip addr add 192.0.2.1/32 dev eth0.101
ip route add 192.0.2.101/32 dev eth0.101

Или так:
ip route add unreachable 192.0.2.0/24

vconfig add eth0 101
ip link set eth0.101 up
ip addr add 192.0.2.1/24 dev eth0.101
ip route del 192.0.2.0/24 dev eth0.101
ip route add 192.0.2.101/32 dev eth0.101

Все эти варианты работают, можно выбрать тот, при котором интерфейсы отображаются наиболее удобным образом. Во всех случаях IP абонента – 192.0.2.101/24.

Proxy_arp


Еще одна проблема, с которой вы можете столкнуться – нет связи между абонентами в разных VLAN и с IP из одной подсети. Действительно, система абонента видит, что IP-адрес назначения в одной подсети с ней, и шлет ARP-запросы, чтобы определить MAC, но из этого ничего не выходит, т.к. они в разных VLAN. Для решения этой проблемы служит технология proxy_arp. Суть ее в том, что маршрутизатор при получении ARP-запросов с интерфейса будет проверять есть ли у него запрашиваемый IP на других интерфейсах. Если есть, то в ответ на ARP-запрос выдаст свой MAC. Таким образом, пакеты будут отправляться на маршрутизатор, который позаботится об их доставке. Включается proxy_arp для конкретного интерфейса следующим образом:
sysctl net.ipv4.conf.eth0/101.proxy_arp=1

или
echo 1 > /proc/sys/net/ipv4/conf/eth0.101/proxy_arp


DHCP Option 82


При использовании IPoE DHCP упростит настройку сети на стороне абонента до нуля. Воткнул патчкорд и ты в сети. Только возникает вопрос: как DHCP узнает кому какой адрес выдавать? Можно определять по MAC, особенно если вы уже используете привязки IP-MAC. Но привязки MAC чреваты частыми звонками в поддержку, т.к. абоненты иногда меняют оборудование. Справиться с этой проблемой поможет расширение протокола DHCP – Option 82. Опция 82 содержит два поля:
  • Agent Circuit ID – номер порта DHCP-релэя, на который пришел DHCP-запрос.
  • Agent Remote ID – некий идентификатор самого DHCP-релэя.

В качестве DHCP-релэев при этом обычно выступают коммутаторы доступа, к которым непосредственно подключаются абоненты. В качестве Agent Remote ID обычно используется MAC коммутатора (по умолчанию в D-Link). Опция 82 поддерживается широким диапазоном оборудования, в том числе типичными у российских провайдеров D-Link DES-3526/3028/3200.
На коммутаторах D-Link есть два режима DHCP-релэя: dhcp_relay и dhcp_local_relay. dhcp_relay работает глобально, для всех портов и VLAN, при этом добавляется опция 82 и запрос передается уже не бродкастом, а непосредственно на DHCP-сервер, т.е. это полноценный DHCP-релэй. dhcp_local_relay работает для конкретных VLAN, но запрос по сути не релэится, а в него просто добавляется опция 82.
Базовые настройки dhcp_relay на D-Link'ах:
enable dhcp_relay
config dhcp_relay option_82 state enable
config dhcp_relay add ipif System 192.168.0.1

192.168.0.1 – IP-адрес DHCP-сервера, доступного в управляющем VLAN.
Базовые настройки dhcp_local_relay:
enable dhcp_local_relay
config dhcp_local_relay vlan 101 state enable

И наконец приведу базовый конфиг для ISC's DHCP с комментариями:
# пишем в лог
log(info, "***");
if exists agent.circuit-id {
 # присутствует опция 82
 # пишем в лог выданный IP-адрес, Agent Remote ID, Agent Circuit ID
 log( info,concat("*Leased ",binary-to-ascii(10,8,".",leased-address)," (with opt82)") );
 log( info,concat("*Remote-ID: ",binary-to-ascii(16,8,":",substring(option agent.remote-id,2,6))) );
 log( info,concat("*Port: ",binary-to-ascii(10,8,"",suffix(option agent.circuit-id,1))) );
} else {
 # опции 82 нет
 # пишем в лог выданный IP-адрес
 log( info,concat("*Leased ",binary-to-ascii(10,8,".",leased-address)," (without opt82)") );
}
log(info, "***");


# в данном примере 192.0.2.101/24 - IP абонента, подключенного к коммутатору с MAC 0:c:29:ec:23:64, на порт 1
# MAC-адрес левый, взят с виртуалки VMWare
# 192.168.0.0/24 - подсеть управления коммутаторами, с адресов в этой подсети будут приходить DHCP-запросы
# эти две подсети следует объединить в одну shared-network для корректной работы

shared-network test {

subnet 192.0.2.0 netmask 255.255.255.0 {

 # определяем класс

 class "v101" {

  # определяем условия соответствия классу:
  # Agent Circuit ID = 1, Agent Remote ID = 0:c:29:ec:23:64
  # обратите внимание - ведущие нули в Agent Remote ID не пишутся (т.е. c вместо 0c и т.д.)

  match if (binary-to-ascii(10,8,"",suffix(option agent.circuit-id,1)) = "1") and
   (binary-to-ascii(16,8,":",substring(option agent.remote-id,2,6)) = "0:c:29:ec:23:64");
 }

 # собственно выдаем IP классу

 pool {
  range 192.0.2.101;
  allow members of "v101";
 }
}

subnet 192.168.0.0 netmask 255.255.255.0 {
}
}
 
 
Источник: http://habrahabr.ru/blogs/sysadm/108453/ 

Шейпирование трафика в Linux. Часть 2

Вторая часть статьи об управлении трафиком в Linux. В статье приведены примеры приоретизации трафика (QoS) и рассказано об использовании hash таблиц при фильтрации трафика (fast hash tables), использование которых позволяет существенно увеличить производительность.
В первой части мы остановились на генерации конфигов средней сложность для htbinit. Сегодня мы поговорим о приоретизации трафика и использовании хэш таблиц в фильтрах. Я подразумеваю, что Вы прочитали первую часть статьи .
Предположим, что нам надоели замечания пользователей о высоком пинге, надоели постоянные детские вопли на форуме о том, что в counter-strike играть невозможно: «лаги страшные», или «у меня странички медленно грузятся, вконтакте открывался 10 минут», а писать что все замеры нужно производить при отключенном «торренте» уже нету сил.
Посему тто бы наша совесть была чиста, и мы могли не кривя душой сказать: «проблема на стороне провайдера предоставляющего данный сервис»(обозначить направление движения в сторону южного полюса) — озаботимся приоретизацией трафика.

Приоритеты выставим в таком порядке:
1. icmp
2. udp
3. tcp port 80
4. bulk traffic

Рассмотрим ограничение полосы на внутреннем интерфейсе, управлять будем «скоростью скачивания».
Напомню.
В простом варианте изложения алгоритм нарезки трафика выглядит так:
1. Создаем корневую дисциплину для интерфейса и указываем класс куда будет попадать не классифицированный трафик.
2. Создаем корневой класс и определяем ширину канала.
3. Создаем дочерний класс для шейпирования абонента.
4. Создаем дисциплину шейпирования для класса абонента.
5. Создаем фильтра позволяющие классифицировать трафик абонента.

Пример

#!/bin/bash

#"Очищаем" интерфейс eht1
/sbin/tc qdisc del dev eth1 root handle 1: htb default 15
#Создаем заново дисциплину и указываем дефолтный класс
/sbin/tc qdisc add dev eth1 root handle 1: htb default 15
#Создаем общий для клиентов класс
/sbin/tc class add dev eth1 parent 1: classid 1:1 htb rate 10Mbit ceil 10Mbit

#Создаем корневой класс клиента
/sbin/tc class add dev eth1 parent 1:1 classid 1:10 htb rate 512kbit ceil 512kbit

#Создаем 4 подкласса для каждого из видов трафика
/sbin/tc class add dev eth1 parent 1:10 classid 1:11 htb rate 1kbit ceil 512kbit prio 1
/sbin/tc class add dev eth1 parent 1:10 classid 1:12 htb rate 1kbit ceil 512kbit prio 2
/sbin/tc class add dev eth1 parent 1:10 classid 1:13 htb rate 1kbit ceil 512kbit prio 3
/sbin/tc class add dev eth1 parent 1:10 classid 1:14 htb rate 1kbit ceil 512kbit prio 4

#Создаем дисциплины шейпирования для конечных классов
/sbin/tc qdisc add dev eth1 parent 1:11 handle 11: sfq perturb 10
/sbin/tc qdisc add dev eth1 parent 1:12 handle 12: sfq perturb 10
/sbin/tc qdisc add dev eth1 parent 1:13 handle 13: sfq perturb 10
/sbin/tc qdisc add dev eth1 parent 1:14 handle 14: sfq perturb 10

Создаем 4 фильтра, для каждого из видов трафика
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 1 u32 match ip dst 192.168.2.2/32 match ip protocol 1 0xff flowid 1:11
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 2 u32 match ip dst 192.168.2.2/32 match ip protocol 17 0xff flowid 1:12
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 3 u32 match ip dst 192.168.2.2/32 match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:13
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 4 u32 match ip dst 192.168.2.2/32 flowid 1:14


* This source code was highlighted with Source Code Highlighter.


Думаю из примера видно, что для реализации приоретизиции трафика мы создали для каждого отдельный класс. Далее создаем фильтры, причем чем меньше prio, тем больше у трафика приоритет. Вообще правила обрабатываются согласно тому как их добавляли, в случае с приоритетами — первыми обслуживаются правила, имеющие наивысший приоритет.
Так же вы можете каждому из классов обзначить RATE равный одной четвертой от RATE корневого класса клиента, что бы уже наверняка.
Хочу обратить внимание, на то что нам пришлось создать 4 фильтра, для оного ип, а если ип 3-4 тысячи, то получим огромный линейный список правил — в итоге производительность упадет ниже плинтуса.
Что бы этого избежать воспользуемся «быстрыми» хэш таблицами.
О том, что такое хэш таблицы Вы можете посмотреть на Википедии.
Создадим 4 таблицы по 256 ячеек, каждая из таблиц будет оценивать один из октетов ип адреса.
И в конечном итоге, вместо поиска по всему списку, как это было бы в классическом варианте, мы уменьшим количество проверок и значительно снизим нагрузку.
Пример.
#Создаем корневой фильтр
/sbin/tc filter add dev eth1 parent 1:0 protocol ip u32
#Создаем 4 хеш таблицы для каждого октета
/sbin/tc filter add dev eth1 parent 1:0 handle 10: protocol ip u32 divisor 256
/sbin/tc filter add dev eth1 parent 1:0 handle 11: protocol ip u32 divisor 256
/sbin/tc filter add dev eth1 parent 1:0 handle 12: protocol ip u32 divisor 256
/sbin/tc filter add dev eth1 parent 1:0 handle 13: protocol ip u32 divisor 256
#Создаем фильтр направлящий весь трафик в хеш таблицу с ID 10
/sbin/tc filter add dev eth1 parent 1:0 protocol ip u32 ht 801:: match ip dst 0.0.0.0/0 hashkey mask 0xff000000 at 16 link 10:
#Добавляем правило в 10 хеш таблицу, если первый октет равен 192, то оправляем пакет в 11 хеш таблицу
/sbin/tc filter add dev eth1 parent 1:0 protocol ip u32 ht 10:c0: match ip dst 192.0.0.0/8  hashkey mask 0xff0000 at 16 link 11:
#Добавляем правило в 11 хеш таблицу, если второй октет равен 168, то оправляем пакет в 12 хеш таблицу
/sbin/tc filter add dev eth1 parent 1:0 protocol ip u32 ht 11:a8: match ip dst 192.168.0.0/16 hashkey mask 0xff00 at 16 link 12:
#Добавляем правило в 12 хеш таблицу, если третий октет равен 2, то оправляем пакет в 13 хеш таблицу
/sbin/tc filter add dev eth1 parent 1:0 protocol ip u32 ht 12:2: match ip dst 192.168.2.0/24 hashkey mask 0xff at 16 link 13:

#Добавляем правила в 13 хеш таблицу, оцениваем 4 октет и направляем в необходимый класс, в зависимости от вида трафика
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 1 u32 ht 13:2: match ip dst 192.168.2.2/32 match ip protocol 1 0xff flowid 1:11
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 2 u32 ht 13:2: match ip dst 192.168.2.2/32 match ip protocol 17 0xff flowid 1:12
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 3 u32 ht 13:2: match ip dst 192.168.2.2/32 match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:13
/sbin/tc filter add dev eth1 parent 1:0 protocol ip prio 4 u32 ht 13:2: match ip dst 192.168.2.2/32 flowid 1:14


* This source code was highlighted with Source Code Highlighter.

Ниже приведен листинг скрипка генерирующего правила для tc включающие в себя приоретизацию и хеш фильтры.
Скрип полностью рабочий, думаю не составит большого труда модифицировать его под себя.
При переходе с линейных фильтров на хеш таблицы нагрузка упала почти в 4 раза.
#!/bin/bash
mysql="mysql -ppass -u user -h host"
#создаем корневуй дсциплину, класс, корневой фильтр и тиблицы хешей для внешних интерфейсов
echo "select ext_iface from system.shaper_view group by ext_iface;"|$mysql|sed 1d|
awk '{
print "/sbin/tc qdisc del dev "$1" root handle 1: htb default 15";
print "/sbin/tc qdisc add dev "$1" root handle 1: htb default 15";
print "/sbin/tc class add dev "$1" parent 1: classid 1:1 htb rate 10Mbit ceil 10Mbit";
print "/sbin/tc filter add dev "$1" parent 1:1 prio 10 protocol ip u32";
print "/sbin/tc filter add dev "$1" parent 1:0 protocol ip u32";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 10: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 11: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 12: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 13: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 protocol ip u32 ht 801:: match ip dst 0.0.0.0/0 hashkey mask 0xff000000 at 16 link 10:";
}'

#создаем корневуй дсциплину, класс, корневой фильтр и тиблицы хешей для внутренних интерфейсов
echo "select int_iface from system.shaper_view group by int_iface;"|$mysql|sed 1d|
awk '{
print "/sbin/tc qdisc del dev "$1" root handle 1: htb default 15";
print "/sbin/tc qdisc add dev "$1" root handle 1: htb default 15";
print "/sbin/tc class add dev "$1" parent 1: classid 1:1 htb rate 10Mbit ceil 10Mbit";
print "/sbin/tc filter add dev "$1" parent 1:1 prio 10 protocol ip u32";
print "/sbin/tc filter add dev "$1" parent 1:0 protocol ip u32";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 10: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 11: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 12: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 handle 13: protocol ip u32 divisor 256";
print "/sbin/tc filter add dev "$1" parent 1:0 protocol ip u32 ht 801:: match ip src 0.0.0.0/0 hashkey mask 0xff000000 at 12 link 10:";
}'


#создаем классы, фильтры,дисциплины и при необходимости заполняем таблицы хешей
echo "select user_id,ip,speed,int_iface,ext_iface from system.shaper_view order by user_id;"|$mysql|sed 1d|
awk '
BEGIN{
buf=0;
class_id=255;
tc_class="/sbin/tc class add dev";
tc_qdisc="/sbin/tc qdisc add dev";
tc_filter="/sbin/tc filter add dev";
}
{
if(buf!=$1)
  {
  printf "%s%x%s\n", "# ",class_id," "class_id" "$2;
  client_speed=$3*128;
  printf "%s%x%s\n",tc_class" "$4" parent 1:1 classid 1:",++class_id," htb rate "client_speed"bps ceil "client_speed"bps";
  printf "%s%x%s\n",tc_class" "$5" parent 1:1 classid 1:",class_id," htb rate "client_speed"bps ceil "client_speed"bps";
  client_class=class_id;
  printf "%s%x%s%x%s\n",tc_class" "$4" parent 1:",client_class," classid 1:",++class_id," htb rate 1024bps ceil "client_speed"bps prio 1";
  printf "%s%x%s%x%s\n",tc_class" "$5" parent 1:",client_class," classid 1:",class_id," htb rate 1024bps ceil "client_speed"bps prio 1";
  printf "%s%x%s%x%s\n",tc_qdisc" "$4" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_qdisc" "$5" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_class" "$4" parent 1:",client_class," classid 1:",++class_id," htb rate 1024bps ceil "client_speed"bps prio 2";
  printf "%s%x%s%x%s\n",tc_class" "$5" parent 1:",client_class," classid 1:",class_id," htb rate 1024bps ceil "client_speed"bps prio 2";
  printf "%s%x%s%x%s\n",tc_qdisc" "$4" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_qdisc" "$5" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_class" "$4" parent 1:",client_class," classid 1:",++class_id," htb rate 1024bps ceil "client_speed"bps prio 3";
  printf "%s%x%s%x%s\n",tc_class" "$5" parent 1:",client_class," classid 1:",class_id," htb rate 1024bps ceil "client_speed"bps prio 3";
  printf "%s%x%s%x%s\n",tc_qdisc" "$4" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_qdisc" "$5" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_class" "$4" parent 1:",client_class," classid 1:",++class_id," htb rate 1024bps ceil "client_speed"bps prio 4";
  printf "%s%x%s%x%s\n",tc_class" "$5" parent 1:",client_class," classid 1:",class_id," htb rate 1024bps ceil "client_speed"bps prio 4";
  printf "%s%x%s%x%s\n",tc_qdisc" "$4" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  printf "%s%x%s%x%s\n",tc_qdisc" "$5" parent 1:",class_id," handle ",class_id,": sfq perturb 10";
  }
split($2,ip,".");
if (ht_1[ip[1]]!=1)
{
printf "%s%x%s\n",tc_filter" "$4" parent 1:0 protocol ip u32 ht 10:",ip[1],": match ip dst "ip[1]".0.0.0/8 hashkey mask 0xff0000 at 16 link 11:";
printf "%s%x%s\n",tc_filter" "$5" parent 1:0 protocol ip u32 ht 10:",ip[1],": match ip src "ip[1]".0.0.0/8 hashkey mask 0xff0000 at 12 link 11:";
ht_1[ip[1]]=1;
}
if (ht_2[ip[2]]!=1)
{
printf "%s%x%s\n",tc_filter" "$4" parent 1:0 protocol ip u32 ht 11:",ip[2],": match ip dst "ip[1]"."ip[2]".0.0/16 hashkey mask 0xff00 at 16 link 12:";
printf "%s%x%s\n",tc_filter" "$5" parent 1:0 protocol ip u32 ht 11:",ip[2],": match ip src "ip[1]"."ip[2]".0.0/16 hashkey mask 0xff00 at 12 link 12:";
ht_2[ip[2]]=1;
}
if (ht_3[ip[3]]!=1)
{
printf "%s%x%s\n",tc_filter" "$4" parent 1:0 protocol ip u32 ht 12:",ip[3],": match ip dst "ip[1]"."ip[2]"."ip[3]".0/24 hashkey mask 0xff at 16 link 13:";
printf "%s%x%s\n",tc_filter" "$5" parent 1:0 protocol ip u32 ht 12:",ip[3],": match ip src "ip[1]"."ip[2]"."ip[3]".0/24 hashkey mask 0xff at 12 link 13:";
ht_3[ip[3]]=1;
}
printf "%s%x%s%x\n",tc_filter" "$4" parent 1:0 protocol ip prio 1 u32 ht 13:",ip[4],": match ip dst "$2"/32 hashkey mask 0x0 at 16 match ip protocol 1 0xff flowid 1:",client_class
printf "%s%x%s%x\n",tc_filter" "$5" parent 1:0 protocol ip prio 1 u32 ht 13:",ip[4],": match ip src "$2"/32 hashkey mask 0x0 at 12 match ip protocol 1 0xff flowid 1:",client_class
printf "%s%x%s%x\n",tc_filter" "$4" parent 1:0 protocol ip prio 2 u32 ht 13:",ip[4],": match ip dst "$2"/32 hashkey mask 0x0 at 16 match ip protocol 17 0xff flowid 1:",++client_class
printf "%s%x%s%x\n",tc_filter" "$5" parent 1:0 protocol ip prio 2 u32 ht 13:",ip[4],": match ip src "$2"/32 hashkey mask 0x0 at 12 match ip protocol 17 0xff flowid 1:",client_class
printf "%s%x%s%x\n",tc_filter" "$4" parent 1:0 protocol ip prio 3 u32 ht 13:",ip[4],": match ip dst "$2"/32 hashkey mask 0x0 at 16 match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:",++client_class
printf "%s%x%s%x\n",tc_filter" "$5" parent 1:0 protocol ip prio 3 u32 ht 13:",ip[4],": match ip src "$2"/32 hashkey mask 0x0 at 12 match ip protocol 6 0xff match ip dport 80 0xffff flowid 1:",client_class
printf "%s%x%s%x\n",tc_filter" "$4" parent 1:0 protocol ip prio 4 u32 ht 13:",ip[4],": match ip dst "$2"/32 hashkey mask 0x0 at 16 flowid 1:",++client_class
printf "%s%x%s%x\n",tc_filter" "$5" parent 1:0 protocol ip prio 4 u32 ht 13:",ip[4],": match ip src "$2"/32 hashkey mask 0x0 at 12 flowid 1:",client_class
buf=$1;
}'

* This source code was highlighted with Source Code Highlighter.

Надеюсь данный опус помог Вам вникнуть в основы управления трафиком в Linux.

Источник: http://habrahabr.ru/blogs/sysadm/89002/

Шейпирование трафика в Linux

Под катом описано как шейпировать трафик в Linux и что для этого нужно знать.
Осуществлять шейпирование трафика будем посредством утилиты tc из пакета iproute2.
Знания без которых нельзя осознать всю полноту управления трафиком в Linux:
Шейпировать можно только исходящий из интерфейса трафик. (в связи с чем возникает проблема с nat, о ней мы поговорим позже). Предположим, что имеется роутер между «интернетом» и абонентом. В роутер воткнуто две сетевые карты: eth0 смотрит на абонента, а eth1 в мир. Для ограничения «скорости скачивания» правила шейпирования описываем на eth0, для ограничения «отдачи» — на eth1.
Необходимо понимать разницу между rate и ceil. Rate — гарантированная полоса пропуская, Ceil — максимальная полоса которую может получить данный класс, rate не может быть больше ceil
Параметры rate и ceil для корневого класса должны совпадать. Таким образом мы определяем общую полосу пропускания.
Сумма Rate'ов классов-потомков, не должна превышать Rate родительского класса. Конечно можно не выполнять этот пункт, но тогда могут возникнуть проблемы с предоставлением «гарантированной полосы пропускания».
Идентификаторы классов указаны в шестнадцатеричной системе, и должны находиться в пределах от 2 до 2^16
Для промежуточных классов необязательно создавать дисциплины и фильтры.
Идентификаторы классов в пределах интерфейса должны быть уникальны.

В простом варианте изложения алгоритм нарезки трафика выглядит так:
1. Создаем корневую дисциплину для интерфейса и указываем класс куда будет попадать не классифицированный трафик.
2. Создаем корневой класс и определяем ширину канала.
3. Создаем дочерний класс для шейпирования абонента.
4. Создаем дисциплину шейпирования для класса абонента.
5. Создаем фильтра позволяющие классифицировать трафик абонента.

В принципе все просто, но в реальной жизни придется потратить много нервов, что бы добиться желаемого результата.
Один из способов добиться результата не тратя много нервов — использовать скрипт htbinit (взять его можно с sourceforge.net/projects/htbinit/). Синтаксис конфигов простой, создание классов тоже просто.
Для построения конфигураций средней сложность вполне достаточно.
Пример.
Имеется локальная сеть, средних размеров. Вам необходимо ограничивать скорость абонентов согласно прейскуранту, трансляция адресов (NAT) происходит на другом сервере.

Получение htbinit
debian:~# wget downloads.sourceforge.net/project/htbinit/HTB.init/0.8.5/htb.init-v0.8.5?use_mirror=surfnet
debian:~# mv htb.init-v0.8.5 /usr/local/sbin/
debian:~# cd /usr/local/sbin/
debian:/usr/local/sbin# mv htb.init-v0.8.5 htb.init
debian:/usr/local/sbin# chmod +x htb.init

По умолчанию htbinit хранит конфиги в папке /etc/sysconfig/htb.
debian:~# mkdir -p /etc/sysconfig/htb
Создаем коневую дисциплину для интерфейса eth0 (интерфейс смотрит в локальную сеть, «на абонента»)
debian:~# touch /etc/sysconfig/htb/eth0
Указываем в какой класс будет попадать трафик не попавший ни в один из фильтров
debian:~# mcedit /etc/sysconfig/htb/eth0
DEFAULT=42

Создаем корневой класс
debian:~# touch /etc/sysconfig/htb/eth0-2.root
debian:~# mcedit /etc/sysconfig/htb/eth0-2.root
RATE=100Mbit

Можно не указывать CEIL, тогда он автоматом будет равен RATE.

Создаем класс для не классифицированного трафика
debian:~# touch /etc/sysconfig/htb/eth0-2:42.root
debian:~# mcedit /etc/sysconfig/htb/eth0-2:42.root
RATE=4Kbit


Создаем общий клиентский класс. Пускай его ID будет равно «D» и всего для абонентов мы выделим 10 Мбит.
debian:~# touch /etc/sysconfig/htb/eth0-2:D.sumamry_cilents_class
debian:~# mcedit /etc/sysconfig/htb/eth0-2:D.sumamry_cilents_class
RATE=10Mbit


Теперь можно заняться абонентами.
Что бы ограничить скорость скачивания в 512 КБит абоненту Василию нужно:
Создать класс для абонента Василия. Пускай ID клиентов будут начинаться с 255. Весьма полезно, если потребуется создать какой либо «системный» класс.
debian:~# touch /etc/sysconfig/htb/eth0-2:D:100.client_login
Интерфейс, идентификатор класса и родительские классы описываются в названии конфига.
Запись eth0-2:D:100.client_login означает что
eth0- Данный класс принадлежит к интерфейсу eth0
2 Корневой класс
D Родительский класс (В нашем случае общий клиентский класс)
100 Идентификатор класса клента
client_login Мнемоническая составляющая названия файла, несет смысловую нагрузку, в генерации классов не используется

Название файла генерируется таким образом:
1. Интерфейс к которому принадлежит класс.
2. Разделитель "-"(минус)
3. ID корневого класса
4. Разделитель ":"(двоеточие)
5. ID родительского класса
6. Разделитель ":"(двоеточие)
7. ID клиентского класса
8. Разделитель "."(точка)
9. Мнемоническая составляющая названия файла
Пункты 5 и 6 могут отсутствовать, в зависимость от выбранной Вами стратегии шейпирования.

debian:~# mcedit /etc/sysconfig/htb/eth0-2:D:100.client_login
RATE=512Kbit
LEAF=sfq
RULE=0.0.0.0/0,client_ip/32

По минимуму в конфиге должно быть 3 строки.
RATE — полоса предоставляемая абоненту.
LEAF — указатель на то, что класс конечный и для него необходимо создать создать дисциплину, в нашем случае sfq («псевдочестное» распределение полосы)
RULE — определяем что попадает в класс.Фильтровать можно по ип адресам, подсетям ип адресов, портам. Количество записей RULE может быть более одной.

Если нам нужно шейпировать трафик и натить на том же руотере, то вместо RULE нужно использовать MARK. Единственное придется маркировать пакеты.
Пример скрипта генерирующего конфиги для htbinit в конфигурации с NATом.
#!/bin/bash
#определяем переменные
declare -a rules
inif="eth0"
outif="eth1"
vlan="10"
workdir="/home/netup"
vardir="${workdir}/var"
htb_dir="/etc/sysconfig/htb"

mysql="/usr/bin/mysql -h host -u user -ppassword -D base"
ipt="/usr/local/sbin/iptables"
IPT_UNLIM="UNLIM_"${vlan}
utm_rules="${vardir}/htb_rules_htb"
htb_rules="${vardir}/htb_rules_utm"

#подготавливаем конфиги при первом запуске
[ -e ${htb_rules} ] || touch ${htb_rules}
#полная регенерация конфигов
if [ "${1}" = "zopa" ];then
echo ""> ${htb_rules};
fi

#получаем данные (id в шестнадцатиричной системе)
echo "select id,ip,mask,speed from view_shaper order by id;"|$mysql|sed '1d' > ${utm_rules};
#если достучались к базе и есть разница с текущим конфигом
exp="${utm_rules} ${htb_rules}"
[ -s ${utm_rules} ] && if [ -n "`diff ${exp}`" ]
then

#удаляем конфиги надобность в которых отпала
for i in `diff ${exp}|awk '{if (NF==5)print $2}'|sort -n|uniq`
do
inshaper=${htb_dir}/${inif}-2:${i}.rule_${i};
[ -e ${inshaper} ] && rm ${inshaper};
outshaper=${htb_dir}/${outif}-2:${i}.rule_${i};
[ -e ${outshaper} ] && rm ${outshaper};
done;

#формируем новые конфиги
rules=(`diff ${exp}|grep "<"|awk '{if (NF==5)print $2,$3,$4,$5}'`)
for i in `seq 1 4 ${#rules[@]}`;
do
id=${rules[$i-1]};
ip=${rules[$i]};
mask=${rules[$i+1]};
rate=${rules[$i+2]};

#Формируем названия конфигов
inshaper=${htb_dir}"/"${inif}-2:${id}.rule_${id};
outshaper=${htb_dir}/${outif}-2:${id}.rule_${id};

#Рассчитываем марки для пакетов
inmark="0x"`echo "obase=16; $((0x${id}*2))"|bc`
outmark="0x"`echo "obase=16; $((0x${id}*2+1))"|bc`

#Удаляем «старые» правила маркировки
${ipt} -t mangle -S ${IPT_UNLIM}|grep -w ${ip}|awk -v ipt=${ipt} '{$1="-D";system(ipt" -t mangle "$0)}';
#Создаем конфиг и правила на внутреннем интерфейсе
if [ -e ${inshaper} ]; then
#echo "RULE="0.0.0.0/0,"${ip}"/"${mask}">> ${inshaper}
${ipt} -t mangle -A ${IPT_UNLIM} -s ${ip} -j MARK --set-mark ${inmark}
else
echo "RATE=4096bit" > ${inshaper}
echo "CEIL="$((${rate}*1024))"bit" >>${inshaper}
echo "LEAF=sfq" >> ${inshaper}
#echo "RULE=0.0.0.0/0,"${ip}"/"${mask}>> ${inshaper};
echo "MARK="${inmark}>> ${inshaper};
${ipt} -t mangle -A ${IPT_UNLIM} -d ${ip}/${mask} -j MARK --set-mark ${inmark}
fi

#Создаем конфиг и правила на внутреннем интерфейсе
if [ -e $outshaper ]; then
#echo "RULE="${ip}"/"${mask}",0.0.0.0/0" >> ${outshaper}
${ipt} -t mangle -A ${IPT_UNLIM} -s ${ip}/${mask} -j MARK --set-mark ${outmark}
else
echo "RATE=4096bit" > ${outshaper}
echo "CEIL="$((${rate}*1024))"bit" >> ${outshaper}
echo "LEAF=sfq" >> ${outshaper}
#echo "RULE="${ip}"/"${mask}",0.0.0.0/0" >> ${outshaper}
echo "MARK="${outmark}>> $outshaper;
${ipt} -t mangle -A ${IPT_UNLIM} -s ${ip}/${mask} -j MARK --set-mark ${outmark}
fi
echo $ip
done;
cp ${exp}
[ -e /var/cache/htb.init ] && rm /var/cache/htb.init
/usr/local/sbin/htb.init restart
fi


Для конфигураций до 1000-1500 фильтров такой вариант подойдет. Для более крупных уже нужно использовать быстрые хэш фильтры, о ни и о приоретизации трафика я расскажу в следующей статье.

Источник: http://habrahabr.ru/blogs/sysadm/88624/

Повышение производительности netfilter, использование ipset

iptables — интерфейс к файрволу Linux (netfilter). При большом количестве правил iptables нагрузка может быть достаточно высокой и создавать проблемы. В этой заметке я постараюсь описать, что влияет на производительность iptables и как ее повысить.

Основная причина нагрузки


Для начала: из-за чего вообще возникает нагрузка при большом количестве правил? Из-за того, что каждому сетевому пакету, обрабатываемому ядром, приходится проходить сравнение по всему списку правил каждой цепочки. Приведу схему, которая отражает цепочки netfilter и порядок прохождения по ним пакетов:



На схеме видно через какие цепочки пройдет тот или иной пакет и можно оценить нагрузку. Возьмем одно простейшее правило:

-A INPUT -s 10.1.1.1/32 -p tcp --dport 25 -j DROP

Это правило указывает файрволлу отбрасывать все пакеты с IP-адреса 10.1.1.1 на порт 25 локальной машины. Таблицу (-t) я не указываю, поэтому будет использоваться дефолтная (-t filter), что нам и нужно. Понятно, что действие DROP выполняется далеко не всегда. Однако, сравнение IP-адреса источника будет проходить любой входящий на локальную машину пакет. А если таких правил тысяча?

Что делать?


Теперь подумаем, как можно ускорить работу файрволла. Первый ответ очевиден — сокращать количество правил. Но вряд ли удастся серьезно оптимизировать записи, особенно если они изначально составлялись грамотно. Где-то вместо правил на несколько IP-адресов можно написать одно правило на подсеть. Где-то вместо правил на несколько портов можно использовать -m multiport и --dports/--sports a,b,c (a,b,c — номера портов). И так далее.

Ветвление правил, дополнительные цепочки


А есть еще второй вариант — использование ветвлений правил. Суть его в том, что однотипные правила группируются в отдельную цепочку, а в основной цепочке остается одно правило, которое перенаправляет пакет в отдельную цепочку в зависимости от какого-то общего признака пакетов. Приведу пример. Имеются три правила:

-A INPUT -s 10.1.1.1/32 -p icmp -j ACCEPT
-A INPUT -s 10.1.1.2/32 -p icmp -j ACCEPT
-A INPUT -s 10.1.1.3/32 -p icmp -j ACCEPT


Что объединяет эти правила? Одинаковый протокол — icmp. Вот по этому признаку и стоит сгруппировать правила. Вообще в данном случае эффективнее использовать ipset, но об этом дальше. Для группировки необходимо создать новую цепочку, а затем создать правило, которое будет отправлять пакеты в эту цепочку.
Создать цепочку PROT_ICMP:

iptables -N PROT_ICMP

Определить правила в этой цепочке:

-A PROT_ICMP -s 10.1.1.1/32 -j ACCEPT
-A PROT_ICMP -s 10.1.1.2/32 -j ACCEPT
-A PROT_ICMP -s 10.1.1.3/32 -j ACCEPT


Как видите, протокол (-p) в этой цепочке мы уже не проверяем, т.к. отправлять в эту цепочку будем только ICMP пакеты. И наконец отправить все пакеты ICMP в эту цепочку:

-A INPUT -p icmp -g PROT_ICMP

Теперь входящий пакет, если он не ICMP, будет проходить лишь через одно правило вместо трех.

ipset


А теперь предположим следующую ситуацию:

-A INPUT -s 10.1.1.1/32 -j DROP
-A INPUT -s 10.1.1.2/32 -j DROP
-A INPUT -s 10.1.1.3/32 -j DROP


Несколько однотипных правил, но сгруппировать их или сделать дополнительную цепочку не представляется возможным. В таких случаях, когда необходимо делать проверку по большому количеству IP-адресов и/или портов, на помощь приходит ipset. ipset представляет из себя модуль ядра ip_set, ряд вспомогательных библиотек и утилиту ipset для задания параметров. Наверняка есть в репозиториях вашего дистрибутива, так что с установкой не должно быть проблем.
Используется следующим образом:
* Создается список:

ipset -N dropips iphash
dropips — название списка, iphash — тип списка. Типы списков можно посмотреть в man ipset, они есть на любой вкус — для работы с ip-адресами, подсетями, портами, mac-адресами. iphash служит для хранения IP-адресов, использование хэширования предотвращает добавление в список дублирующих IP-адресов.
* Добавляется IP-адрес в список:

ipset -A dropips 10.1.1.1

* Создается правило для использования списка:

iptables -A INPUT -m set --set dropips src -j DROP
-m set указывает на использование модуля ipset, --set dropips указывает список IP-адресов, src указывает на то, что сверять нужно только IP-источника. Таким образом, будут отбрасываться все пакеты с IP-адресов, указанных в списке dropips.

В статье я не стал описывать тюнинг сетевых параметров ядра, а сделал упор на рациональную организацию правил файрволла. Информации о тюнинге очень много можно найти в сети, это различные net.*mem*, в случае большого количества соединений и использования conntrack — параметры net.netfilter.nf_conntrack_max, net.netfilter.nf_conntrack*timeout и т.д.

Источник http://habrahabr.ru/blogs/sysadm/108691/

воскресенье, 16 мая 2010 г.

Срезаем пики с RRD графиков на примере Munin

Любой linux администратор наверняка наблюдал аномальные пики на RRD графиках. Пики появляются вследствие нарушения процесса сбора отслеживаемой величины и портят картину на графике. Это нормальное явление для RRD.

На графике трафика пики могут появится после перезапуска сетевого интерфейса или после перезагрузки сервера, что по сути одно и тоже. В обоих случаях процесс подсчета будет прерван из-за остановки устройства.

image



При появлении пиков необходимо удалить аномальные значения из базы RRD, чтобы график снова стал информативен. Это можно сделать с помощью утилиты rrdtool:
а) в ручную
rrdtool dump -> xml (находим и удаляем пики) -> rrdtool restore

б) или запустив скрипт removespikes.pl, в нем происходит тоже самое, но без вашего участия.

Я использую removespikes.pl. Процесс срезания пиков занимает не более 1 минуты.
На моих серверах установлен мониторинг Munin, поэтому примеры приведены с использованием этого мониторинга. Метод будет работать с любым мониторингов на основе RRD.

Срезаем пики с графиков eth0 трафика

## переключаем пользователя (подробнее см. «Подводные камни»)
su – munin

## утасновка скрипта removespikes.pl на сервере
wget oss.oetiker.ch/rrdtool/pub/contrib/removespikes-20080226-mkn.tar.gz
tar xvzf removespikes-20080226-mkn.tar.gz
rm removespikes-20080226-mkn.tar.gz

## Корректировка rrd файлов
## Указываем маску только тех файлов в которых необходимо срезать пики и не трогаем бекапы *.rrd.old при повторных запусках.
for f in `find ~/localdomain/ -name "localhost.localdomain-if_eth0*.rrd"`
do
## я использую removespikes.pl-orig.
## в removespikes.pl добавлен новый функционал и изменен метод среза пиков так, что можно запороть всю RRD базу. (подробнее см. «Подводные камни»)
~/removespikes/removespikes.pl-orig $f;
done;


После запуска скрипта вы должны увидеть что-то вроде
Chopping peak at
Chopping peak at


Графики Munin eth0 traffic после removespikes.pl

image


Подводные камни


Камень №1
Внимание: запускайте скрипт removespikes.pl под пользователем вашего мониторинга или проверяйте права на rdd файлы созданные скриптом, иначе сбор данных станет не возможен!

На графике выше отмечен разрыв, который произошел, вследствие того что я запускал removespikes.pl из под root. Исправленные rrd файлы были созданы с владельцем root и munin не мог записывать в них данные.

Камень №2
В архиве removespikes-20080226-mkn.tar.gz две модификации скрипта: оригинальная (removespikes.pl-orig) и с доп. функциями (removespikes.pl).

Корректность работы removespikes.pl-orig неоднократно мною проверена на разных серверах.

А вот запустив removespikes.pl я получил неожиданный результат. График как утюгом разгладило :(.

image

В скрипте есть параметр removespikes.pl
# Threshhold for cutting. Exponents above it will be chopped – срезаются все точки выше этого значения.
my $THRESH=10000;, что соответствует примерно 140Мбит/с.
Мой трафик был больше 140 и попал под это ограничение.
Если у вас обычные 100Мбит/с то это ограничение не окажет влияния на конечный результат.

Заключение

Скрипт автоматически создает бекап файлы с именами *.rrd.old, так что всегда можно вернутся к исходному состоянию. Главное правильно создать шаблон поиска файлов для прохода removespikes.pl в цикле for… in.

Источники

howto-remove-spikes-from-rrd-graphs
rrdtool doc