zoukankan      html  css  js  c++  java
  • [草稿][内容垃圾勿看]netfiler源代码分析

    ip_rcv, ip_rcv_finish

    钩子函数注册时间?nf_register_hooks
    模块初始化的时候,如filter模块初始化的时候module_init(iptable_filter_init);

    nf_hook_ops是某个hook点的函数链,由list来指定下一个处理函数(结构也是nf_hook_ops),优先级并不是通过链表顺序来指定的,而是有priority选项来指定的。?如何找到下一个正好的优先级?
    A:hook函数链表是按优先级排序的,在插入hook函数的时候,找到第一个优先级比此hook函数小的,在这个小的函数之前插入。

    struct nf_hook_ops
    {
    struct list_head list;
    /* User fills in from here down. */
    nf_hookfn *hook;
    struct module *owner;
    int pf;
    int hooknum;
    /* Hooks are ordered in ascending priority. */
    int priority;
    };

    firewall rule由三部分组成:
    include/linux/netfilter_ipv4/ip_tables.h
    ipt_entry:标准匹配结构,主要包含数据包的源、目的IP,出、入接口和掩码等;
    include/linux/netfilter/x_tables.h
    ipt_entry_match:扩展匹配。一条rule规则可能有零个或多个ipt_entry_match结构;
    include/linux/netfilter/x_tables.h
    ipt_entry_target:一条rule规则有且仅有一个target动作。就是当所有的标准匹配和扩展匹配都符合之后才来执行该target。

    static struct xt_af *xt
    全局维护二位数组,由协议簇决定长度。其中每一个成员结构中包含所有表,match,target。


    iptable_filter_init filter初始化动作主要初始化了初始化filter表,将filter表插入全局表的双向链表中


    简而言之ipt_register_table()所做的事情就是从模板initial_table变量的repl成员里取出初始化数据,然后申请一块内存并用repl里的值来初始化它,之后将这块内存的首地址赋给packet_filter表的private成员,最后将packet_filter挂载到xt[2].tables的双向链表中。

    xt表和 nf_hook_ops如何共同工作的?


    Table->private

    /* The table itself */
    struct xt_table_info
    {
    /* Size per table */
    unsigned int size;
    /* Number of entries: FIXME. --RR */
    unsigned int number;
    /* Initial number of entries. Needed for module usage count */
    unsigned int initial_entries;

    /* Entry points and underflows */
    unsigned int hook_entry[NF_IP_NUMHOOKS];
    unsigned int underflow[NF_IP_NUMHOOKS];

    /* ipt_entry tables: one per CPU */
    char *entries[NR_CPUS];
    };


    连接跟踪首先进入ip_conntrack_defrag处理,将已经分片的ip报文组装。即连接跟踪只跟踪完整的IP报文,不对IP分片进行跟踪,所有的IP分片都必须被还原成原始报文,才能进入连接跟踪系统。

    ip_conntrack_in定义位置:net/ipv4/netfilter/ip_conntrack_core.c

    ip_ct_protos变量里保存连接跟踪系统当前可以处理的所有协议,协议号作为数组唯一的下标,如下图所示。

    连接跟踪表是由一个全局的双向链表指针变量ip_conntrack_hash[]来表示


    每一种协议需要,如果gre协议使用如下方式注册 :
    ip_conntrack_protocol_register(&gre);
    其中gre有如下定义
    static struct ip_conntrack_protocol gre = {
    .proto = IPPROTO_GRE,
    .name = "gre",
    .pkt_to_tuple = gre_pkt_to_tuple,
    .invert_tuple = gre_invert_tuple,
    .print_tuple = gre_print_tuple,
    .print_conntrack = gre_print_conntrack,
    .packet = gre_packet,
    .new = gre_new,
    .destroy = gre_destroy,
    .me = THIS_MODULE,
    #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) ||
    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
    .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
    .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
    #endif
    };

    对于tcp、udp和icmp协议,在netfiler框架初始化的时候就已经注册了。module_init(ip_conntrack_standalone_init)->ip_conntrack_init中有
    rcu_assign_pointer(ip_ct_protos[IPPROTO_TCP], &ip_conntrack_protocol_tcp);
    rcu_assign_pointer(ip_ct_protos[IPPROTO_UDP], &ip_conntrack_protocol_udp);
    rcu_assign_pointer(ip_ct_protos[IPPROTO_ICMP], &ip_conntrack_protocol_icmp);


    tuple用来区分不同的连接,如tcp报文转换为tuple时会关注src port和dst port
    TODO: ip tule how to create one?
    根据tuple找到对应的ip_coontrack_hash[hash],然后查找链表中是否有匹配,若有匹配则将ip_conntrack_tuple_hash返回,否则初始化连接跟踪(init_conntrack)。其中ip_conntrack_tuple_hash两部分组成,一部分是ip_conntrack_tuple,其中包含了标识某种协议的某个连接的信息,另一部分是list_head双向链表。
    初始化连接跟踪时会将ip和port等倒置,生成reply tuple(何时使用?)

    报文连接跟踪记录是什么时候产生的?区别于ip_conntrack_untracked,后者又是何时赋值的?

    在raw表中skb->nfct字段被设置成了ip_conntrack_untracked,所以如果后面没有设置连接跟踪的话,nfct字段就一直是ip_conntrack_untracked.

    该变量又是何意呢?我们知道iptables维护的其实是四张表,有一张raw不是很常用。该表以-300的优先级在PREROUTING和LOCAL_OUT点注册了ipt_hook函数,其优先级要高于连接跟踪。当每个数据包到达raw表时skb->nfct字段缺省都被设置成了ip_conntrack_untracked,所以当该skb还没被连接踪的话,其skb->nfct就一直是ip_conntrack_untracked。对于没有被连接跟踪处理过的skb是不能进行NAT的,因此遇到这种情况代码中直接返回ACCEPT。


    没看到ipt_hook方法中有设置untracked的地方

    ip_conntrack计算reply tuple如何应用?


    只有每条连接的第一个数据包才会经过nat表,而属于该连接的后续数据包会按照第一个数据包则会按照第一个报所执行的动作进行处理,不再经过nat表。Netfilter为什么要做这个限制?有什么好处?它又是如何实现的?
    从用户空间的iptables规则来看,每条规则都有一个counter计数器,该计数器记录的是被该规则成功匹配了数据包的数目。而内核中对该计数器的修改是在ipt_do_table()函数。从ip_nat_fn()函数的执行流程可以看出,当连接跟踪记录项被设置了IPS_SRC_NAT_DONE_BIT状态位,或者连接跟踪的状态不再是IP_CT_NEW状态时,ipt_do_table()函数就不再被调用了,反应在用户空间所看到的直观现象就是,nat表的规则计数器不再增长了。

    ip_conntrack_alter_reply将reply信息修改以使得reply tuple能够在连接跟踪中识别

    bysource有何作用?

    net/ipv4/netfilter/ip_nat_proto_tcp.c:tcp_manip_pkt


    SNAT在ip_nat_fn中根据将连接跟踪中的reply tuple修改(根据action,具体并找到),这样就能保证回程报文能够找到连接跟踪,并根据连接跟踪中的origin tuple做对应的De-NAT。NAT中在manip_pkt中完成的。

    SNAT或DNAT规则改变的ip依据在哪?

  • 相关阅读:
    ICON 收集
    vs2015with_update_3
    文件大全,以后就从这些格式入手fuzz
    诗词
    tools URL 收集
    (四)ORBSLAM运动估计
    (三)ORB特征匹配
    (二)ORB描述子提取源码思路与实现
    (一)ORB描述子提取
    双目立体匹配——归一化互相关(NCC)
  • 原文地址:https://www.cnblogs.com/haoqingchuan/p/5642016.html
Copyright © 2011-2022 走看看