netfilter filter表(三)

news/2025/1/8 17:11:13/

修改《netfilter filter表(二)》的hello_open函数,将ipt_entry的信息打印处理,代码如下:

char* get_verdict(int verdict)
{verdict = -(verdict + 1);char* p = "";switch (verdict){case NF_DROP:p = "NF_DROP";break;case NF_ACCEPT:p = "NF_ACCEPT";break;case NF_STOLEN:p = "NF_STOLEN";break;case NF_QUEUE:p = "NF_QUEUE";break;case NF_REPEAT:p = "NF_REPEAT";break;case NF_STOP:p = "NF_STOP";break;default:break;}return p;
}void print_entry_info(struct ipt_entry* ipt_entry)
{printk("  ipt_entry.target_offset = %d\n", ipt_entry->target_offset);printk("  ipt_entry.next_offset = %d\n", ipt_entry->next_offset);printk("  ipt_entry.comefrom = %d\n", ipt_entry->comefrom);printk("  ipt_entry.ip.src = %X\n", ipt_entry->ip.src);printk("  ipt_entry.ip.smsk = %X\n", ipt_entry->ip.smsk);printk("  ipt_entry.ip.dst = %X\n", ipt_entry->ip.dst);printk("  ipt_entry.ip.dmsk = %X\n", ipt_entry->ip.dmsk);printk("  ipt_entry.ip.iniface = %s\n", ipt_entry->ip.iniface);printk("  ipt_entry.ip.outiface = %s\n", ipt_entry->ip.outiface);printk("  ipt_entry.ip.proto = %d\n", ipt_entry->ip.proto);printk("  ipt_entry.ip.flags = %d\n", ipt_entry->ip.flags);printk("  ipt_entry.ip.invflags = %d\n", ipt_entry->ip.invflags);struct xt_standard_target *t = (void*)ipt_entry +  ipt_entry->target_offset;printk("    xt_standard_target.verdict = %s\n", get_verdict(t->verdict));struct xt_target *target = t->target.u.kernel.target;if (NULL != target){printk("      xt_target.name = %s\n", target->name);printk("      xt_target.revision = %d\n", target->revision);printk("      xt_target.table = %s\n", target->table);printk("      xt_target.targetsize = %d\n", target->targetsize);printk("      xt_target.usersize = %d\n", target->usersize);printk("      xt_target.hooks = %d\n", target->hooks);printk("      xt_target.proto = %d\n", target->proto);printk("      xt_target.family = %d\n", target->family);}else{printk("no target\n");}// 有matchif (offsetof(struct ipt_entry, elems) != ipt_entry->target_offset){printk("have match\n");}else{printk("no match\n");}
}static int hello_open(struct inode* inode, struct file*filep)
{... ...ipt_entry = table_base + filter_info->hook_entry[NF_INET_LOCAL_IN];ipt_entry_end = table_base + filter_info->underflow[NF_INET_LOCAL_IN];while (1){if (ipt_entry >= ipt_entry_end){break;}print_entry_info(ipt_entry);ipt_entry = (void *)ipt_entry + ipt_entry->next_offset;}return 0;
}

其中iptable配置如下:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  1.2.3.5              0.0.0.0/0           
ACCEPT     all  -- !1.2.3.4              0.0.0.0/0       

ipt_entry部分日志如下:

[ 538.451864] ipt_entry.target_offset = 112

[ 538.451865] ipt_entry.next_offset = 152

[ 538.451866] ipt_entry.comefrom = 2

[ 538.451866] ipt_entry.ip.src = 5030201

[ 538.451867] ipt_entry.ip.smsk = FFFFFFFF

[ 538.451868] ipt_entry.ip.dst = 0

[ 538.451868] ipt_entry.ip.dmsk = 0

[ 538.451869] ipt_entry.ip.iniface =

[ 538.451869] ipt_entry.ip.outiface =

[ 538.451870] ipt_entry.ip.proto = 6

[ 538.451871] ipt_entry.ip.flags = 0

[ 538.451871] ipt_entry.ip.invflags = 0

[ 538.451872] xt_standard_target.verdict = NF_DROP

[ 538.451873] xt_target.name =

[ 538.451873] xt_target.revision = 0

[ 538.451874] xt_target.table = (null)

[ 538.451874] xt_target.targetsize = 4

[ 538.451875] xt_target.usersize = 0

[ 538.451875] xt_target.hooks = 0

[ 538.451876] xt_target.proto = 0

[ 538.451877] xt_target.family = 2

[ 538.451877] no match

[ 538.451878] ipt_entry.target_offset = 112

[ 538.451878] ipt_entry.next_offset = 152

[ 538.451879] ipt_entry.comefrom = 2

[ 538.451879] ipt_entry.ip.src = 4030201

[ 538.451880] ipt_entry.ip.smsk = FFFFFFFF

[ 538.451880] ipt_entry.ip.dst = 0

[ 538.451881] ipt_entry.ip.dmsk = 0

[ 538.451882] ipt_entry.ip.iniface =

[ 538.451882] ipt_entry.ip.outiface =

[ 538.451883] ipt_entry.ip.proto = 0

[ 538.451883] ipt_entry.ip.flags = 0

[ 538.451884] ipt_entry.ip.invflags = 8

[ 538.451884] xt_standard_target.verdict = NF_ACCEPT

[ 538.451885] xt_target.name =

[ 538.451886] xt_target.revision = 0

[ 538.451886] xt_target.table = (null)

[ 538.451887] xt_target.targetsize = 4

[ 538.451887] xt_target.usersize = 0

[ 538.451888] xt_target.hooks = 0

[ 538.451888] xt_target.proto = 0

[ 538.451889] xt_target.family = 2

