След дълго четене и ровене в интернет, реших, че варианта, който е описал VladSun е добър избор (линковете към неговите статии може да намерите в предишния пост), а именно използване на IPMARK.
IPMARK не идва като част от iptables, поради което трябва да се инсталира допълнително. За да тествам как работи IPMARK написах едно малко скрипче на Python, но възникнаха някои въпроси по време на този процес.
За тези, които искат да използват IPMARK и се борят, да разберат на какъв принцип работи всичко, искам да обясня на кратко какво съм разбрал.
Система: Debian 3.2.46-1 x86_64
Инсталиране на IPMARK (copy-paste):
--------------------------------------------------------------------------------
aptitude update
aptitude install module-assistant xtables-addons-source xtables-addons-common
m-a prepare
m-a auto-install xtables-addons-source
depmod -a
--------------------------------------------------------------------------------
Източник:
Установка модуля IPMARK для iptables в Debian Squeeze и shaper tc без нагрузки на процессор - See more at: http://linuxsnippets.net/ru/node/268#sthash.TbbGwjXr.dpufИсталиране на необходим модул за Python:
apt-get install python-ipcalc
Ето и тестовия скрипт:
GeSHi (Python):
#!/usr/bin/env python
import ipcalc
IFACE_INTERNAL = "eth0"
IFACE_EXTERNAL = "eth1"
DOWN_SPEED = "8Mbit"
UP_SPEED = "4Mbit"
ip = "10.111.1.2"
mask = 24
net = ipcalc.Network(ip, mask)
ip_version = net.version()
if ip_version == 4:
ip = ipcalc.IP(ip)
ipmark_hex = ip.hex()[4:8]
# Upload Speed Rule
ipmark_up = 'iptables -t mangle -A FORWARD -s ' + "10.111.1.0/24" + ' -j IPMARK --addr=src --and-mask=0xffff --or-mask=0x10000'
tc_up = []
tc_up += ['tc qdisc add dev ' + IFACE_EXTERNAL + ' root handle 1: htb']
tc_up += ['tc filter add dev ' + IFACE_EXTERNAL + ' parent 1:0 protocol ip prio 1 fw']
tc_up += ['tc class add dev ' + IFACE_EXTERNAL + ' parent 1: classid 1:' + ipmark_hex + ' htb rate ' + UP_SPEED]
tc_up += ['tc qdisc add dev ' + IFACE_EXTERNAL + ' parent 1:' + ipmark_hex + ' handle ' + ipmark_hex + ' sfq perturb 10']
# Download Speed Rule
ipmark_down = 'iptables -t mangle -A FORWARD -d ' + "10.111.1.0/24" + ' -j IPMARK --addr=dst --and-mask=0xffff --or-mask=0x10000'
tc_down = []
tc_down += ['tc qdisc add dev ' + IFACE_INTERNAL + ' root handle 1: htb']
tc_down += ['tc filter add dev ' + IFACE_INTERNAL + ' parent 1:0 protocol ip prio 1 fw']
tc_down += ['tc class add dev ' + IFACE_INTERNAL + ' parent 1: classid 1:' + ipmark_hex + ' htb rate ' + DOWN_SPEED]
tc_down += ['tc qdisc add dev ' + IFACE_INTERNAL + ' parent 1:' + ipmark_hex + ' handle ' + ipmark_hex + ' sfq perturb 10']
print '==========='
print 'hex.......:', ip.hex()
print '==========='
print 'IPMARK Rule UP:', ipmark_up
print 'TC Rules UP:', tc_up
print '==========='
print 'IPMARK Rule DOWN:', ipmark_down
print 'TC Rules DOWN:', tc_up
print '==========='
Изхода от скрипта е:
===========
hex.......: 0a6f0102
===========
IPMARK Rule UP: iptables -t mangle -A FORWARD -s 10.111.1.0/24 -j IPMARK --addr=src --and-mask=0xffff --or-mask=0x10000
TC Rules UP: ['tc qdisc add dev eth1 root handle 1: htb', 'tc filter add dev eth1 parent 1:0 protocol ip prio 1 fw', 'tc class add dev eth1 parent 1: classid 1:0102 htb rate 4Mbit', 'tc qdisc add dev eth1 parent 1:0102 handle 0102 sfq perturb 10']
===========
IPMARK Rule DOWN: iptables -t mangle -A FORWARD -d 10.111.1.0/24 -j IPMARK --addr=dst --and-mask=0xffff --or-mask=0x10000
TC Rules DOWN: ['tc qdisc add dev eth0 root handle 1: htb', 'tc filter add dev eth0 parent 1:0 protocol ip prio 1 fw', 'tc class add dev eth0 parent 1: classid 1:0102 htb rate 8Mbit', 'tc qdisc add dev eth0 parent 1:0102 handle 0102 sfq perturb 10']
===========
Искам да уточня, че скрипта не изпълнява командите, а само събира стойностите и ги извежда в удобен вариант за copy-paste.
Какво прави скрипта?
Имаме едно тестово IP - 10.111.1.2, за което предварително сме дигнали рутиране. На 19-ти ред от скрипта взимаме това IP и го превръщаме в hex (hex.......: 0a6f0102) след което от тази стойност взимаме и използваме само последните 4 символа (0102). Това ми стана ясно от статията, която посочих по-горе, но от това което е обяснил VladSun за траснирането не можах да разбера нищо. Ако някой може да обясни разликата между този начин на прихващане на пакетите и този на VladSun, ще е полезно.
В коя верига е по-добре да се прихванат пакетите - PREROUTING, POSTROUTING или FORWRD и защо?
Също не ми стана ясно, защо добавяме "tc qdisc add dev eth1 parent 1:0102 handle 0102 sfq perturb 10" при положение, че шейпъра работи и без това правило, каква е идеята.
Благодаря!