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)