LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Server (http://www.linuxquestions.org/questions/linux-server-73/)
-   -   IPTABLES and TC for limiting bandwidth per linux user (http://www.linuxquestions.org/questions/linux-server-73/iptables-and-tc-for-limiting-bandwidth-per-linux-user-744365/)

alexxxutz 08-01-2009 10:18 AM

IPTABLES and TC for limiting bandwidth per linux user
 
I discovered that i can use TC and IPTABLES for limiting bandwidth on SSH per linux user.
First i added the command:

Quote:

iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner test -j MARK --set-mark 1
to mark packet.
Then i used this script to limit bandwidth:

Quote:

#!/bin/bash
#
# tc uses the following units when passed as a parameter.
# kbps: Kilobytes per second
# mbps: Megabytes per second
# kbit: Kilobits per second
# mbit: Megabits per second
# bps: Bytes per second
# Amounts of data can be specified in:
# kb or k: Kilobytes
# mb or m: Megabytes
# mbit: Megabits
# kbit: Kilobits
# To get the byte figure from bits, divide the number by 8 bit
#

#
# Name of the traffic control command.
TC=/sbin/tc

# The network interface we're planning on limiting bandwidth.
IF=eth0 # Interface

# Download limit (in mega bits)
DNLD=1mbit # DOWNLOAD Limit

# Upload limit (in mega bits)
UPLD=1mbit # UPLOAD Limit

# IP address of the machine we are controlling
IP=216.3.128.12 # Host IP

# Filter options for limiting the intended interface.
U32="$TC filter add dev $IF protocol ip parent 1:0 prio 1 u32"

start() {

# We'll use Hierarchical Token Bucket (HTB) to shape bandwidth.
# For detailed configuration options, please consult Linux man
# page.

$TC qdisc add dev $IF root handle 1: htb default 30
$TC class add dev $IF parent 1: classid 1:1 htb rate $DNLD
$TC class add dev $IF parent 1: classid 1:2 htb rate $UPLD
$U32 match ip dst $IP/32 flowid 1:1
$U32 match ip src $IP/32 flowid 1:2

# The first line creates the root qdisc, and the next two lines
# create two child qdisc that are to be used to shape download
# and upload bandwidth.
#
# The 4th and 5th line creates the filter to match the interface.
# The 'dst' IP address is used to limit download speed, and the
# 'src' IP address is used to limit upload speed.

}

stop() {

# Stop the bandwidth shaping.
$TC qdisc del dev $IF root

}

restart() {

# Self-explanatory.
stop
sleep 1
start

}

show() {

# Display status of traffic control status.
$TC -s qdisc ls dev $IF

}

case "$1" in

start)

echo -n "Starting bandwidth shaping: "
start
echo "done"
;;

stop)

echo -n "Stopping bandwidth shaping: "
stop
echo "done"
;;

restart)

echo -n "Restarting bandwidth shaping: "
restart
echo "done"
;;

show)

echo "Bandwidth shaping status for $IF:"
show
echo ""
;;

*)

pwd=$(pwd)
echo "Usage: tc.bash {start|stop|restart|show}"
;;

esac

exit 0

But no luck... The speed is unlimited.
I tried to use this script:

Quote:

iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner test -j REJECT
to see if it rejects the packets created by "test" user, and it works. It rejects all the packets. Now the problem is what i have done wrong in the part of bandwidth limiting? I didn't marked correctly the packets, or my script is wrong? Please help me!

vishesh 08-01-2009 10:51 AM

Does htb implemented on ethernet interface
I mean ouput of
#ip a

I implemented htb for internet bandwidth sharing and it worked perfectly

thanks

alexxxutz 08-01-2009 11:27 AM

and how can i implement it? i have done just the steps i described

vishesh 08-01-2009 12:04 PM

There can be two possiblities
1. htb algorithm not get implemented on interface or
2. htb implemented successfully but not working according to aspectation

thats why i asked you about output of

#ip a


Thanks

alexxxutz 08-01-2009 01:06 PM

Here is the #ip a output
Quote:


1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:50:56:b5:3d:4b brd ff:ff:ff:ff:ff:ff
inet 94.24.x.x/24 brd 94.24.x.255 scope global eth0
inet 94.24.x.y/24 brd 94.24.x.255 scope global secondary eth0
inet 94.24.x.z/24 brd 94.24.x.255 scope global secondary eth0
inet6 fe80::250:56ff:feb5:3d4b/64 scope link
valid_lft forever preferred_lft forever
3: sit0: <NOARP> mtu 1480 qdisc noop
link/sit 0.0.0.0 brd 0.0.0.0

