Latest revision |
Your text |
Line 1: |
Line 1: |
− | Sometimes it's necessary to limit traffic bandwidth from and to a [[container]]. | + | Sometimes it's necessary to limit traffic bandwidth from and to a [[VE]]. |
| You can do it using ordinary <code>tc</code> tool. | | You can do it using ordinary <code>tc</code> tool. |
| | | |
| == Packet routes == | | == Packet routes == |
− | First of all, a few words about how packets travel from and to a [[container]]. | + | First of all, a few words about how packets travel from and to a [[VE]]. |
− | Suppose we have [[Hardware Node]] (HN) with a container (CT) on it, and this | + | Suppose we have [[Hardware Node]] (HN) with a VE on it, and this VE talks |
− | container talks to some Remote Host (RH). HN has one "real" network interface
| + | to some Remote Host (RH). HN has one "real" network interface <tt>eth0</tt> and, |
− | <tt>eth0</tt> and, | |
| thanks to OpenVZ, there is also "virtual" network interface <tt>venet0</tt>. | | thanks to OpenVZ, there is also "virtual" network interface <tt>venet0</tt>. |
− | Inside the container we have interface <tt>venet0:0</tt>. | + | Inside the VE we have interface <tt>venet0:0</tt>. |
| | | |
| <pre> | | <pre> |
| venet0:0 venet0 eth0 | | venet0:0 venet0 eth0 |
− | CT >------------->-------------> HN >--------->--------> RH
| + | VE >------------->-------------> HN >--------->--------> RH |
| | | |
| venet0:0 venet0 eth0 | | venet0:0 venet0 eth0 |
− | CT <-------------<-------------< HN <---------<--------< RH
| + | VE <-------------<-------------< HN <---------<--------< RH |
| </pre> | | </pre> |
| | | |
| == Limiting outgoing bandwidth == | | == Limiting outgoing bandwidth == |
− | We can limit container outgoing bandwidth by setting the <tt>tc</tt> filter on <tt>eth0</tt>. | + | We can limit VE outgoing bandwidth by setting the <tt>tc</tt> filter on <tt>eth0</tt>. |
| <pre> | | <pre> |
| DEV=eth0 | | DEV=eth0 |
Line 28: |
Line 27: |
| tc qdisc add dev $DEV parent 1:1 sfq perturb 10 | | tc qdisc add dev $DEV parent 1:1 sfq perturb 10 |
| </pre> | | </pre> |
− | X.X.X.X is an IP address of container. | + | X.X.X.X is an IP address of VE. |
| | | |
| == Limiting incoming bandwidth == | | == Limiting incoming bandwidth == |
Line 40: |
Line 39: |
| tc qdisc add dev $DEV parent 1:1 sfq perturb 10 | | tc qdisc add dev $DEV parent 1:1 sfq perturb 10 |
| </pre> | | </pre> |
− | Note that <code>X.X.X.X</code> is an IP address of container. | + | Note that <code>X.X.X.X</code> is an IP address of VE. |
| | | |
− | == Limiting CT to HN talks == | + | == Limiting VE to HN talks == |
− | As you can see, two filters above don't limit [[container]] to [[HN]] talks. | + | As you can see, two filters above don't limit [[VE]] to [[HN]] talks. |
− | I mean a [[container]] can emit as much traffic as it wishes. To make such a limitation from the [[HN]], | + | I mean a [[VE]] can emit as much traffic as it wishes. To make such a limitation from the [[HN]], |
| it is necessary to use <tt>tc</tt> police on <tt>venet0</tt>: | | it is necessary to use <tt>tc</tt> police on <tt>venet0</tt>: |
| <pre> | | <pre> |
Line 51: |
Line 50: |
| </pre> | | </pre> |
| | | |
− | == Limiting packets per second rate from container == | + | == Limiting packets per second rate from VE == |
− | To prevent dos atacks from the container you can limit packets per second rate using iptables. | + | To prevent dos atacks from the VE you can limit packets per second rate using iptables. |
− | <source lang="bash"> | + | <pre> |
| DEV=eth0 | | DEV=eth0 |
| iptables -I FORWARD 1 -o $DEV -s X.X.X.X -m limit --limit 200/sec -j ACCEPT | | iptables -I FORWARD 1 -o $DEV -s X.X.X.X -m limit --limit 200/sec -j ACCEPT |
| iptables -I FORWARD 2 -o $DEV -s X.X.X.X -j DROP | | iptables -I FORWARD 2 -o $DEV -s X.X.X.X -j DROP |
− | </source> | + | </pre> |
− | Here <code>X.X.X.X</code> is an IP address of container. | + | Here <code>X.X.X.X</code> is an IP address of VE |
− | | |
− | == An alternate approach using HTB ==
| |
− | | |
− | For details refer to the [http://luxik.cdi.cz/~devik/qos/htb/ HTB Home Page]
| |
− | | |
− | <source lang="bash">
| |
− | #!/bin/sh
| |
− | #
| |
− | # Incoming traffic control
| |
− | #
| |
− | CT_IP1=$1
| |
− | CT_IP2=$2
| |
− | DEV=venet0
| |
− | #
| |
− | tc qdisc del dev $DEV root
| |
− | #
| |
− | tc qdisc add dev $DEV root handle 1: htb default 10
| |
− | #
| |
− | tc class add dev $DEV parent 1: classid 1:1 htb rate 100mbit burst 15k
| |
− | tc class add dev $DEV parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit burst 15k
| |
− | tc class add dev $DEV parent 1:1 classid 1:20 htb rate 20mbit ceil 20mbit burst 15k
| |
− | tc class add dev $DEV parent 1:1 classid 1:30 htb rate 30mbit ceil 30mbit burst 15k
| |
− | #
| |
− | tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
| |
− | tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
| |
− | tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
| |
− | #
| |
− | if [ ! -z $CT_IP1 ]; then
| |
− | tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$CT_IP1" flowid 1:20
| |
− | fi
| |
− | if [ ! -z $CT_IP2 ]; then
| |
− | tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$CT_IP2" flowid 1:30
| |
− | fi
| |
− | #
| |
− | echo;echo "tc configuration for $DEV:"
| |
− | tc qdisc show dev $DEV
| |
− | tc class show dev $DEV
| |
− | tc filter show dev $DEV
| |
− | #
| |
− | # Outgoing traffic control
| |
− | #
| |
− | DEV=eth0
| |
− | #
| |
− | tc qdisc del dev $DEV root
| |
− | #
| |
− | tc qdisc add dev $DEV root handle 1: htb default 10
| |
− | #
| |
− | tc class add dev $DEV parent 1: classid 1:1 htb rate 100mbit burst 15k
| |
− | tc class add dev $DEV parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit burst 15k
| |
− | tc class add dev $DEV parent 1:1 classid 1:20 htb rate 20mbit ceil 20mbit burst 15k
| |
− | tc class add dev $DEV parent 1:1 classid 1:30 htb rate 30mbit ceil 30mbit burst 15k
| |
− | #
| |
− | tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
| |
− | tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
| |
− | tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
| |
− | #
| |
− | if [ ! -z $CT_IP1 ]; then
| |
− | tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$CT_IP1" flowid 1:20
| |
− | fi
| |
− | if [ ! -z $CT_IP2 ]; then
| |
− | tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$CT_IP2" flowid 1:30
| |
− | fi
| |
− | #
| |
− | echo;echo "tc configuration for $DEV:"
| |
− | tc qdisc show dev $DEV
| |
− | tc class show dev $DEV
| |
− | tc filter show dev $DEV
| |
− | </source>
| |
− | | |
− | | |
− | | |
− | == Autogen rules for CT ==
| |
− | | |
− | <source lang="python">
| |
− | #!/usr/bin/env python
| |
− | # -*- coding: utf-8 -*-
| |
− | ######################################
| |
− | ## by VoidLess, lepus.su
| |
− | ######################################
| |
− | import fnmatch
| |
− | import os
| |
− | | |
− | ######################################
| |
− | ## НАСТРОЙКИ СКРИПТА
| |
− | confdir = "/etc/vz/conf/"
| |
− | rulefile = "/etc/vz/shaper/rules.sh"
| |
− | | |
− | # шейпятся только эти тарифы
| |
− | table_band = {
| |
− | #ORIGIN_SAMPLE : канал
| |
− | "SSD8": "100mbit",
| |
− | "SSD7": "100mbit",
| |
− | "SSD6": "100mbit",
| |
− | "SSD5": "100mbit",
| |
− | "SSD4": "100mbit",
| |
− | "SSD3": "100mbit",
| |
− | "SSD2": "100mbit",
| |
− | "SSD1": "100mbit"
| |
− | }
| |
− | | |
− | ######################################
| |
− | ## ШАБЛОН СКРИПТА НАСТРОЙКИ ШЕЙПЕРА
| |
− | | |
− | fileheader = """#!/bin/bash
| |
− | # shaper configuration file
| |
− | | |
− | ##### ЧИСТКА ОТ СТАРЫХ ПРАВИЛ #####
| |
− | tc qdisc del dev eth0 root
| |
− | tc -s qdisc ls dev eth0
| |
− | | |
− | tc qdisc del dev venet0 root
| |
− | tc -s qdisc ls dev venet0
| |
− | ##### ЧИСТКА ОТ СТАРЫХ ПРАВИЛ #####
| |
− | """
| |
− | | |
− | # eth0
| |
− | | |
− | eth0header = """
| |
− | DEV=eth0
| |
− | tc qdisc del dev $DEV root 2>/dev/null
| |
− | tc qdisc add dev $DEV root handle 1: htb default 1 r2q 3000
| |
− | tc class add dev $DEV parent 1: classid 1:1 htb rate 1000mbit burst 10mb
| |
− | """
| |
− | | |
− | eth0template = """
| |
− | # vzid {VPSID} tarif {BANDWIDTH} ip {IP}
| |
− | | |
− | tc class add dev $DEV parent 1:1 classid 1:{CLASS} htb rate {BANDWIDTH} ceil {BANDWIDTH} burst 1mb
| |
− | tc qdisc add dev $DEV parent 1:{CLASS} handle {CLASS}: sfq perturb 5 #quantum 5000b
| |
− | """
| |
− | | |
− | eth0match = """
| |
− | tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src {IP} flowid 1:{CLASS}
| |
− | """
| |
− | | |
− | # venet0
| |
− | | |
− | venet0header = """
| |
− | DEV=venet0
| |
− | tc qdisc del dev $DEV root 2>/dev/null
| |
− | tc qdisc add dev $DEV root handle 1: htb default 1 r2q 3000
| |
− | tc class add dev $DEV parent 1: classid 1:1 htb rate 1000mbit burst 10mb
| |
− | """
| |
− | | |
− | venet0template = """
| |
− | # vzid {VPSID} tarif {BANDWIDTH} ip {IP}
| |
− | | |
− | tc class add dev $DEV parent 1:1 classid 1:{CLASS} htb rate {BANDWIDTH} ceil {BANDWIDTH} burst 1mb
| |
− | tc qdisc add dev $DEV parent 1:{CLASS} handle {CLASS}: sfq perturb 5 #quantum 5000b
| |
− | """
| |
− | | |
− | venet0match = """
| |
− | tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst {IP} flowid 1:{CLASS}
| |
− | """
| |
− | | |
− | ######################################
| |
− | ## КОД СКРИПТА
| |
− | # получает список и настройки виртуалок из папки конфигов OpenVZ
| |
− | def getvz():
| |
− | vzlist = []
| |
− | | |
− | for file in os.listdir(confdir):
| |
− | if fnmatch.fnmatch(file, '*.conf') and file != "0.conf":
| |
− | #берем список конфигов
| |
− | vzid = file.split(".",1)[0]
| |
− | vztarif = None
| |
− | vzip = None
| |
− | | |
− | #открываем файл, узнаем название тарифа
| |
− | with open(confdir + file) as f:
| |
− | for line in f:
| |
− | if line[0]=="#":
| |
− | continue
| |
− | | |
− | ar = line.split("=")
| |
− | | |
− | if ar[0] == "ORIGIN_SAMPLE":
| |
− | vztarif = ar[1].replace('"', '').strip()
| |
− | continue
| |
− | | |
− | if ar[0] == "IP_ADDRESS":
| |
− | vzip = ar[1].replace('"', '').strip().split(" ")
| |
− | continue
| |
− | | |
− | #если в файле не написан тариф, или он левый, ничего не делаем
| |
− | if vztarif == None or vzip == None or vztarif not in table_band:
| |
− | continue
| |
− |
| |
− | # в список записываем инфу про все vps
| |
− | vzlist.append((vzid, table_band[vztarif], vzip))
| |
− | return vzlist
| |
− | | |
− | # записывает команды настройки шейпера в sh файл
| |
− | def genconf(vzlist):
| |
− | with open(rulefile,"w+") as f:
| |
− | | |
− | # file header
| |
− | f.write(fileheader)
| |
− | | |
− | # eth0 rules
| |
− | f.write(eth0header)
| |
− | | |
− | shaper_id = 100
| |
− | for vz in vzlist:
| |
− | f.write(eth0template
| |
− | .replace("{VPSID}",vz[0])
| |
− | .replace("{CLASS}",str(shaper_id))
| |
− | .replace("{BANDWIDTH}",vz[1])
| |
− | .replace("{IP}",str(vz[2])))
| |
− | for ip in vz[2]:
| |
− | f.write(eth0match
| |
− | .replace("{VPSID}",vz[0])
| |
− | .replace("{CLASS}",str(shaper_id))
| |
− | .replace("{IP}",ip))
| |
− | shaper_id += 1
| |
− | | |
− | # venet0 rules
| |
− | f.write(venet0header)
| |
− | | |
− | shaper_id = 100
| |
− | for vz in vzlist:
| |
− | f.write(venet0template
| |
− | .replace("{VPSID}",vz[0])
| |
− | .replace("{CLASS}",str(shaper_id))
| |
− | .replace("{BANDWIDTH}",vz[1])
| |
− | .replace("{IP}",str(vz[2])))
| |
− | for ip in vz[2]:
| |
− | f.write(venet0match
| |
− | .replace("{VPSID}",vz[0])
| |
− | .replace("{CLASS}",str(shaper_id))
| |
− | .replace("{IP}",ip))
| |
− | shaper_id += 1
| |
− | | |
− | # make in runnable
| |
− | os.chmod(rulefile, 0755)
| |
− | | |
− | ## основной код скрипта. выполнение функций
| |
− | # получили список VPSок
| |
− | vzlist = getvz()
| |
− | | |
− | # сгенерировали скрипт с правилами
| |
− | genconf(vzlist)
| |
− | | |
− | # применили правила
| |
− | os.system(rulefile)
| |
− | </source>
| |
− | | |
| | | |
| == External links == | | == External links == |