如何使用 iptables 或 tc 来限制每个客户端的数据包。

如何使用 iptables 或 tc 来限制每个客户端的数据包。

我遇到了一些问题网络客户端,它们发送数据的速度太快。

我想使用 iptables 或者可能是 tc 来减慢它们的速度。

我见过如下 iptables 解决方案:

sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 50/second --limit-burst 50 -j ACCEPT

但我认为该限制适用于符合规则的所有内容,而不是每个客户端地址。

有没有办法让这条规则限制每个客户端地址的数据包?

答案1

你可以用一种简单的方法解决这个问题,尝试使用带有 iptables 的 recent 模块,recent 会跟踪源地址:

iptables -m recent -h
recent match options:
[!] --set                       Add source address to list, always matches.
[!] --rcheck                    Match if source address in list.
[!] --update                    Match if source address in list, also update last-seen time.
[!] --remove                    Match if source address in list, also removes that address from list.
    --seconds seconds           For check and update commands above.
                                Specifies that the match will only occur if source address last seen within
                                the last 'seconds' seconds.
    --reap                      Purge entries older then 'seconds'.
                                Can only be used in conjunction with the seconds option.
    --hitcount hits             For check and update commands above.
                                Specifies that the match will only occur if source address seen hits times.
                                May be used in conjunction with the seconds option.
    --rttl                      For check and update commands above.
                                Specifies that the match will only occur if the source address and the TTL
                                match between this packet and the one which was set.
                                Useful if you have problems with people spoofing their source address in order
                                to DoS you via this module.
    --name name                 Name of the recent list to be used.  DEFAULT used if none given.
    --rsource                   Match/Save the source address of each packet in the recent list table (default).
    --rdest                     Match/Save the destination address of each packet in the recent list table.
    --mask netmask              Netmask that will be applied to this recent list.

阻止 ssh 暴力破解的示例:

iptables -A INPUT -i eth0 -p tcp --syn --dport 22 -m recent --name ssh --set
iptables -A INPUT -i eth0 -p tcp --syn --dport 22 -m recent --name ssh --rcheck --seconds  30 --hitcount 2 -j DROP

答案2

我使用 TC 和 iptables hashlimit 的组合来实现这一点。我在 LAN 接口上创建了一个 TC 带宽限制器(用于下载流量),设置为 5 Mbits/秒。然后,我在接口的输出 mangle 链中使用 iptables hashlimit 模块,这样,如果数据包速率超过某个阈值,则在任何两个不同的源和目标 IP 地址之间,它就会开始将这些数据包分类到 TC 5 Mbit/s 流量整形类中。

不过,您必须正确设置数据包阈值,我根据 MTU 为 1500 字节的事实来设置阈值,因此使用它来计算每秒需要多少个数据包才能创建 1.5 Mbits 每秒的阈值(1000 个数据包/秒)。再加上在 hashlimit iptables 模块上设置最高可能的突发值(在我的设置中,似乎是 10,000),所有这些的结果是短距离下载以全速运行,但较长的下载开始变慢,因为一些数据包被传递到 TC 带宽限制类,这显然会降低数据包速率等。这有点像黑客行为,但令人惊讶的是它确实有效,而且效果很好。而且由于使用了 TC,所以不会丢弃任何数据包 - 只是由于在达到数据包速率后被推入 TC 类而延迟和变慢。

这是在 CentOS 6 机器上。我认为更现代的东西允许 hashlimit 模块支持每秒字节数,而不仅仅是每秒数据包数,这甚至更好,但我在我的设置上尝试了这一点,它只是恢复到使用每秒数据包数。

我现在正在使用手机,所以无法粘贴任何配置,但如果您想要一些示例,请告诉我,我会编辑这个答案。我非常喜欢这个解决方案,因为我所进行的限制是基于源 IP 和目标 IP 的。因此,系统将每个不同的 src+dst IP 组合视为其自己的数据包流以进行限制。hashlimit 模块也支持源端口和目标端口(基本上是源 IP、源端口、目标 IP、目标端口的任意组合),因此您甚至可以在源 IP+端口和目标 IP+端口之间基于每个会话进行限制。

更新

下面大致就是操作方法;需要进行实验。

TC:

/sbin/tc qdisc add dev eth0 root handle 1: htb
/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 5Mbit

iptables:

#!/bin/bash

[[ "$1" =~ ^[ADI]$ ]] || exit 1

for IPT in /sbin/ip{,6}tables
do
  $IPT -t mangle -$1 POSTROUTING -o eth0 -m hashlimit --hashlimit-above 1000/second --hashlimit-burst 10000 --hashlimit-mode srcip,dstip --hashlimit-name limiter -j CLASSIFY --set-class 1:1
done

答案3

您也许可以使用 connlimit 模块来解决这个问题:

http://www.cyberciti.biz/faq/iptables-connection-limits-howto/

相关内容