Living in the Dark & Playing & with the Open Source is Fun & Amazingly Powerful ! z@iB
Scenario:
We have few Linux base FTP/HTTP base media file sharing server setup. User can access these server by bypassing the router as we donot want to put load on the router itself & user should access these servers from switch level by intervlan routing setup.
Problem:
Since the FTP data is in many terabytes and hundreds of users are accessing it, this is creating bottleneck for server’s network/storage.
Solution:
On Linux we can use TRAFFIC CONTROLLER (TC) to limit bandwidth on per user IP basis. We will create a simple bash script which will do the following in sequence …
- FTP Server IP: 101.11.11.254
- Clear any existing shaping rules
- Create 4 bandwidth packages as following
– 1024kbps [for General Users subnet 101.11.11.0/24]
– 2048kbps [for Support Staff subnet 101.11.50.0/24]
– 512kbps [for ICMP, so that ping should work fine , Protocol base]
– 128kbps [for any unknown IP series, that is no define above, for ALL 0.0.0.0/0.0.0.0] - Assign ip subnet to these packages (/24 and it will create per ip base rules via LOOP statement)
- In this example, we are limiting Bandwidth in one way only, means packets sending from server to client will be applied limitation .. For both ways just duplicate rules and use src as well.
Create , the script!
mkdir /temp touch /temp/shaper.sh chmod +x /temp/shaper.sh
Now Edit
nano /temp/shaper.sh
& paste following,
#!/bin/bash # Traffic Shaping Using `TC` in Linux / This was made for specific requirements. # ITs customzied designed to fulfill some specific requirements & it went well. # Following Script will limit outgoing bandwidth for specific ip range series. # It will also allow ICMP more bandwidth so that ping to local server may not delay or imtout. # It will then limit all other ips that are not listed to minimum bandwidth that is 128kbps. # Adjust is as per your requirements. # Syed Jahanzaib / aacable @ hotmail . com / https://aacable.wordpress.com :~) # 23-Febraury-2018 # Enable following to see debug # set -x # Local Network Interface name INT="ens33" INT_SPEED="100Mbit" # First IP Range & its package with class IP1="101.11.11" IP1_PKG="1mbit" IP1_CLASSID="1:10" # Second IP Range & its package with class IP2="101.11.50" IP2_PKG="2mbit" IP2_CLASSID="1:20" # Separate Bandwidth for ICMP protocol to minimze delay in PING/ICMP packets ICMP_PKG="512kbit" ICMP_CLASSID="1:200" # Other Default Package Line, means all other unmarked IP's or traffic UNKNOWN_PKG="128kbit" UNKNOWN_CLASSID="1:201" if [[ "$1" != "start" && "$1" != "stop" && "$1" != "status" ]]; then echo "Usage: ./shaper.sh start ./shaper stop ./shaper status by Jz!" exit 1 fi if [ $1 == "stop" ]; then echo "Clearing all existing Queues on user request ... Done!" tc qdisc del dev $INT root 2> /dev/null > /dev/null exit 1 fi if [ $1 == "status" ]; then echo "Showing Current TC Class and Filter Status ==========================================" tc class show dev $INT echo " " tc -s -d class show dev $INT echo "==========================================" exit 1 fi if [ $1 == "start" ]; then echo "Starting Shaper ... Clearing all existing Queues for re-implementation ... ==========================================" " # clean existing down- and uplink qdiscs, hide errors tc qdisc del dev $INT root 2> /dev/null > /dev/null echo " Adding Queues ...." # Create egress shaping for all required classes tc qdisc add dev $INT root handle 1: htb default 20 r2q 50 tc class add dev $INT parent 1: classid 1:1 htb rate $INT_SPEED ceil $INT_SPEED tc class add dev $INT parent 1:1 classid $IP2_CLASSID htb rate $IP1_PKG ceil $IP1_PKG prio 100 tc class add dev $INT parent 1:1 classid $IP1_CLASSID htb rate $IP2_PKG ceil $IP2_PKG prio 100 tc class add dev $INT parent 1:1 classid $ICMP_CLASSID htb rate $ICMP_PKG ceil $ICMP_PKG prio 100 tc class add dev $INT parent 1:1 classid $UNKNOWN_CLASSID htb rate $UNKNOWN_PKG ceil $UNKNOWN_PKG prio 100 # ICMP reply Adjustment so ping may not timeout or high delay may not occur at client end for this server local IP tc filter add dev $INT parent 1: protocol ip prio 100 u32 match ip protocol 1 0xff flowid $ICMP_CLASSID # IP-1 series limitation applies here ... for (( i = 1 ; i <= 255; i++ )) do b=$i tc filter add dev $INT parent 1: protocol ip prio 100 u32 match ip dst $IP1.$i flowid $IP1_CLASSID done # IP-2 series limitation applies here ... for (( i = 1 ; i <= 255; i++ )) do b=$i tc filter add dev $INT parent 1: protocol ip prio 100 u32 match ip dst $IP2.$i flowid $IP2_CLASSID done # Send every unknown IP to classid UNKNOWN_CLASS that is lowest. so that any IP that is not listed above will get htis lowest bandwidth tc filter add dev $INT parent 1: protocol ip prio 100 u32 match ip dst 0.0.0.0/0.0.0.0 flowid $UNKNOWN_CLASSID echo " Done!" fi
Result: