LINUX.ORG.RU
ФорумAdmin

tc - шейпинг FORWARD трафика с NAT


0

1

Здравствуйте.

Я пытаюсь сделать полосы гарантированного пропускания для p2p и всего остального трафика в следующей архитектуре сети:

  • Сервер подключён интерфейсом eth1 (192.168.1.33) к ADSL-модему (192.168.1.1).
  • Через этот модем на сервере поднято PPPoE-соединение ppp0 с внешним динамическим ip.
  • Компьютеры сети подключены к интерфейсу eth0 (192.168.10.1).
  • На этом интерфейсе висит мост br0, к которому подключены две виртуальных машины KVM (192.168.10.102 и 192.168.10.103, раздаются по DHCP с привязкой по MAC), которые и качают из пиринговых сетей.

Пакеты маркируются iptables, после чего шейпятся tc (решение осталось от старых попыток использовать ipp2p, с которым иное не получается).

Настройка iptables:

#!/bin/sh
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t filter -F

#######
##NAT
#######
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE # для всех машин в сети
iptables -t nat -A POSTROUTING -d 192.168.1.0/24 -o eth1 -j MASQUERADE # чтобы иметь возможность достучаться до  модема
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # иначе не работает
#######

################
##perfect dark
################
iptables -A PREROUTING -t nat  -p udp --dport 55272 -j DNAT --to 192.168.10.102:55272 #открываем порт
iptables -A PREROUTING -t nat  -p tcp --dport 55272 -j DNAT --to 192.168.10.102:55272 #открываем порт
iptables -A FORWARD -t mangle -p tcp -d 192.168.10.102 -j MARK --set-mark 0x3 #pd downloads
iptables -A FORWARD -t mangle -p udp -d 192.168.10.102 -j MARK --set-mark 0x3 #pd downloads
iptables -A PREROUTING -t mangle -p tcp --source 192.168.10.102 -j MARK --set-mark 0x4 #pd uploads
iptables -A PREROUTING -t mangle -p udp --source 192.168.10.102 -j MARK --set-mark 0x4 #pd uploads
###############

###############
##transmission
###############
iptables -A PREROUTING -t nat -p udp --dport 31415 -j DNAT --to 192.168.10.103:31415 #transmission
iptables -A PREROUTING -t nat -p tcp --dport 31415 -j DNAT --to 192.168.10.103:31415 #transmission
iptables -A FORWARD -t mangle -p tcp -d 192.168.10.103 -j MARK --set-mark 0x1 # transmission downloads
iptables -A FORWARD -t mangle -p udp -d 192.168.10.103 -j MARK --set-mark 0x1 # transmission downloads
iptables -A PREROUTING -t mangle -p tcp --source 192.168.10.103 -j MARK --set-mark 0x2 #transmission uploads
iptables -A PREROUTING -t mangle -p udp --source 192.168.10.103 -j MARK --set-mark 0x2 #transmission uploads
##############

######################
##transmission webui
######################
iptables -A PREROUTING -t nat -p tcp --to-source 192.168.10.1 --dport 80 -j DNAT --to 192.168.10.103:8080
iptables -A PREROUTING -t nat -p tcp --to-source 192.168.10.103 --dport 80 -j DNAT --to 192.168.10.103:8080
######################

iptables-save

Настройка tc:

#!/bin/sh

tc qdisc del dev ppp0 root

tc qdisc add dev ppp0 root handle 1: htb default 20

	#Корневая дисциплина
	tc class add dev ppp0 parent 1: classid 1:1 htb \
	rate 2560kbit ceil 2560kbit

		#p2p downloads
		tc class add dev ppp0 parent 1:1 classid 1:11 htb \
		rate 500kbit ceil 2560kbit
		
		#p2p uploads
		tc class add dev ppp0 parent 1:1 classid 1:12 htb \
		rate 50kbit ceil 512kbit

		#Всё остальное
		tc class add dev ppp0 parent 1:1 classid 1:20 htb \
		rate 100kbit ceil 100000kbit

