IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> iptables匹配connlimit限制并发连接数量 -> 正文阅读

[网络协议]iptables匹配connlimit限制并发连接数量

以下规则将每个IP的最大并发连接数量控制在5个,使用connlimit-above或者connlimit-upto都可实现。

# iptables -I INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 5 -j DROP 
# 
# iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x17/0x02 #conn src/32 > 5
#
#
# iptables -I INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-upto 5 -j ACCEPT
# 
# iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x17/0x02 #conn src/32 <= 5

以下规则将每个C网段内的所有地址的连接总数量控制在5个。

# iptables -I INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 5 --connlimit-mask 24 -j DROP 
# 
# iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x17/0x02 #conn src/24 > 5

默认情况下–connlimit-saddr是生效的,以下指定–connlimit-daddr,控制到每个目的地址的连接数量不超过5个。

# iptables -I INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 5 --connlimit-daddr -j DROP        
# 
# iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x17/0x02 #conn dst/32 > 5

connlimit匹配

内核函数connlimit_mt_init注册了connlimit_mt_reg匹配结构。

static struct xt_match connlimit_mt_reg __read_mostly = {
    .name       = "connlimit",
    .revision   = 1,
    .family     = NFPROTO_UNSPEC,
    .checkentry = connlimit_mt_check,
    .match      = connlimit_mt,
    .matchsize  = sizeof(struct xt_connlimit_info),
    .usersize   = offsetof(struct xt_connlimit_info, data),
    .destroy    = connlimit_mt_destroy,
    .me         = THIS_MODULE,
};
static int __init connlimit_mt_init(void)
{
    return xt_register_match(&connlimit_mt_reg);
}

配置检查函数connlimit_mt_check如下,这里初始化conncount相关结构,keylen包括zone区ID和相应协议组的地址长度。

static int connlimit_mt_check(const struct xt_mtchk_param *par)
{
    struct xt_connlimit_info *info = par->matchinfo;
    unsigned int keylen;

    keylen = sizeof(u32);
    if (par->family == NFPROTO_IPV6)
        keylen += sizeof(struct in6_addr);
    else
        keylen += sizeof(struct in_addr);

    /* init private data */
    info->data = nf_conncount_init(par->net, par->family, keylen);

    return PTR_ERR_OR_ZERO(info->data);

匹配函数connlimit_mt,如果报文已经带有连接跟踪结构,取出其中的原始方向tuple,否则,解析报文的tuple,解析失败,返回false,未能匹配。

static bool
connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
    const struct xt_connlimit_info *info = par->matchinfo;
    struct nf_conntrack_tuple tuple;
    const struct nf_conntrack_tuple *tuple_ptr = &tuple;
    const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
    const struct nf_conn *ct;
    u32 key[5];

    ct = nf_ct_get(skb, &ctinfo);
    if (ct != NULL) {
        tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
        zone = nf_ct_zone(ct);
    } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
                      xt_family(par), net, &tuple)) {
        goto hotdrop;
    }

否则,成功获取报文的tuple信息,对于IPv6,如果设置了XT_CONNLIMIT_DADDR标志(–connlimit-daddr),key值选取报文的目的地址,否则,选取源地址。

    if (xt_family(par) == NFPROTO_IPV6) {
        const struct ipv6hdr *iph = ipv6_hdr(skb);
        union nf_inet_addr addr;

        memcpy(&addr.ip6, (info->flags & XT_CONNLIMIT_DADDR) ?
               &iph->daddr : &iph->saddr, sizeof(addr.ip6));

        for (i = 0; i < ARRAY_SIZE(addr.ip6); ++i)
            addr.ip6[i] &= info->mask.ip6[i];
        memcpy(key, &addr, sizeof(addr.ip6));
        key[4] = zone->id;
    } else {
        const struct iphdr *iph = ip_hdr(skb);
        key[0] = (info->flags & XT_CONNLIMIT_DADDR) ?
              iph->daddr : iph->saddr;
        key[0] &= info->mask.ip;
        key[1] = zone->id;
    }

对于IPv4协议,处理与以上相同,另外,key值中的地址部分需要与配置的掩码进行与操作(&)。之后,由key值和tuple值来获取连接的数量,最后,检查是否满足限制条件。

   connections = nf_conncount_count(net, info->data, key, tuple_ptr, zone);
   if (connections == 0)
       /* kmalloc failed, drop it entirely */
       goto hotdrop;

   return (connections > info->limit) ^ !!(info->flags & XT_CONNLIMIT_INVERT);

hotdrop:
   par->hotdrop = true;
   return false;

内核版本 5.10

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:30:49  更:2022-03-21 21:31:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:45:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码