[ 538.451889] no match

根据上面信息,整理的关系图如下:

 一个ipt_standard代表iptable表INPUT链中的一条配置,ipt_ip配置了源地址,目的地址等信息,其定义如下:

struct ipt_ip {

源地址与目的地址

struct in_addr src, dst;

源地址与目的地址的掩码

struct in_addr smsk, dmsk;

char iniface[IFNAMSIZ], outiface[IFNAMSIZ];

unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];

协议 0 = ANY

IPPROTO_TCP 6

__u16 proto;

/* Flags word */

__u8 flags; 

取反标记

#define IPT_INV_SRCIP 0x08 对源IP区反,对于第二条配置,就是源地址不是1.2.3.4的包

__u8 invflags; 

};

ipt_ip表示的是标准匹配,如果有扩展匹配信息(结构体是:xt_match) ,保存在ipt_entry和xt_standard_target之间。本例中的两条配置,都不带扩展匹配,所以ipt_entry后面紧挨着xt_standard_target。是否包含扩展匹配信息,都可以通过ipt_entry的地址+target_offset,获取到xt_standard_target。

ipt_entry的地址+next_offset可以获取到下一个ipt_entry的地址。

ipt_standaard_target的verdict表示处理方法。对于标准的处理方法(如:DROP,ACCEPT),将其取反后再减1(即:-(__verdict) - 1),赋给ipt_standaard_target的verdict。给verdict赋值,可以参考下面的宏。

#define IPT_STANDARD_INIT(__verdict) \

{ \

.entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \

.target = XT_TARGET_INIT(XT_STANDARD_TARGET, \

sizeof(struct xt_standard_target)), \

.target.verdict = -(__verdict) - 1, \

}

最后做一个有趣的实验,将源地址为1.2.3.5的处理方法改成 NF_ACCEPT,代码如下:

void print_entry_info(struct ipt_entry* ipt_entry)
{... ...struct xt_standard_target *t = (void*)ipt_entry +  ipt_entry->target_offset;printk("    xt_standard_target.verdict = %s\n", get_verdict(t->verdict));// 新加的代码if (0x5030201 == ipt_entry->ip.src.s_addr){t->verdict = -(NF_ACCEPT) - 1;}struct xt_target *target = t->target.u.kernel.target;if (NULL != target){printk("      xt_target.name = %s\n", target->name);printk("      xt_target.revision = %d\n", target->revision);printk("      xt_target.table = %s\n", target->table);printk("      xt_target.targetsize = %d\n", target->targetsize);printk("      xt_target.usersize = %d\n", target->usersize);printk("      xt_target.hooks = %d\n", target->hooks);printk("      xt_target.proto = %d\n", target->proto);printk("      xt_target.family = %d\n", target->family);}... ...
}

 更新驱动,调用用户空间测试程序,最后用iptables查下INPUT链的配置,查询结果如下:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  1.2.3.5              0.0.0.0/0           
ACCEPT     all  -- !1.2.3.4              0.0.0.0/0 

由此可见,上述代码的改动,已经生效了。


http://www.ppmy.cn/news/52470.html

相关文章

算法基础(三):链表知识点及题型讲解

算法基础(三):链表知识点及题型讲解 1 链表定义2 Python链表常用操作2.1 创建链表2.2 添加元素2.3 访问元素2.4 搜索元素2.5 更新元素2.6 删除元素2.7 获取链表长度 3 力扣题目训练 一些算法基础知识点和leetcode题解,语言是pytho…

Windows 彻底卸载联软流氓软件(亲测可用)

文章目录 1、前言2、卸载步骤(1)打开服务,将所有Uni开头的服务都禁用,某些服务禁用后可能还是会自启,不过不影响(2)进入安全模式,电脑重启(3)重启后桌面显示了…

黑盒测试过程中【测试方法】讲解1-等价类,边界值,判定表

在黑盒测试过程中,有9种常用的方法:1.等价类划分 2.边界值分析 3.判定表法 4.正交实验法 5.流程图分析 6.因果图法 7.输入域覆盖法 8.输出域覆盖法 9.猜错法 我们一般用第1种和第2种方法最多。此处简单介绍一下这两种方法,详细介绍其…

Linux Shell 实现一键部署http+用户名密码登录

Apache 前言 Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等…

C++类与对象this指针

文章目录 前言一,类1.类的引入2.类的定义3.类的作用域4.类的访问限定符及封装封装访问限定符面试题 二,this指针1.this指针定义2.this指针的特性 前言 从此篇往后,开始了C的类和对象的篇章,嗯就说这么多 一,类 1.类的…

如何在 Java 中将文本和形状放置在图像上

将新的可视元素编码到图像文件中首先要对图像文件的正常显示方式有基本的了解。当加载图像文件以在我们的任何设备上显示时,该设备的软件必须首先解码该文件,并将解码结果存储在称为缓冲区的临时内存块中。缓冲区负责传达图像中每个像素存储的颜色信息&a…

港联证券|人民币大消息!美科技股涨嗨,微软一夜暴增超万亿!

当地时间26日,美股三大股指收盘涨跌纷歧。到收盘,道指报33301.87点,下跌0.68%;标普500指数报4055.99点,下跌0.38%;纳指报11854.35点,上涨0.47%。 榜首共和银行大跌29.75%,该股昨天大…

100种思维模型之头脑开放思维模型-53

投资界的“斯蒂夫乔布斯”,桥水基金创始人瑞达利欧(Ray Dalio)在他的畅销书《原则》中说,做到头脑极端开放是最重要的原则。 书中原话:“做到头脑极度开放。这也许是全书最重要的一条,因为本条将阐述如何克服影响大多数人实现人生…