Netfilter provides an abstract and universal framework. The implementation of a sub-function defined by this framework is the packet filtering subsystem. The Netfilter framework consists of the following five parts:
1. define a set of hook functions for each network protocol (IPv4, IPv6, and so on) (five hook functions are defined for IPv4). These hook functions are called at several key points when the datagram flows through the protocol stack. In these vertices, the protocol stack uses the datagram and hook function labels as parameters to call the netfilter framework.
2. any module of the kernel can register one or more hooks of each Protocol to implement mounting. When a data packet is transmitted to the netfilter framework, whether there are any modules in the inner nuclear energy detection that have registered the protocol and hook functions. If the module is registered, call the callback function used for registration of the module, so that these modules have the opportunity to check (and may modify it) this packet, discard the packet, and instruct netfilter to pass the packet into the queue of the user space.
3. The queued data packets are passed to the user space for asynchronous processing. A user process can check the data packet, modify the data packet, and even reinject the data packet into the kernel through the same hook function that leaves the kernel.
4. Check all ip data packets to be discarded on the ip layer before they are discarded. For example, allow the module to check the ip-spoofed package (discarded by the route ).
5. The location of the five HOOK points on the IP layer is as follows:
1. NF_IP_PRE_ROUTING: the packet that has just entered the network layer passes this point (the version number, verification, and other tests have just been completed), and the source address is converted to this point; IP_rcv is called in ip_input.c.
2. NF_IP_LOCAL_IN: This checkpoint is sent to the local machine after route query. The INPUT package is filtered at this point. It is called in ip_local_deliver.
3. NF_IP_FORWARD: indicates the packet to be forwarded. The FORWORD packet is filtered at this point;
4. NF_IP_POST_ROUTING;
5. NF_IP_LOCAL_OUT: the packet sent by the local process uses this detection point, and the OUTPUT packet is filtered at this point.
These points have been defined in the kernel. The kernel module can register for processing on these HOOK points and can be specified using the nf_register_hook function. When the datagram passes through these hook functions, the module can modify the datagram and return the following value to netfilter:
NF_ACCEPT continues NORMAL Data Transmission
NF_DROP discards the datagram and no longer transmits it.
The NF_STOLEN module takes over the datagram. Do not continue to transmit the datagram.
NF_QUEUE queues the data packet (usually used to process the process that sends the data packet to the user space)
NF_REPEAT calls the hook function again.
A Netfilter-based datagram selection system called iptables is applied in the Linux2.4 kernel. In fact, it is a successor tool of ipchains, but it has higher scalability. The kernel module can register a new rule table and require that the datagram flow through the specified rule table. This type of datagram selection is used to implement datagram filtering (filter table), Network Address Translation (Nat table), and datagram processing (mangle table ). The three datagram processing functions provided by the Linux kernel are based on the netfilter hook function and IP table. They are independent modules and mutually independent. They are all perfectly integrated into the framework provided by Netfileter.
Package filtering
The filter table does not modify the datagram, but only filters the datagram. Iptables is smaller and faster than ipchains. It uses the hook functions NF_IP_LOCAL_IN, NF_IP_FORWARD, and NF_IP_LOCAL_OUT to access the netfilter framework. Therefore, it is reported that there is only one place to filter any number. This is a huge improvement compared to ipchains, because a forwarded datagram in ipchains traverses three chains.
NAT
The NAT table listens to three Netfilter hook functions: NF_IP_PRE_ROUTING, NF_IP_POST_ROUTING, and NF_IP_LOCAL_OUT. NF_IP_PRE_ROUTING converts the source address of the data packet to be forwarded, while NF_IP_POST_ROUTING converts the destination address of the data packet to be forwarded. The conversion of the destination address of the local datagram is implemented by NF_IP_LOCAL_OUT. The NAT table is different from the filter table, because only the first newly connected datagram will traverse the table, and the subsequent datagram will perform the same Conversion Based on the result of the first datagram. NAT tables are used in the source NAT, destination NAT, disguise (which is a special case of source NAT), and transparent proxy (which is a special case of destination NAT ).
Packet mangling)
The mangle table is registered in the NF_IP_PRE_ROUTING and NF_IP_LOCAL_OUT hooks. Using the mangle table, you can modify the datagram or attach some out-of-band data to the datagram. Currently, the mangle table supports modifying the TOS bit and setting the nfmard field of skb.
Source code analysis
If we want to add our own code, we need to use the nf_register_hook function. Its prototype is:
Int nf_register_hook (struct nf_hook_ops * reg)
Struct nf_hook_ops
{
Struct list_head list;
/* User fills in from here down .*/
Nf_hookfn * hook;
Int pf;
Int hooknum;
/* Hooks are ordered in ascending priority .*/
Int priority;
};
Our job is to generate an instance of the struct nf_hook_ops structure and HOOK it with nf_register_hook. Among them, we always initialize the list items as {NULL, NULL}. Since it generally works at the IP layer, pf is always PF_INET; hooknum is the HOOK point we choose; a hook point may have multiple processing functions. Whoever goes first depends on the priority, that is, the priority specified by priority. Netfilter_00004.h specifies the priority of the built-in processing function with an enumeration type:
Enum nf_ip_hook_priorities {
NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_CONNTRACK =-200,
NF_IP_PRI_MANGLE =-150,
NF_IP_PRI_NAT_DST =-100,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_LAST = INT_MAX,
};
Hook is the processing function provided, that is, our main work. Its prototype is:
Unsigned int nf_hookfn (unsigned int hooknum,
Struct sk_buff ** skb,
Const struct net_device * in,
Const struct net_device * out,
Int (* okfn) (struct sk_buff *));
The five parameters will be passed in by the NFHOOK macro.
Nf_register_hook finds the corresponding location in nf_hooks based on the protocol cluster type and priority registered in reg and inserts it into this table. Struct list_head nf_hooks [NPROTO] [NF_MAX_HOOKS] is initially an empty table when netfilter is initialized (netfilter_init/netfilter. c, called during sock_init.
For example, when iptable is initialized (init/iptable_filter.c), it calls nf_register_hook to register its hook function.
Static struct nf_hook_ops ipt_ops []
={{ NULL, NULL}, ipt_hook, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_FILTER },
{NULL, NULL}, ipt_hook, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER },
{NULL, NULL}, ipt_local_out_hook, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_FILTER}
};
Mangle registers its own hook function in init/iptable_mangle.c.
Static struct nf_hook_ops ipt_ops []
={{ NULL, NULL}, ipt_hook, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_MANGLE },
{NULL, NULL}, ipt_local_out_hook, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_MANGLE}
};
NAT registers its own hook function in init/ip_nat_standalone.c.
/* Change the destination address before filtering the package */
Static struct nf_hook_ops ip_nat_in_ops