snat analysis

1, target registration

net/netfilter/xt_nat.c

static struct xt_target xt_nat_target_reg[] __read_mostly = {
    {
        .name        = "SNAT",
        .revision    = 0,
        .checkentry    = xt_nat_checkentry_v0,
        .target        = xt_snat_target_v0,
        .targetsize    = sizeof(struct nf_nat_ipv4_multi_range_compat),
        .family        = NFPROTO_IPV4,
        .table        = "nat",
        .hooks        = (1 << NF_INET_POST_ROUTING) |
                  (1 << NF_INET_LOCAL_IN),
        .me        = THIS_MODULE,
    },
    {
        .name        = "DNAT",
        .revision    = 0,
        .checkentry    = xt_nat_checkentry_v0,
        .target        = xt_dnat_target_v0,
        .targetsize    = sizeof(struct nf_nat_ipv4_multi_range_compat),
        .family        = NFPROTO_IPV4,
        .table        = "nat",
        .hooks        = (1 << NF_INET_PRE_ROUTING) |
                  (1 << NF_INET_LOCAL_OUT),
        .me        = THIS_MODULE,
    },
    {
        .name        = "SNAT",
        .revision    = 1,
        .target        = xt_snat_target_v1,
        .targetsize    = sizeof(struct nf_nat_range),
        .table        = "nat",
        .hooks        = (1 << NF_INET_POST_ROUTING) |
                  (1 << NF_INET_LOCAL_IN),
        .me        = THIS_MODULE,
    },
    {
        .name        = "DNAT",
        .revision    = 1,
        .target        = xt_dnat_target_v1,
        .targetsize    = sizeof(struct nf_nat_range),
        .table        = "nat",
        .hooks        = (1 << NF_INET_PRE_ROUTING) |
                  (1 << NF_INET_LOCAL_OUT),
        .me        = THIS_MODULE,
    },
};

xt_nat_init
   xt_register_targets (as snat, dnat target register, when the kernel to add a rule, to find the name of the rule in accordance with the corresponding target follow-up user mode)

2、nat hook注册
net/ipv4/netfilter/iptable_nat.c

static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
    /* Before packet filtering, change destination */
    {
        .hook        = iptable_nat_ipv4_in,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_PRE_ROUTING,
        .priority    = NF_IP_PRI_NAT_DST,
    },
    /* After packet filtering, change source */
    {
        .hook        = iptable_nat_ipv4_out,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_POST_ROUTING,
        .priority    = NF_IP_PRI_NAT_SRC,
    },
    /* Before packet filtering, change destination */
    {
        .hook        = iptable_nat_ipv4_local_fn,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_OUT,
        .priority    = NF_IP_PRI_NAT_DST,
    },
    /* After packet filtering, change source */
    {
        .hook        = iptable_nat_ipv4_fn,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_IN,
        .priority    = NF_IP_PRI_NAT_SRC,
    },
};

iptable_nat_init
    nf_register_hooks

3、l3、l4 conntrack注册
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c

static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
    {
        .hook        = ipv4_conntrack_in,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_PRE_ROUTING,
        .priority    = NF_IP_PRI_CONNTRACK,
    },
    {
        .hook        = ipv4_conntrack_local,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_OUT,
        .priority    = NF_IP_PRI_CONNTRACK,
    },
    {
        .hook        = ipv4_helper,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_POST_ROUTING,
        .priority    = NF_IP_PRI_CONNTRACK_HELPER,
    },
    {
        .hook        = ipv4_confirm,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_POST_ROUTING,
        .priority    = NF_IP_PRI_CONNTRACK_CONFIRM,
    },
    {
        .hook        = ipv4_helper,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_IN,
        .priority    = NF_IP_PRI_CONNTRACK_HELPER,
    },
    {
        .hook        = ipv4_confirm,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_IN,
        .priority    = NF_IP_PRI_CONNTRACK_CONFIRM,
    },
};

nf_conntrack_l3proto_ipv4_init
    nf_register_hooks (l3 is registered handler conntrack)
    nf_ct_l4proto_register (registered handler conntrack L4)

4, add rules:
compat_do_ipt_set_ctl    
    compat_do_replace
        translate_compat_table
            translate_table
                find_check_entry (find the corresponding target snat by name and provided to the T-> u.kernel.target = target)
                    xt_request_find_target
                        xt_find_target

5, filter rules

