类似于netfilter的内核模块,用于获取源地址和目标地址 [英] netfilter-like kernel module to get source and destination address
问题描述
我阅读了本指南编写一个内核模块以进行简单的网络过滤.
I read this guide to write a kernel module to do simple network filtering.
首先,我不知道下面的文字意味着什么,(按传输层)入站和出站数据包之间有什么区别?
First, I have no idea of what below text this means, and what's the difference between inbound and outbound data packet(by transportation layer)?
当数据包从电线进入时,它从物理层传输,数据 链路层,网络层向上,因此它可能无法通过 netfilter中定义的用于skb_transport_header的功能.
When a packet goes in from wire, it travels from physical layer, data link layer, network layer upwards, therefore it might not go through the functions defined in netfilter for skb_transport_header to work.
第二,我讨厌魔术数字,我想用Linux内核实用程序中的任何函数替换20
(典型IP头的长度)(
Second, I hate magic numbers, and I want to replace the 20
(the length of typical IP header) with any function from the linux kernel's utilities(source file).
任何帮助将不胜感激.
推荐答案
本文现在有点过时了.您不理解的文本仅适用于3.11以下的内核版本.
This article is a little outdated now. Text that you don't understand is only applicable to kernel versions below 3.11.
如果您确定自己的代码仅用于> = 3.11的内核,则可以对 input 和 output 数据包使用下一个代码:
If you are sure that your code will only be used with kernels >= 3.11, you can use next code for both input and output packets:
udp_header = (struct udphdr *)skb_transport_header(skb);
或更优雅:
udp_header = udp_hdr(skb);
在这种情况下,在sk_buffer
中正确设置了.transport_header
字段,因此它指向实际的传输层标头(UDP/TCP).因此,您可以使用如下代码:
In this case .transport_header
field set up correctly in sk_buffer
, so it points to actual transport layer header (UDP/TCP). So you can use code like this:
udp_header = (struct udphdr *)skb_transport_header(skb);
或更美观(但实际上是一样的):
or better looking (but actually the same):
udp_header = udp_hdr(skb);
传入数据包(NF_INET_PRE_ROUTING
)
这是棘手的部分.
Incoming packets (NF_INET_PRE_ROUTING
)
This is the tricky part.
在这种情况下,.transport_header
字段未设置为sk_buffer
结构中的实际传输层标头(UDP或TCP)(在netfilter钩子函数中获得).相反,.transport_header
指向IP标头(即网络层标头).
In this case the .transport_header
field is not set to the actual transport layer header (UDP or TCP) in sk_buffer
structure (that you get in your netfilter hook function). Instead, .transport_header
points to IP header (which is network layer header).
因此,您需要自己计算运输标头的地址.为此,您需要跳过IP标头(即,将IP标头长度添加到您的.transport_header
地址).这就是为什么您可以在文章中看到下一个代码的原因:
So you need to calculate address of transport header by your own. To do so you need to skip IP header (i.e. add IP header length to your .transport_header
address). That's why you can see next code in the article:
udp_header = (struct udphdr *)(skb_transport_header(skb) + 20);
所以20
这只是IP标头的长度.
So 20
here is just the length of IP header.
可以通过以下方式更优雅:
It can be done more elegant in this way:
struct iphdr *iph;
struct udphdr *udph;
iph = ip_hdr(skb);
/* If transport header is not set for this kernel version */
if (skb_transport_header(skb) == (unsigned char *)iph)
udph = (unsigned char *)iph + (iph->ihl * 4); /* skip IP header */
else
udph = udp_hdr(skb);
在此代码中,我们使用实际的IP标头大小(以字节为单位的iph->ihl * 4
)而不是幻数20
.
In this code we use an actual IP header size (which is iph->ihl * 4
, in bytes) instead of magic number 20
.
文章中的另一个魔术数字是下一个代码中的17
:
Another magic number in the article is 17
in next code:
if (ip_header->protocol == 17) {
在此代码中,您应该使用IPPROTO_UDP
而不是17
:
In this code you should use IPPROTO_UDP
instead of 17
:
#include <linux/udp.h>
if (ip_header->protocol == IPPROTO_UDP) {
Netfilter输入/输出数据包说明
如果需要有关netfilter中传入和传出数据包之间差异的参考,请参见下图.
Netfilter input/output packets explanation
If you need some reference about difference between incoming and outgoing packets in netfilter, see the picture below.
详细信息:
[1]:来自GitHub的一些有用代码
[2]:"Linux内核网络:实现和理论",拉米·罗森(Rami Rosen)
[3]:此答案可能也有用
这篇关于类似于netfilter的内核模块,用于获取源地址和目标地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!