1

The script blow tries to limit the incoming rate of the port 2000, when using iptables to mark the INPUT packets does not work, but OUTPUT works fine.

I use nc -kl 2000 on machine 10.0.1.54 and iperf -c 10.0.1.54 -p 2000 -t 10 on another machine to test it.

Why OUTPUT works but not INPUT?

dev=enp3s0
ip_addr=10.0.1.54
ip_port=2000

rate_limit=20kbit
htb_class=10

if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi

if [ "$1" = "enable" ]; then
    echo "enabling rate limits"
    tc qdisc del dev $dev root > /dev/null 2>&1
    tc qdisc add dev $dev root handle 1: htb

    tc class add dev $dev parent 1: classid 1:$htb_class htb rate $rate_limit ceil $rate_limit
    tc filter add dev $dev parent 1: prio 0 protocol ip handle $htb_class fw flowid 1:$htb_class

    # marking the INPUT chain does dot work as expected
    #iptables -t mangle -A INPUT -d $ip_addr -p tcp --dport $ip_port -j MARK --set-mark $htb_class

    # marking the OUTPUT chain works fine
    iptables -t mangle -A OUTPUT -s $ip_addr -p tcp --sport $ip_port -j MARK --set-mark $htb_class
elif [ "$1" = "disable" ]; then
    echo "disabling rate limits"
    tc qdisc del dev $dev root > /dev/null 2>&1

    #iptables -t mangle -D INPUT -d $ip_addr -p tcp --dport $ip_port -j MARK --set-mark $htb_class
    iptables -t mangle -D OUTPUT -s $ip_addr -p tcp --sport $ip_port -j MARK --set-mark $htb_class
elif [ "$1" = "show" ]; then
    tc qdisc show dev $dev
    tc class show dev $dev
    tc filter show dev $dev
    iptables -t mangle -vnL INPUT
    iptables -t mangle -vnL OUTPUT
else
    echo "invalid arg $1"
fi

3 Answers3

2

I try to answer this question by listing links below:

There are two modes of traffic shaping, INGRESS and EGRESS. INGRESS handles incoming traffic and EGRESS outgoing traffic. Linux does not support shaping/queuing on INGRESS, but only policing. Therefore IFB exists, which we can attach to the INGRESS queue while we can add any normal queuing like FQ_CODEL as EGRESS queue on the IFB device. [http://wiki.gentoo.org/wiki/Traffic_shaping]

So, my solution to this question is:

#!/bin/bash

dev=enp3s0
ifb_dev=ifb0
ip_addr=10.0.1.54
ip_port=2000

rate_limit=20kbit
htb_class=10

if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi

modprobe ifb
ifconfig ifb0 up

if [ "$1" = "enable" ]; then
    echo "enabling rate limits"

    tc qdisc add dev $dev handle ffff: ingress
    tc filter add dev $dev parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $ifb_dev

    tc qdisc add dev $ifb_dev root handle 1: htb
    tc class add dev $ifb_dev parent 1: classid 1:$htb_class htb rate $rate_limit ceil $rate_limit

    tc filter add dev $ifb_dev parent 1: protocol ip prio 1000 u32 match ip dport 2001 0xffff flowid 1:$htb_class

elif [ "$1" = "disable" ]; then
    echo "disabling rate limits"

    tc qdisc del dev $dev root > /dev/null 2>&1
    tc qdisc del dev $dev ingress > /dev/null 2>&1
    tc qdisc del dev $ifb_dev root > /dev/null 2>&1
    tc qdisc del dev $ifb_dev ingress > /dev/null 2>&1

elif [ "$1" = "show" ]; then

    tc qdisc show dev $dev
    tc class show dev $dev
    tc filter show dev $dev

else
    echo "invalid arg $1"
fi
1

what jinzheng said is right, you cannot shape ingress traffic. but you can do it like captain jack sparrow...change the facts.

create a openvpn connection between your host and a vps with "redirect-gateway" so all the traffic goes over the vps. so that it looks like this: your home network/pc -> internet -> vps -> internet

what for your home network is INGRESS is EGRESS for the vps then shape the outgoing interface on the vps.

some tips: remember to specify your home network/ip or you will kill the vps upload rate. the vps has to have better bandwidth than your homenetwork, measure the bandwith. in germany you could just get a 7€ vps from hetzner.de they are pretty reliable.

0

Its not necessary do to that, its simple you just need to patch kernel and iptables and than you can shape incoming traffic, + if youre using LXC then you don't even need to patch anything, just on KVM