类似于netfilter的内核模块,用于获取源地址和目标地址 [英] netfilter-like kernel module to get source and destination address

查看:152
本文介绍了类似于netfilter的内核模块,用于获取源地址和目标地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了本指南编写一个内核模块以进行简单的网络过滤.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