traffic shape per ip
Hello everyone.
i am running a small server that everyone connects on it through openvpn.
once connected the server offers some services to the connected members (voip, php forms, company email). i would to limit the bandwidth of some users based on IPs:
-10.10.0.10-19/24 gets only 1Mbps up/down
-10.10.0.20-29/24 gets only 2Mbps up/down
-the rest of the subnet is free of traffic shapping
the server has an ethernet (eth0) connected to the outside world by public IP and the VPN users connected throught the br0 (virtual interface). i have seen the tc option on the iptables, but this is where i've lost it.
the server runs debian wheezy 7.1
Quoted 1 line · binary
i would to limit the bandwidth of some users based on IPs:
[...]
This is not as simple as you might think. In order to shape per-IP, you'll need to set up a class for each individual IP address, and then filter to that class. I am not aware of a way to write one rule to say "limit each IP address to this amount".
Presumably the reason to filter per-IP is to stop single users hogging the bandwidth. If so, a better approach might be to classify the type of traffic and then shape on that, or alternatively share bandwidth evenly per-IP rather than per-connection (as is the default). There is some information on how to do this on this page at the end of the "downlink" section:
http://www.andybev.com/index.php/Fair_traffic_shaping_an_ADSL_line_for_a_local_network_using_Linux
If you have any more questions you might want to use the LARTC mailing list instead of this mailing list.
Andy
A message that is not in the archive (sent off-list or not yet received): CALFTrnNDLHW0NDJVE_sKRjP7DMsnfKXcuiEXado+p6nYUJpUbA@mail.gmail.com
Bounced for HTML. Re-sending as plaintext.
Quoted 176 lines · Ray Soucy
Try something like this.
It's not perfect, but it will work for a pool of up to 8000 IPs (TC limit is 9999 I believe). Sorry for it being in PHP, it was tossed on a box where everything else is already PHP.
Verified to work, and a modest Linux system doesn't have a problem keeping up with it.
#!/bin/php
<?php$config['wan_if'] = 'eth0'; $config['lan_if'] = 'eth1'; $config['global_down'] = '300mbit'; $config['global_up'] = '300mbit'; $config['default_down'] = '1mbit'; $config['default_up'] = '1mbit';$config['network_list'] = array('172.19.0.0/20');
function cidrtorange($network) {
list($ip, $bits)=explode('/', $network);
$ip = ip2long($ip);
$mask = ~((1 << (32 - $bits)) - 1);
$start = ($ip & $mask) + 1;
$end = ($start - 3) - $mask;
$range =array($start, $end);
return $range;
}function
exec_cmds($cmd){
$log_data = "";
$cmd =str_replace('iptables ', '/usr/local/sbin/iptables ', $cmd); $cmd =str_replace('tc ', '/usr/sbin/tc ', $cmd); $cmd_list =explode("\n", $cmd);foreach ($cmd_list as $c) { if (strlen($c) < 1) continue; $out = array(); exec($c . ' 2>&1', $out, $status); if ($status == 0) $log_data .= $c . "\n"; else { $log_data .= '# FAILED ' . $c . "\n"; foreach ($out as $o) $log_data .= '# ' . $o . "\n"; }}
echo $log_data;
}function
do_start(){
global $config;
$host_list =array();foreach ($config['network_list'] as $network) { list($start_ip, $end_ip) = cidrtorange($network); for ($i = $start_ip + 1; $i < $end_ip; $i++) { $host = long2ip($i); $host_list[$host]['down'] = $config['default_down']; $host_list[$host]['up'] = $config['default_up']; }}
$cmd = "";
$cmd .= 'iptables -t mangle -NTraffic_Control' . "\n";
$cmd .= 'iptables -t mangle -A PREROUTING -i ' . $config['lan_if'] . ' -jTraffic_Control' . "\n";
$cmd .= 'tc qdisc add dev ' . $config['lan_if'] . ' root handle 1: htb
default 9999' . "\n";
$cmd .= 'tc class add dev ' . $config['lan_if'] . ' parent 1: classid
1:9999 htb rate ' . $config['global_down'] . "\n";
$cmd .= 'tc qdisc add dev ' . $config['lan_if'] . ' parent 1:9999 handle
9999: sfq perturb 10' . "\n";
$cmd .= 'tc qdisc add dev ' . $config['wan_if'] . ' root handle 1: htb
default 9999' . "\n";
$cmd .= 'tc class add dev ' . $config['wan_if'] . ' parent 1: classid
1:9999 htb rate ' . $config['global_up'] . "\n";
$cmd .= 'tc qdisc add dev ' . $config['wan_if'] . ' parent 1:9999 handle
9999: sfq perturb 10' . "\n";
$tc_index = 1;
foreach ($host_list as $host => $lim) {
$cmd .= 'iptables -t mangle -ATraffic_Control-s ' . $host . ' -j MARK
--set-mark ' . $tc_index . "\n";
$cmd .= 'tc class add dev ' . $config['wan_if'] . ' parent 1: classid
1:' . $tc_index . ' htb rate ' . $lim['up'] . "\n";
$cmd .= 'tc filter add dev ' . $config['wan_if'] . ' protocol ip parent
1: prio 1 handle ' . $tc_index . ' fw flowid 1:' . $tc_index . "\n";
$cmd .= 'tc class add dev ' . $config['lan_if'] . ' parent 1: classid
1:' . $tc_index . ' htb rate ' . $lim['down'] . "\n";
$cmd .= 'tc filter add dev ' . $config['lan_if'] . ' protocol ip parent1: prio 1 u32 match ip dst ' . $host . ' flowid 1:' . $tc_index . "\n"; $tc_index++;}
exec_cmds($cmd);
}function
do_stop(){
global $config;
$cmd = "";
$cmd .= 'tc qdisc del dev ' . $config['lan_if'] . ' root' . "\n"; $cmd .= 'tc qdisc del dev ' . $config['wan_if'] . ' root' . "\n"; $cmd .= 'iptables -t mangle -D PREROUTING -i ' . $config['lan_if'] . ' -jTraffic_Control' . "\n";
$cmd .= 'iptables -t mangle -FTraffic_Control' . "\n";
$cmd .= 'iptables -t mangle -XTraffic_Control' . "\n";exec_cmds($cmd);
}if ($argc == 2) {
if ($argv[1] == 'start') { do_start(); } elseif ($argv[1] == 'stop') { do_stop(); } elseif ($argv[1] == 'restart') { do_stop(); do_start(); } else { echo 'Usage: ' . $argv[0] . ' {start|stop|restart}' . "\n";}
} else {
echo 'Usage: ' . $argv[0] . ' {start|stop|restart}' . "\n";
}Quoted 24 lines · Andrew Beverley
Quoted 1 line · binary
i would to limit the bandwidth of some users based on IPs:
[...]
This is not as simple as you might think. In order to shape per-IP, you'll need to set up a class for each individual IP address, and then filter to that class. I am not aware of a way to write one rule to say "limit each IP address to this amount".
Presumably the reason to filter per-IP is to stop single users hogging the bandwidth. If so, a better approach might be to classify the type of traffic and then shape on that, or alternatively share bandwidth evenly per-IP rather than per-connection (as is the default). There is some information on how to do this on this page at the end of the "downlink" section:
http://www.andybev.com/index.php/Fair_traffic_shaping_an_ADSL_line_for_a_local_network_using_Linux
If you have any more questions you might want to use the LARTC mailing list instead of this mailing list.
Quoted 7 lines
Andy
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
Ray Patrick Soucy
Network Engineer
University of Maine SystemT: 207-561-3526
F: 207-561-3531MaineREN, Maine's Research and Education Network
www.maineren.net
Signature · 9 lines
Ray Patrick Soucy Network Engineer University of Maine System T: 207-561-3526 F: 207-561-3531 MaineREN, Maine's Research and Education Network www.maineren.net
Perhaps a little late to weigh in, but I found this to be an interesting thread. Ray, thanks for sharing your script, I found it an educational read.
I have always found it interesting that nobody ever seems to use/mention tcng to implement the shaping. I found the learning curve a little steep because there isn't a lot of examples and documentation, but now that I have it, shaping is actually very very easy. This said, I have never tried to use it to shape traffic on a vpn, but if you are attaching the vpn to an interface, I don't see why it wouldn't work.
In case it is useful, I put an example of how to use tcng to limit speed on a public access network here:
http://cocnm.computerisms.ca/index.php/Shape/Track_Bandwidth_-_Finalize_IPTables
Signature · 4 lines
Computerisms Bob Miller 867-334-7117 / 867-633-3760 http://computerisms.ca
Quoted 182 lines · Ray Soucy
Bounced for HTML. Re-sending as plaintext.
Quoted 176 lines · Ray Soucy
Try something like this.
It's not perfect, but it will work for a pool of up to 8000 IPs (TC limit is 9999 I believe). Sorry for it being in PHP, it was tossed on a box where everything else is already PHP.
Verified to work, and a modest Linux system doesn't have a problem keeping up with it.
#!/bin/php
<?php$config['wan_if'] = 'eth0'; $config['lan_if'] = 'eth1'; $config['global_down'] = '300mbit'; $config['global_up'] = '300mbit'; $config['default_down'] = '1mbit'; $config['default_up'] = '1mbit';$config['network_list'] = array('172.19.0.0/20');
function cidrtorange($network) {
list($ip, $bits)=explode('/', $network);
$ip = ip2long($ip);
$mask = ~((1 << (32 - $bits)) - 1);
$start = ($ip & $mask) + 1;
$end = ($start - 3) - $mask;
$range =array($start, $end);
return $range;
}function
exec_cmds($cmd){
$log_data = "";
$cmd =str_replace('iptables ', '/usr/local/sbin/iptables ', $cmd); $cmd =str_replace('tc ', '/usr/sbin/tc ', $cmd); $cmd_list =explode("\n", $cmd);foreach ($cmd_list as $c) { if (strlen($c) < 1) continue; $out = array(); exec($c . ' 2>&1', $out, $status); if ($status == 0) $log_data .= $c . "\n"; else { $log_data .= '# FAILED ' . $c . "\n"; foreach ($out as $o) $log_data .= '# ' . $o . "\n"; }}
echo $log_data;
}function
do_start(){
global $config;
$host_list =array();foreach ($config['network_list'] as $network) { list($start_ip, $end_ip) = cidrtorange($network); for ($i = $start_ip + 1; $i < $end_ip; $i++) { $host = long2ip($i); $host_list[$host]['down'] = $config['default_down']; $host_list[$host]['up'] = $config['default_up']; }}
$cmd = "";
$cmd .= 'iptables -t mangle -NTraffic_Control' . "\n";
$cmd .= 'iptables -t mangle -A PREROUTING -i ' . $config['lan_if'] . ' -jTraffic_Control' . "\n";
$cmd .= 'tc qdisc add dev ' . $config['lan_if'] . ' root handle 1: htb
default 9999' . "\n";
$cmd .= 'tc class add dev ' . $config['lan_if'] . ' parent 1: classid
1:9999 htb rate ' . $config['global_down'] . "\n";
$cmd .= 'tc qdisc add dev ' . $config['lan_if'] . ' parent 1:9999 handle
9999: sfq perturb 10' . "\n";
$cmd .= 'tc qdisc add dev ' . $config['wan_if'] . ' root handle 1: htb
default 9999' . "\n";
$cmd .= 'tc class add dev ' . $config['wan_if'] . ' parent 1: classid
1:9999 htb rate ' . $config['global_up'] . "\n";
$cmd .= 'tc qdisc add dev ' . $config['wan_if'] . ' parent 1:9999 handle
9999: sfq perturb 10' . "\n";
$tc_index = 1;
foreach ($host_list as $host => $lim) {
$cmd .= 'iptables -t mangle -ATraffic_Control-s ' . $host . ' -j MARK
--set-mark ' . $tc_index . "\n";
$cmd .= 'tc class add dev ' . $config['wan_if'] . ' parent 1: classid
1:' . $tc_index . ' htb rate ' . $lim['up'] . "\n";
$cmd .= 'tc filter add dev ' . $config['wan_if'] . ' protocol ip parent
1: prio 1 handle ' . $tc_index . ' fw flowid 1:' . $tc_index . "\n";
$cmd .= 'tc class add dev ' . $config['lan_if'] . ' parent 1: classid
1:' . $tc_index . ' htb rate ' . $lim['down'] . "\n";
$cmd .= 'tc filter add dev ' . $config['lan_if'] . ' protocol ip parent1: prio 1 u32 match ip dst ' . $host . ' flowid 1:' . $tc_index . "\n"; $tc_index++;}
exec_cmds($cmd);
}function
do_stop(){
global $config;
$cmd = "";
$cmd .= 'tc qdisc del dev ' . $config['lan_if'] . ' root' . "\n"; $cmd .= 'tc qdisc del dev ' . $config['wan_if'] . ' root' . "\n"; $cmd .= 'iptables -t mangle -D PREROUTING -i ' . $config['lan_if'] . ' -jTraffic_Control' . "\n";
$cmd .= 'iptables -t mangle -FTraffic_Control' . "\n";
$cmd .= 'iptables -t mangle -XTraffic_Control' . "\n";exec_cmds($cmd);
}if ($argc == 2) {
if ($argv[1] == 'start') { do_start(); } elseif ($argv[1] == 'stop') { do_stop(); } elseif ($argv[1] == 'restart') { do_stop(); do_start(); } else { echo 'Usage: ' . $argv[0] . ' {start|stop|restart}' . "\n";}
} else {
echo 'Usage: ' . $argv[0] . ' {start|stop|restart}' . "\n";
}Quoted 24 lines · Andrew Beverley
Quoted 1 line · binary
i would to limit the bandwidth of some users based on IPs:
[...]
This is not as simple as you might think. In order to shape per-IP, you'll need to set up a class for each individual IP address, and then filter to that class. I am not aware of a way to write one rule to say "limit each IP address to this amount".
Presumably the reason to filter per-IP is to stop single users hogging the bandwidth. If so, a better approach might be to classify the type of traffic and then shape on that, or alternatively share bandwidth evenly per-IP rather than per-connection (as is the default). There is some information on how to do this on this page at the end of the "downlink" section:
http://www.andybev.com/index.php/Fair_traffic_shaping_an_ADSL_line_for_a_local_network_using_Linux
If you have any more questions you might want to use the LARTC mailing list instead of this mailing list.
Quoted 7 lines
Andy
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
Ray Patrick Soucy
Network Engineer
University of Maine SystemT: 207-561-3526
F: 207-561-3531MaineREN, Maine's Research and Education Network
www.maineren.net
Quoted 3 lines
If you have any more questions you might want to use the LARTC mailing list instead of this mailing list.
I asked about the lartc mailing list on this list some years ago. Based on the response I got, my understanding is that the lartc list is not active, and I was instructed to send my tc questions here instead. Do you have new information such that I should be adjusting my understanding?
Quoted 8 lines
Andy
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 8 lines · Bob Miller
Quoted 2 lines
If you have any more questions you might want to use the LARTC mailing list instead of this mailing list.
I asked about the lartc mailing list on this list some years ago. Based on the response I got, my understanding is that the lartc list is not active, and I was instructed to send my tc questions here instead. Do you have new information such that I should be adjusting my understanding?
The LARTC list did die for a period, but has now been resurrected, hosted on vger.kernel.org. It's not as active as it used to be, but does have the occasional interesting discussion.
http://vger.kernel.org/vger-lists.html#lartc
Andy
Quoted 7 lines
Quoted 6 lines
I asked about the lartc mailing list on this list some years ago. Based on the response I got, my understanding is that the lartc list is not active, and I was instructed to send my tc questions here instead. Do you have new information such that I should be adjusting my understanding?
Quoted 5 lines
The LARTC list did die for a period, but has now been resurrected, hosted on vger.kernel.org. It's not as active as it used to be, but does have the occasional interesting discussion.
Most excellent, thanks for the info...
Quoted 8 lines
Andy
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html