zoukankan      html  css  js  c++  java
  • netfiler/iptables

    一. 什么是netfilter

    netfilter is a set of hooks inside the Linux kernel that allows kernel modules to register callback functions with the network stack. A registered callback function is then called back for every packet that traverses the respective hook within the network stack.

    iptables is a generic table structure for the definition of rulesets. Each rule within an IP table consists of a number of classifiers (iptables matches) and one connected action (iptables target).

    netfilter, ip_tables, connection tracking (ip_conntrack, nf_conntrack) and the NAT subsystem together build the major parts of  the packet filtering framework. Software inside this framework enables packet filtering, network address [and port] translation (NA[P]T) and other packet mangling. 

    linux防火墙通常包含两部分,分别为iptables和netfilter。iptables是linux管理防火墙规则的命令行工具,处于用户空间。netfilter执行报文过滤,处于linux内核空间。有时也将iptables统称linux防火墙。

    Netfilter提供了过滤网络数据报的底层机制。Netfilter提供了基于其上的一整套工具集合,即其各个子系统,包括:连接跟踪、NAT、xtables、iptables/iptables6、nftables、arptables。

    在netfilter的官网www.netfilter.org上,可以看到netfilter的一个子项目patch-o-matic,其中收录了大量的各种定制kernel modules,这些modules给我们展示了很多使用例程。

    netfilter的优势不仅包含防火墙的实现,还包括各种报文的处理工作(如报文的加密、统计等)。用户可以方便地利用netfilter提供的接口实现内核层的报文处理。

    二. netfilter框架

    netfilter在linux内核中的IPv4、IPv6和DECnet等网络协议栈中都有相应的实现。以常用的IPv4协议栈上netfilter的实现为例说明。

    IPv4协议栈为了实现对netfilter架构的支持,在IP包的IPv4协议栈上的传递过程之中,选择了5个检查点。在这5个检查点上,各引入了一行对NF_HOOK()宏函数的一个相应的调用:

    PREROUTING、LOCAL-IN、FORWARD、LOCAL-OUT和POSTROUTING。

    利用netfilter中的5个参考点,查阅用户注册的回调函数,根据用户定义的回调函数来监视进出的网络数据包,是netfilter的基本实现框架。

    netfilter核心代码位于linux/net/netfilter目录下。

    1. 如何切入协议栈

    在IPv4协议栈中,netfilter在IP数据包的路线上选取了5个挂节点(HOOK)。这5个点,在合适的位置对NF_HOOK()宏函数进行了调用。

    static inline int 
    NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb,
        struct net_device *in, struct net_device *out,
        int (*okfn)(struct sk_buff *)) 
    {
        return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN);
    }

    pf:协议族,如PF_INET、PF_INET6、PF_DECnet等
    hook:HOOK点,如:PRE_ROUTING、LOCAL_IN、FORWARD、LOCAL_OUT、POST_ROUTING
    skb:sk_buff
    indev:数据包入站的设备(某些情况下为空值)
    outdev:数据包出站的设备(某些情况下为空值)
    okfn:  函数指针,指向协议栈下一步的处理函数,当Netfilter该HOOK点流程结束时调用该函数。

    示例:

    int ip_forward(struct sk_buff *skb)
    {
        /* protocol stack processing */
    
       return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev,
                   rt->dst.dev, ip_forward_finish);
    }

    2. 回调函数

    netfilter定义了一个全局变量来存储用户的回调函数:

    struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;
    EXPORT_SYMBOL(nf_hooks);

    NFPROTO_NUMPROTO是协议类型,可以是TCP、UDP或IP协议。NF_MAX_HOOKS是挂接的钩子的最大数量。

    用户可以挂接回调函数到netfilter架构上,函数为nf_register_hook()。

    int nf_register_hook(struct nf_hook_ops *reg)
    {
        struct nf_hook_ops *elem;
        int err;
    
        err = mutex_lock_interruptible(&nf_hook_mutex);
        if (err < 0)
            return err;
        list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
            if (reg->priority < elem->priority)
                break;
        }   
        list_add_rcu(&reg->list, elem->list.prev);
        mutex_unlock(&nf_hook_mutex);
    #if defined(CONFIG_JUMP_LABEL)
        static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
    #endif
        return 0;
    }
    EXPORT_SYMBOL(nf_register_hook);

    可以看出注册函数根据优先级,将用户的回调函数放到全局变量nf_hooks中。

    回调函数用结构体struct nf_hook_ops存储:

    struct nf_hook_ops;
    typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,
                       struct sk_buff *skb,
                       const struct net_device *in,
                       const struct net_device *out,
                       int (*okfn)(struct sk_buff *));
    
    struct nf_hook_ops {
        struct list_head list;
    
        /* User fills in from here down. */
        nf_hookfn   *hook;
        struct module   *owner;
        void        *priv;
        u_int8_t    pf;
        unsigned int    hooknum;
        /* Hooks are ordered in ascending priority. */
        int     priority;
    };

    回调函数的返回值:

    NF_ACCEPT 继续正常传输数据报
    NF_DROP 丢弃该数据报,不再传输
    NF_STOLEN 模块接管该数据报,告诉Netfilter“忘掉”该数据报
    NF_QUEUE 对该数据报进行排队,等待用户空间的进程处理
    NF_REPEAT 再次调用该回调函数
    NF_STOP 终止Netfilter的后续处理,将数据报交还给协议栈

    实现注册回调函数步骤:

    1. 实现自己的HOOK函数;
    2. 初始化一个struct nf_hook_ops的对象;
    3.调用nf_register_hook注册HOOK函数,注销时调用nf_unregister_hook;也可以调用nf_register_hooks和nf_unregister_hooks一次注册注销多个HOOK函数;

    三. iptables

    Iptables是基于netfilter实现的有状态防火墙,Iptables包括用户层工具和内核中的HOOK函数集合。Iptables rule的要素:
    Chain:PREROUTING、INPUT、OUTPUT、FORWARD、POSTROUTING,对应Netfilter的五个HOOK点
    Tables:filter,nat,mangle,raw, security
    Match:各种匹配条件,包括标准匹配和扩展匹配
    Target:匹配后的目标Action,一条rule可以有多个match,但只能有一个target

    防火墙的作用就在于对经过的报文匹配“规则”(match),然后执行对应的“动作”(target)。

    参考:

    1. http://www.netfilter.org/

    2. linux网络编程 宋敬彬

    3.  iptables用法

  • 相关阅读:
    每日一题 为了工作 2020 0412 第四十一题
    每日一题 为了工作 2020 04011 第四十题
    每日一题 为了工作 2020 0410 第三十九题
    每日一题 为了工作 2020 0409 第三十八题
    每日一题 为了工作 2020 0408 第三十七题
    每日一题 为了工作 2020 0407 第三十六题
    每日一题 为了工作 2020 0406 第三十五题
    每日一题 为了工作 2020 0405 第三十四题
    学习总结(二十四)
    学习总结(二十三)
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/7895256.html
Copyright © 2011-2022 走看看