x,y,z are the last 2 blocks of my ip, but i have not written them here for security reasons

alexxxutz 08-02-2009 08:26 AM

so the htb is implemented or not? what i must do to enable it?

alexxxutz 08-03-2009 03:20 AM

well? :(

vishesh 08-03-2009 05:03 AM

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000

So its clear that pfifo_fast is working over your eth0 interface not htb.

Your program is not working properly .

Is there any error message appear when try to execute your script ?
#./tc.bash start

thanks

alexxxutz 08-04-2009 06:33 AM

no...

Quote:

[root@tolgyi-alexandru ~]# ./tc.bash start
Starting bandwidth shaping: done
[root@tolgyi-alexandru ~]#

alexxxutz 08-04-2009 06:45 AM

now it's working, but it limits the global speed on the server. how to limit only the rule marked by:
Quote:

iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner test -j MARK --set-mark 1

vishesh 08-04-2009 07:35 AM

according to your script you are limiting data coming or going from ip 216.3.128.12. There is no criteria for user test.

replace following
U32="$TC filter add dev $IF protocol ip parent 1:0 prio 1 u32"
and
start()
{
...
$U32 match ip dst $IP/32 flowid 1:1
$U32 match ip src $IP/32 flowid 1:2
}
with
start()
{
$TC qdisc add dev $IF root handle 1: htb default 30
$TC class add dev $IF parent 1: classid 1:1 htb rate $DNLD
$TC filter add dev $IF protocol ip parent 1:0 prio 1 handle 1 fw flowid 1:1
}


I think that may work to control download speed and same logic to control upload speed

Thanks
www.linuxinterviews.blogspot.com might also help you.

jomen 08-04-2009 08:28 AM

vishesh: I was writing while you posted - but mine is a little different ;)

alexxxutz:
You should probably take the POSTROUTING chain instead of OUTPUT (see: man iptables)
Are you sure that the -m owner --uid-owner is really what you want?
from man iptables:
Quote:

--uid-owner userid[-userid]
Matches if the packet socket's file structure (if it has one) is owned by the given user. You may also specify a numerical UID, or an UID range.
So: it is not really about a username as such.

You want to control ssh? Then you can use its port (22) in the match, instead of the "-m owner" match.
Or use "-m layer7" to match for ssh traffic...


generally, if you want to use iptables and its marks for filtering:

Code:

# you create a new rule in the mangle table

$PRIO="123" #some number
IPT="$IPTABLES -t mangle"

$IPT -N myfilter

# you add it to the POSTROUTING chain

$IPT -A POSTROUTING -j myfilter

# if conntrack is used - restore a mark and allow the packets, which already have been marked, through - no need to check again

$IPT -A myfilter -p tcp -j CONNMARK --restore-mark
$IPT -A myfilter -m mark --mark $PRIO -j ACCEPT

# you add to it your matching rule

$IPT -A myfilter -p tcp -m owner --uid-owner test -j MARK --set-mark $PRIO

# you conntrack it optionally, so not every packet has to be rematched

$IPT -A myfilter -j CONNMARK --save-mark

# you use that mark in a tc filter rule

$TC qdisc add dev $IF root handle 1: htb default 30
$TC class add dev $IF parent 1: classid 1:1 htb rate $your_rate

# add an SFQ qdisc to the end - to which you then attach the actual filter
$TC qdisc add dev $IF parent 1:1 sfq perturb 10

$TC filter add dev $IF parent 1:1 prio 1 handle $PRIO fw flowid 1:1

It is not a working example - but shows the concept.

alexxxutz 08-04-2009 08:41 AM

ok. now all seems to be ok, but now the speed still unlimited on any user i set... so the mark don't works... i have a tunneling service via ssh (port forwarding) and i want to limit the speed for each client. for example 1 euro = 64kB/s 2 euro = 128kB/s. so i want to make 2 groups. one for 1 euro packet speed and other for the 2 euro packet. for that reason i need to use owner

jomen 08-04-2009 08:55 AM

...but the "owner" may not quite work the way you think it does... [this line added/edited]

:D if you give me 20 I'll write the script :cool:
Please look at vishesh's post again - it has been edited with regard to the mark (last line)

rakib_sarder 07-04-2010 03:24 PM

but mine does not work ........
whenever i run the command
#bash tc.bash

it shows......

#'c.bash: line 23: synax error near unexpected token '{
'c.bash: line 23: 'start()

please help me......


All times are GMT -5. The time now is 04:56 PM.