Examples transmission: 172.20.21.201 ----> 114.114.114.114 (snat external network IP: 175.43.23.56)
ip_local_out
    NF_HOOK (NFPROTO_IPV4, NF_INET_LOCAL_OUT, SK, SKB, NULL, skb_dst (SKB) -> dev, dst_output_sk)
        ipv4_conntrack_local
            nf_conntrack_in
                resolve_normal_ct
                    nf_ct_get_tuple (Get tuple according skb header information)
                    hash_conntrack_raw (find the corresponding according tuple the hash)
                    __nf_conntrack_find_get (determined whether the tuple exists)
                        init_conntrack (it does not exist according to the tuple newly ct information provided reply direction tuple
                                        tuple [Origin] = {src_ip = 172.20.20.201, dst_ip = 114.114.114.114}
                                        tuple [Reply] = {src_ip = 114.114.114.114, dst_ip} = 172.20.20.201)
                        nf_ct_add_to_unconfirmed_list (ct hung on the chain not confirm)
                l4proto-> Packet (tcp state is determined according to a state machine tcp_conntracks legitimacy tcp)   
        
    NF_HOOK (NFPROTO_IPV4 , NF_INET_POST_ROUTING, SK, SKB, NULL, skb_dst (SKB) -> dev, dst_output_sk)
        iptable_nat_ipv4_in
            nf_nat_ipv4_in
                nf_nat_ipv4_fn
                    iptable_nat_do_chain
                        ipt_do_table (rule acquired from net-> ipv4.nat_table table, execution target)
                            xt_snat_target_v1
                                nf_nat_setup_info (the tuple reply direction of ct the object of the target value ip ip modified to set
                                                  tuple [Origin] = {src_ip = 172.20.20.201, dst_ip = 114.114.114.114}
                                                  tuple [reply] = {src_ip = 114.114.114.114, dst_ip} = 175.43.23.56)
                    nf_nat_packet (IP reply information according to a direction ct, modifications skb ip message packet source)
                        1, according to the current hooknum NF_INET_POST_ROUTING, nat type determination NF_NAT_MANIP_SRC;
                        2, according to the current direction is dir origin, taken tuple information from the reply in the other direction, and the source, the sink ip Alternatively, to obtain = {src_ip = 175.43.23.56 tmp_tuple, dst_ip = 114.114.114.114};
                        . 3, l3proto-> manip_pkt modified message packet information
                            1), acquiring header information from SKB ip;
                            2), because the current is SNAT, the source ip ip head Lane modify tmp_tuple source ip, ip modify the header and synchronization information csum;
            
        ipv4_confirm
            nf_conntrack_confirm (confirm whether or not the connection is determined through)
                __nf_conntrack_confirm
                    __nf_conntrack_hash_insert (tuple reply the origin and direction are
                                                linked to the net-> ct.hash)

Back to ACK:
the ip_rcv
    NF_HOOK (NFPROTO_IPV4, NF_INET_PRE_ROUTING, NULL, skb, dev, NULL, ip_rcv_finish)
        ipv4_conntrack_in
            resolve_normal_ct    
                nf_ct_get_tuple (tuple information acquiring the skb)
                __nf_conntrack_find_get (> ct ct.hash obtain information from the net- then skb-> nfct = & ct-> ct_general disposed in the skb)
                l4proto-> Packet (legality status determination)
                
        iptable_nat_ipv4_in
            nf_nat_ipv4_in
                nf_nat_ipv4_fn
                    nf_nat_packet (hooknum determined according to the current nat type NF_NAT_MANIP_DST, from ct-> tuplehash origin acquired direction information tuple)
                        1, according to the current hooknum is NF_INET_PRE_ROUTING, nat type determination NF_NAT_MANIP_DST;
                        2, according to the current direction is dir Reply, taken tuple information from another in the direction of origin, and the source, the sink ip Alternatively, to obtain = {src_ip = 114.114.114.114 tmp_tuple, dst_ip = 172.20.20.201};
                        . 3, l3proto- > manip_pkt modified message packet information
                            1), ip access header information from skb;
                            2), because the current is DNAT, the modified object ip ip head is tmp_tuple in the object ip, and concurrent modification ip header csum information;
                        
            skb_dst_drop (the skb -> _ skb_refdst blanking)
            ip_rcv_finish
                ip_route_input_noref (Analyzing current skb -> _ skb_refdst is empty, according to the modified information skb reset routing information)
                    ip_route_input_slow
                        . 1, if the local receiver is provided input function rth-> dst.input = ip_local_deliver;
                        2, if you need to transfer
                            ip_mkroute_input
                                __mkroute_input(rth->dst.input = ip_forward)

Published 25 original articles · won praise 7 · views 50000 +

Guess you like

Origin blog.csdn.net/zgy666/article/details/104239245