tc qdisc add dev ppp0 parent 1:11 handle 10:0 sfq perturb 10
tc qdisc add dev ppp0 parent 1:12 handle 20:0 sfq perturb 10
tc qdisc add dev ppp0 parent 1:20 handle 20:0 sfq perturb 10


#MARK 1 transmission downloads
tc filter add dev ppp0 protocol ip parent 1:0 prio 1 \
handle 0x1 fw flowid 1:11

#MARK 3 pd downloads
tc filter add dev ppp0 protocol ip parent 1:0 prio 1 \
handle 0x3 fw flowid 1:11

#MARK 2 transmission uploads
tc filter add dev ppp0 protocol ip parent 1:0 prio 1 \
handle 0x2 fw flowid 1:12

#MARK 4 pd uploads
tc filter add dev ppp0 protocol ip parent 1:0 prio 1 \
handle 0x4 fw flowid 1:12

Маркируются пакеты совершенно правильно:

iptables -t mangle -vnL 
Chain PREROUTING (policy ACCEPT 113K packets, 81M bytes)
 pkts bytes target     prot opt in     out     source               destination         
 8778 5105K MARK       tcp  --  *      *       192.168.10.102       0.0.0.0/0           MARK set 0x4 
   47 13834 MARK       udp  --  *      *       192.168.10.102       0.0.0.0/0           MARK set 0x4 
54766   39M MARK       tcp  --  *      *       192.168.10.103       0.0.0.0/0           MARK set 0x2 
  165 19754 MARK       udp  --  *      *       192.168.10.103       0.0.0.0/0           MARK set 0x2 

