iptables匹配physdev

本文详细解读iptables的physdevmatch模块,涉及输入输出接口匹配、网桥流量控制规则,以及在不同链路的使用限制。重点讲解了如何配置匹配由网桥发出和子接口发送的报文,以及注意事项和br_netfilter模块的依赖。
摘要由CSDN通过智能技术生成

physdev匹配帮助信息如下。

# iptables -m physdev -h

physdev match options:
 [!] --physdev-in inputname[+]          bridge port name ([+] for wildcard)
 [!] --physdev-out outputname[+]        bridge port name ([+] for wildcard)
 [!] --physdev-is-in                    arrived on a bridge device
 [!] --physdev-is-out                   will leave on a bridge device
 [!] --physdev-is-bridged               it's a bridged packet

–physdev-in 匹配报文入方向虚拟网桥的物理接口名称,最后的字符+匹配随后的任何字符。
–physdev-out 匹配报文出方向虚拟网桥的物理接口名称。
–physdev-is-in 匹配由网桥接收到的报文,
–physdev-is-out 匹配由网桥发送的报文。
–physdev-is-bridged 匹配在网桥内部中转发的报文,仅在FORWARD和POSTROUTING点有效。

如下配置策略,匹配由网桥发出,并且由网桥子接口ens39发出的报文。

# ip link add br0 type bridge
# ip link set ens39 master br0
#
# iptables -A FORWARD -m physdev --physdev-is-out --physdev-out ens39 -j ACCEPT    
# 
# iptables -L -n -v

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-is-out --physdev-out ens39

physdev匹配

函数xt_register_matche注册匹配结构physdev_mt_reg。

static struct xt_match physdev_mt_reg __read_mostly = {
    .name       = "physdev",
    .revision   = 0,
    .family     = NFPROTO_UNSPEC,
    .checkentry = physdev_mt_check,
    .match      = physdev_mt,
    .matchsize  = sizeof(struct xt_physdev_info),
    .me         = THIS_MODULE,
};

static int __init physdev_mt_init(void)
{
    return xt_register_match(&physdev_mt_reg);

配置项检查函数,首先判断是否为以上定义的5种配置选项(XT_PHYSDEV_OP_MASK);其次,对于配置项–physdev-out和–physdev-is-out,仅支持在FORWARD和POSTROUTING点配置,但是,只有在配置OUTPUT链时,出错并提示以下错误,对于INPUT和PREROUTING可配置成功,没有告警。

# iptables -t mangle -A OUTPUT -m physdev --physdev-out ens39 -j ACCEPT
#
# dmesg | tail
[2712782.456829] Bridge firewalling registered
[2712850.494235] xt_physdev: --physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic

另外,此功能需要br_netfilter内核模块。

static int physdev_mt_check(const struct xt_mtchk_param *par)
{
    const struct xt_physdev_info *info = par->matchinfo;
    static bool brnf_probed __read_mostly;

    if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
        info->bitmask & ~XT_PHYSDEV_OP_MASK)
        return -EINVAL;
    if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) &&
        (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || info->invert & XT_PHYSDEV_OP_BRIDGED) &&
        par->hook_mask & (1 << NF_INET_LOCAL_OUT)) {
        pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n");
        return -EINVAL;
    }
    if (!brnf_probed) {
        brnf_probed = true;
        request_module("br_netfilter");
    }

匹配函数physdev_mt如下,首先,判断网桥信息是否存在,在报文经过NF_BR_PRE_ROUTING时将创建此结构(br_nf_pre_routing)。如果网桥信息不存在,并且没有配置取反操作,返回不匹配。否则,匹配。

static bool
physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
    const struct xt_physdev_info *info = par->matchinfo;
    const struct net_device *physdev;
    unsigned long ret;
    const char *indev, *outdev;

    /* Not a bridged IP packet or no info available yet:
     * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
     * the destination device will be a bridge. */
    if (!nf_bridge_info_exists(skb)) {
        /* Return MATCH if the invert flags of the used options are on */
        if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
            !(info->invert & XT_PHYSDEV_OP_BRIDGED))
            return false;
        if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
            !(info->invert & XT_PHYSDEV_OP_ISIN))
            return false;
        if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
            !(info->invert & XT_PHYSDEV_OP_ISOUT))
            return false;
        if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
            !(info->invert & XT_PHYSDEV_OP_IN))
            return false;
        if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
            !(info->invert & XT_PHYSDEV_OP_OUT))
            return false;
        return true;
    }

这里网桥信息存在,表明报文由网桥子接口进入,如果出接口不是网桥的子接口,对于physdev-is-bridged网桥转发选项,不匹配。

    physdev = nf_bridge_get_physoutdev(skb);
    outdev = physdev ? physdev->name : NULL;

    /* This only makes sense in the FORWARD and POSTROUTING chains */
    if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
        (!!outdev ^ !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
        return false;

对于physdev-is-in配置项,如果indev不存在,或者对于physdev-is-out配置项,如果outdev不存在,表明不匹配。

    physdev = nf_bridge_get_physindev(skb);
    indev = physdev ? physdev->name : NULL;

    if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
        (!indev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
        (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
        (!outdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
        return false;

对于physdev-in配置项,如果没有开启,跳转到下一个判断(match_outdev)。否则,在入接口存在的情况下,比较入接口名称是否相符。入接口不存在的情况下,开始比较下一个physdev-out出接口。

    if (!(info->bitmask & XT_PHYSDEV_OP_IN))
        goto match_outdev;

    if (indev) {
        ret = ifname_compare_aligned(indev, info->physindev, info->in_mask);

        if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN))
            return false;
    }

对于physdev-out配置项,比较出接口名称是否相符。

match_outdev:
    if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
        return true;

    if (!outdev)
        return false;

    ret = ifname_compare_aligned(outdev, info->physoutdev, info->out_mask);

    return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT));

内核版本 5.10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值