Since several articles in the Smart Router series blog have used NetFilter to implement some of the features in the router, write this blog to illustrate what I think when I use the NetFilter framework programming.
I try to describe netfilter programming essentials in concise language. 5 Hook points
respectively: prerouting, postouting, INPUT, FORWARD, OUTPUT, the following gives a very concise frame diagram, presumably we are familiar with
Note: I marked the position of Dnat and snat with a red font on the 5 hook frame of netfilter, why should I mark it. Because they are important and special, they affect the content of the TCP/IP messages that we intercept on the hook point. Say it later.
As for the 5 points of the role of the hook I do not have to say (in this save space), because the general introduction of NetFilter's article will give an explanation, search search good. Source Code Sign up/logout hook
Nerfilter Hook Registration/cancellation needs to include Netfilter.h header file first
int Nf_register_hook (strcut nf_hook_ops *reg);
void Nf_unregister_hook (struct nf_hook_ops *reg);
General Linux kernel module registration and logoff code is this form of structure Nf_hook_ops
This structure is included in the registration and logoff functions above, as follows:
struct Nf_hook_ops
{
struct list_head list;//Hook list
NF_HOOKFN *hook;//hook processing function
struct module *owner;// Module owner
int pf;//Hook protocol family
int hooknum;//Hook's position value
int priority;//Hook's priority
}
Take a closer look at the form defined by this NF_HOOKFN type:
typedef unsigned int NF_HOOKFN (unsigned int hooknum,
struct Sk_buff *skb,
const struct Net_device,
const struct Net_device *out,
Int (*OKFN) (struct sk_buff *));
Processing Results
The hook function must be returned, the processing result represents the fate of the network packet, there are several:
/* Responses from hook functions. * *
#define NF_DROP 0 //Discard the packet, release the resource assigned to him
#define NF_ACCEPT 1 //Keep the packet and leave it to the next hook function
#define Nf_ Stolen 2//Forget the packet, the hook function processes the packet, no longer passes through NetFilter processing
#define NF_QUEUE 3//Inserts the packet into the user space
#define NF_REPEAT 4// Call the hook function again
#define NF_STOP 5//Stronger than nf_accept, fully accept the packet, and all subsequent hook functions do not need to process the packet
priority of hook function
The hook function that is mounted under the same hook point determines the execution order of the Mount function by priority, and the hook priority is defined in the Linux kernel as follows (source code in NETFILTER_IPV4.H):
Enum Nf_ip_hook_priorities {
Nf_ip_pri_first = int_min,
Nf_ip_pri_conntrack_defrag = -400,
nf_ip_pri_ RAW = -300,
nf_ip_pri_selinux_first = -225,
nf_ip_pri_conntrack = -200,
nf_ip_pri_mangle = -150,
NF_IP_PRI_NAT_DST = -100,
nf_ip_pri_filter = 0,
nf_ip_pri_security = x,
nf_ip_pri_nat_src = m,
Nf_ip_pri_selinux_last = Nf_ip_pri_conntrack_confirm =
Int_max,
nf_ip_pri_last = Int_max,
};
Writing kernel modules
With the above basic code to write the kernel module, the simplest example is as follows:
#include <linux/moudle> #include <linux/kernel> #include <skbuff.h>//Here omit some header files static unsigned int my
_hook (unsigned int hooknum, struct sk_buff *skb, const struct Net_device,
const struct Net_device *out, int (*OKFN) (struct sk_buff *));
{struct IPHDR *ip;
struct UDPHDR *udp;
if (!SKB) return nf_accept;
if (Skb->protocol!= htons (0x0800))//Grab IP packet (excluding ARP packet) return nf_accept IP = IP_HDR (SKB);
if (Ip->protocol!= 17)//crawl UDP packet return nfaccept; UDP = UDP_HDR (SKB);
This function, although it has, does not necessarily get the correct result, depending on the hook function mount point and priority UDP = (struct UDPHDR *) (ip+1);
if (Ntohs (udp->dest)!= 53)//filter UDP Destination port to 53 port data return nfaccept;
return nf_drop; struct Nf_hook_ops my_ops = {. List = {null, null},. Hook = My_hook,. PF = pf_inet,. Hooknum = nf_inet_ Pre_routing,. Priority = nf_ippri_first+1} static int __init m_iNit (void) {Nf_register_hook (&my_ops);}
static void __exit m_exit (void) {Nf_unregister_hook (&my_ops);}
Module_init (M_exit); Module_exit (M_exit);
All right, all hands, coherent.
The function of this program is to drop the request data of the domain name resolution. The module discards the port data for UDP packet destination port 53 in the network packet flowing through the NetFilter, and the UDP destination port is 53 port data is the DNS resolution request packet that is about to be sent to the DNS server.
I recommend that you do not understand the network packet level of children's shoes look at my "Ethernet packets" series articles. Sk_buff Structural Body
Sk_buff is the network packet structure. Well, to explain this estimate several articles are not finished, this is only a brief description and explanation
struct Sk_buff {* * Two members must to be the struct sk_buff;
struct Sk_buff *prev;
ktime_t Tstamp;
struct sock *sk;
struct Net_device *dev;
Char cb[48] __aligned (8);
unsigned long _skb_refdst;
#ifdef config_xfrm struct Sec_path *sp;
#endif unsigned int len, Data_len;
__u16 Mac_len, Hdr_len;
Union {__wsum Csum;
struct {__u16 csum_start;
__u16 Csum_offset;
};
};
__U32 priority;
Kmemcheck_bitfield_begin (FLAGS1);
__u8 local_df:1, Cloned:1, Ip_summed:2, Nohdr:1,
Nfctinfo:3;
__u8 Pkt_type:3, Fclone:2, Ipvs_property:1, Peeked:1,
Nf_trace:1;
Kmemcheck_bitfield_end (FLAGS1);
__BE16 Protocol; void (*destrUctor) (struct sk_buff *skb); #if defined (config_nf_conntrack) | |
Defined (config_nf_conntrack_module) struct nf_conntrack *nfct;
#endif #ifdef net_skbuff_nf_defrag_needed struct Sk_buff *nfct_reasm;
#endif #ifdef config_bridge_netfilter struct nf_bridge_info *nf_bridge;
#endif int skb_iif; #ifdef config_net_sched __u16 Tc_index; /* Traffic Control Index */#ifdef config_net_cls_act __u16 tc_verd;
/* Traffic Control verdict */#endif #endif __u32 Rxhash;
Kmemcheck_bitfield_begin (FLAGS2);
__u16 queue_mapping:16;
#ifdef config_ipv6_ndisc_nodetype __u8 ndisc_nodetype:2, deliver_no_wcard:1;
#else __u8 deliver_no_wcard:1;
#endif __u8 ooo_okay:1;
Kmemcheck_bitfield_end (FLAGS2);
#ifdef CONFIG_NET_DMA dma_cookie_t Dma_cookie;
#endif #ifdef Config_network_secmark __u32 Secmark; #endif Union {__U32 Mark
__u32 Dropcount;
};
__u16 Vlan_tci;
sk_buff_data_t Transport_header;
sk_buff_data_t Network_header;
sk_buff_data_t Mac_header; /* These elements must are at the end, and the ALLOC_SKB () for details.
* * sk_buff_data_t tail;
sk_buff_data_t end;
unsigned char *head, *data;
unsigned int truesize;
atomic_t users; };
| Sk_buff Main members |
meaning |
| Next |
Sk_buff the next buffer in a linked list |
| Prev |
Sk_buff the previous buffer in the list, it is obvious that the sk_buff is on a doubly linked list |
| Sk |
This article belongs to the sock structure, this value is only valid in the message sent out, the message received from the network this value is NULL |
| Tstamp |
Time stamp received by message |
| Dev |
The network device that received this message |
| Transport_header |
Transport Layer Head |
| Network_header |
Network Layer Head |
| Mac_header |
Link Layer Head |
| Cb |
Used to control the buffer. Each layer can use this pointer to place private data here. |
| Len |
Valid data length |
| Data_len |
Data length |
| Mac_len |
Connection layer head length, for Ethernet, refers to the length of MAC address, 6 |
| Hdr_len |
SKB length of the writable head |
| Csum |
Checksum (contains start and offset) |
| Csum_start |
Offset from Skb->head when the checksum is started to be computed |
| Csum_offset |
Offset starting from Csum_stat |
| Local_df |
Allow local fragmentation |
| Pkt_type |
Categories of packages |
| Priority |
Priority of Package queues |
| Truesize |
The size of the message buffer |
| Head |
Header of message buffer |
| Data |
Header pointer to data |
| Tail |
The tail pointer of the data |
| End |
The tail of the message buffer |
In view of the relationship between time and space, sk_buff data structure diagram and related operation functions are not introduced in this article, the Internet should be able to find. struct Net_device structural body
This is a mega-structure, inconvenience in this list, online an article to this explanation, detailed understanding can go to address http://blog.chinaunix.net/uid-21807675-id-1814837.html NAT
Network packets in the NetFilter through the Snat and Dnat to the network packet made changes, mainly made IP and port mapping, of course, input device Net_device also changed, these should be noted that in the writing program, in the appropriate hook point to intercept the packet is very necessary, Because there are other modules in addition to the hooks you hook up on the NetFilter hook, these hooks will have an impact on the packet, often hanging the wrong hook point can not intercept the desired data.
Okay, here's the end of this article.