Chain INPUT (policy ACCEPT 44172 packets, 37M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 68638 packets, 44M bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1685 1119K MARK       tcp  --  *      *       0.0.0.0/0            192.168.10.102      MARK set 0x3 
   49  6586 MARK       udp  --  *      *       0.0.0.0/0            192.168.10.102      MARK set 0x3 
27145   27M MARK       tcp  --  *      *       0.0.0.0/0            192.168.10.103      MARK set 0x1 
  253 27799 MARK       udp  --  *      *       0.0.0.0/0            192.168.10.103      MARK set 0x1 

Chain OUTPUT (policy ACCEPT 26773 packets, 28M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 95417 packets, 72M bytes)
 pkts bytes target     prot opt in     out     source               destination         

А вот шейпится только исходящий трафик, входящий же сваливается в дефолтную дисциплину:

tc -s -d class show dev ppp0 
class htb 1:11 parent 1:1 leaf 10: prio 0 quantum 6250 rate 500000bit ceil 2560Kbit burst 1600b/8 mpu 0b overhead 0b cburst 1600b/8 mpu 0b overhead 0b level 0 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 rate 0bit 0pps backlog 0b 0p requeues 0 
 lended: 0 borrowed: 0 giants: 0
 tokens: 400000 ctokens: 78125

class htb 1:1 root rate 2560Kbit ceil 2560Kbit burst 1600b/8 mpu 0b overhead 0b cburst 1600b/8 mpu 0b overhead 0b level 7 
 Sent 15023540 bytes 42136 pkt (dropped 0, overlimits 0 requeues 0) 
 rate 625480bit 201pps backlog 0b 0p requeues 0 
 lended: 32956 borrowed: 0 giants: 0
 tokens: 73047 ctokens: 73047

class htb 1:20 parent 1:1 prio 0 quantum 1250 rate 100000bit ceil 100000Kbit burst 1600b/8 mpu 0b overhead 0b cburst 1600b/8 mpu 0b overhead 0b level 0 
 Sent 5096283 bytes 11227 pkt (dropped 63, overlimits 0 requeues 0) 
 rate 198800bit 57pps backlog 0b 0p requeues 0 
 lended: 5626 borrowed: 5601 giants: 0
 tokens: -30597 ctokens: 1954

class htb 1:12 parent 1:1 leaf 20: prio 0 quantum 1000 rate 50000bit ceil 512000bit burst 1600b/8 mpu 0b overhead 0b cburst 1600b/8 mpu 0b overhead 0b level 0 
 Sent 9927257 bytes 30909 pkt (dropped 0, overlimits 0 requeues 0) 
 rate 425264bit 143pps backlog 0b 0p requeues 0 
 lended: 3554 borrowed: 27355 giants: 0
 tokens: -2903778 ctokens: 365235

Из того, что я читал, получается, что для того, чтобы tc мог видеть маркировку пакетов, они должны маркироваться в цепочках PREROUTING или INPUT, те же из них, что маркируются в остальных, просто пролетают мимо шейпера, вот и попадают в дисциплину по умолчанию раньше, чем будут промаркированы.

Но поскольку у меня стоит NAT с маскарадингом и динамическим внешним ip, на этапе PREROUTING нет никакой возможности узнать адрес назначения пакета.

Аналогично, не получится проверять его и в самом tc с помощью u32 match, поскольку на том этапе, пока работает tc, все пакеты имеют ip dst равный внешнему ip ppp0.

Можно ли как-то разрешить такую проблему?

Вроде, говорили, что можно настроить NAT с заменой порта, каждому компу свой диапазон. Чем это черевато не знаю, но, тогда, можно поробовать u32 на номер порта.

mky ★★★★★ ()
Ответ на: комментарий от mky

То есть, сделать так, чтобы исходящие соединения p2p, с какого бы порта они не шли, при трансляции адресов становились исходящими соединениями с конкретного порта, и тогда все ответные пакеты будут иметь конкретный порт назначения ещё до маршрутизации?

Добавил в настройки iptables:

iptables -A PREROUTING -t nat -p tcp --source 192.168.10.103 -j REDIRECT --to-port 4321 #transmission downloads nat
iptables -A PREROUTING -t nat -p udp --source 192.168.10.103 -j REDIRECT --to-port 4321 #transmission downloads nat

В настройки tc:

tc filter add dev ppp0 protocol ip parent 1:0 prio 0 \
u32 match ip dport 4321 0xffff flowid 1:11

Правило iptables отрабатывает правильно:

832 49920 REDIRECT   tcp  --  *      *       192.168.10.103       0.0.0.0/0           redir ports 4321 
266 28584 REDIRECT   udp  --  *      *       192.168.10.103       0.0.0.0/0           redir ports 4321 

Немного, конечно, но если это исключительно запросы кусков, а не сами куски, то так, вроде, и должно быть.

Но в соответствующей дисциплине tc по-прежнему пусто.

maxikov ()

у тебя заданы дисциплины только для ppp0, чтобы шейпился входящий трафик, задай подобные дисциплины для br0

Minus ()
Ответ на: комментарий от maxikov

Может, я не совсем правильно понял вашу проблему. В общем, у вас несколько машин и маршрутизатор делает для них NAT, точнее SNAT. И вам нужно «резать» приходящий из инета на эти машины траффик? Если так, то делаете, чтобы при SNAT менялся не только src-ip адрес, но и src port:

iptables -t nat -I POSTROUTING -p tcp --source 192.168.10.103 -j SNAT --to-source X.X.X.X:4321 # для udp аналогично

Хотя, лучше диапазон портов, причём такой, чтобы закрывался двоичной маской (для правила u32).

И нужно для каждого локального ip адреса, который NAT-ится прописать свой диапазон портов, чтобы не было путаницы, так как по умолчанию SNAT стремится сохранить порт неизменным. То есть если машина 192.168.10.105 откроет соединение с порта 4321 и попадёт в SNAT правило без указания порта, то в инет пакет удёт с порта 4321 и ответный пакет попадёт в очередь 1:11.

mky ★★★★★ ()
Ответ на: комментарий от mky

Похоже, проблема была в том, что tc просто игнорирует входящий трафик.

Я прописал правила для подмены портов:

iptables -t nat -A POSTROUTING -o ppp0 --source 192.168.10.103 -p tcp -j MASQUERADE --to-ports 4096-4249 #transmission downloads nat
iptables -t nat -A POSTROUTING -o ppp0 --source 192.168.10.103 -p udp -j MASQUERADE --to-ports 4096-4249 #transmission downloads nat

iptables -A PREROUTING -t mangle -p udp --dport 4096:4249 -j MARK --set-mark 0x1
iptables -A PREROUTING -t mangle -p tcp --dport 4096:4249 -j MARK --set-mark 0x1

Плюс, ещё добавил маркировку пакетов, приходящих на указанный диапазон портов.

Работали они совершенно нормально:

iptables -t mangle -vnL 
Chain PREROUTING (policy ACCEPT 189K packets, 116M bytes)
 pkts bytes target     prot opt in     out     source               destination         
19095 7742K MARK       tcp  --  *      *       192.168.10.102       0.0.0.0/0           MARK set 0x4 
  107 33368 MARK       udp  --  *      *       192.168.10.102       0.0.0.0/0           MARK set 0x4 
    0     0 MARK       udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpts:4096:4249 MARK set 0x1 
24027   31M MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpts:4096:4249 MARK set 0x1 
22734 1275K MARK       tcp  --  *      *       192.168.10.103       0.0.0.0/0           MARK set 0x2 
  103  6288 MARK       udp  --  *      *       192.168.10.103       0.0.0.0/0           MARK set 0x2 

Сделал правила для tc:

tc filter add dev ppp0 protocol ip parent 1:0 prio 1 handle 0x1 fw flowid 1:11
tc filter add dev ppp0 protocol ip parent 1:0 prio 0 u32 match ip dport 0x1000 0xff00 flowid 1:11

Но всё равно не работало:

tc -s -d -p class show dev ppp0
class htb 1:11 parent 1:1 leaf 10: prio 0 quantum 6250 rate 500000bit ceil 2560Kbit burst 1600b/8 mpu 0b overhead 0b cburst 1600b/8 mpu 0b overhead 0b level 0 
 Sent 34858 bytes 71 pkt (dropped 0, overlimits 0 requeues 0) 
 rate 8bit 0pps backlog 0b 0p requeues 0 
 lended: 63 borrowed: 8 giants: 0
 tokens: 378000 ctokens: 73829

Зато трафик стал идеально шейпиться, когда я к правилам для ppp0 добавил правила для br0:

tc qdisc del dev br0 root

tc qdisc add dev br0 root handle 1: htb default 20

	tc class add dev br0 parent 1: classid 1:1 htb rate 102400kbit ceil 102400kbit

		tc class add dev br0 parent 1:1 classid 1:11 htb rate 100kbit ceil 1024000kbit

		tc class add dev br0 parent 1:11 classid 1:20 htb rate 200kbit ceil 1024000kbit
tc qdisc add dev br0 parent 1:11 handle 15:0 sfq perturb 11
tc qdisc add dev br0 parent 1:20 handle 25:0 sfq perturb 11

tc filter add dev br0 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.10.103 flowid 1:11

Тут же нужные пакеты посыпались в диспицлину, а одновременно со включённым без ограничений transmission стали проигрываться видео на youtube.

Жаль, я надеялся на большую сообразительность tc, но хоть так, но проблема решилась. Спасибо всем.

maxikov ()
Ответ на: комментарий от maxikov

Да, входящий трафик нельзя шейпить. Я почему то думал, что у вас используется специальное псевдо-устройство IFB, позволяющее из входящего на интерфес трафика сделать исходящий.

mky ★★★★★ ()
Ответ на: комментарий от mky

Теперь буду с с ним разбираться. Возможно, это окажется лучшим решением.

maxikov ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.