打印TCP数据包 [英] Print TCP Packet Data
问题描述
在TCP通信,当数据包正在从以太网传输到网络(IP)层,我想打印在数据包中的数据present?
我的工作在Linux上。
我得到了一些信息,它可以与Linux内核code即在Linux中的NAT防火墙code的帮助下完成。但是,在我会得到内核源码code?如果这些编码正在做?
如何打印从TCP数据包的数据
下面是一个不正是你所需要的一个例子:钩子收到的TCP数据包,并打印其有效载荷。如果您想打印从收到的报文的一些其他信息(如二进制数据),你只需要修改了一下这条评论下部分:
/ * -----打印从接收TCP数据包的全部所需信息------ * /
如果您需要跟踪的发送的数据包,而不是的接收的那些,你可以替换此行:
nfho.hooknum = NF_INET_ pre_ROUTING;
这一个:
nfho.hooknum = NF_INET_POST_ROUTING;
保存下一个文件,并发出制作
命令来构建内核模块。然后做须藤insmod的print_tcp.ko
加载它。之后,你将能够看到使用的dmesg
命令嗅了嗅信息。如果你想卸载你的模块,运行须藤rmmod的print_tcp
命令。
print_tcp.c
的#include< Linux的/ - module.h中GT;
#包括LT&; Linux的/ netfilter.h中>
#包括LT&; Linux的/ netfilter_ipv4.h>
#包括LT&; Linux的/ ip.h>
#包括LT&; Linux的/ tcp.h中>#定义PTCP_WATCH_PORT 80 / * HTTP端口* /静态结构nf_hook_ops nfho;静态unsigned int类型ptcp_hook_func(常量的struct nf_hook_ops * OPS,
结构的sk_buff * SKB,
常量结构的net_device *中,
常量结构的net_device *出来,
INT(* okfn)(结构的sk_buff *))
{
结构iphdr * IPH; / * IPv4报头* /
结构tcphdr * TCPH; / * TCP报头* /
U16运动,DPORT; / *源和目的端口* /
U32 SADDR,DADDR; / *源和目的地址* /
无符号字符* USER_DATA; / * TCP数据开始指针* /
无符号字符*尾; / * TCP数据结束指针* /
无符号字符*它; / * TCP数据迭代器* / / *网络数据包是空的,好像发生了一些问题。跳过它 */
如果(!SKB)
返回NF_ACCEPT; IPH = ip_hdr(SKB); / *获取IP报头* / / *跳过,如果它不是TCP包* /
如果(iph->!PROTOCOL = IPPROTO_TCP)
返回NF_ACCEPT; TCPH = tcp_hdr(SKB); / *得到TCP报头* / / *转换网络字节序到主机字节序* /
SADDR = ntohl(iph-> SADDR);
DADDR = ntohl(iph-> DADDR);
运动= ntohs和(tcph->源);
DPORT = ntohs和(tcph-> DEST); / *观看的兴趣*的唯一港口/
如果(运动!= PTCP_WATCH_PORT)
返回NF_ACCEPT; / *计算指针开始和TCP数据包结束* /
USER_DATA =(无符号字符*)((无符号字符*)TCPH +(tcph->脱下* 4));
尾= skb_tail_pointer(SKB); / * -----从接收TCP数据包打印的所有需要的信息------ * / / *只显示HTTP数据包* /
如果(USER_DATA [0]!='H'|| USER_DATA [1]!='T'|| USER_DATA [2]!='T'||
的user_data [3]!='P'){
返回NF_ACCEPT;
} / *打印包路由* /
pr_debug(print_tcp:%pI4h数:%d - >%pI4h数:%d \\ n,&安培; SADDR,体育,
&安培; DADDR,DPORT); / *打印TCP数据包(有效载荷)* /
pr_debug(print_tcp:数据:\\ n);
对于(IT = USER_DATA;!它=尾; ++吧){
字符C = *(字符*)它; 如果(C =='\\ 0')
打破; printk的(%C,C);
}
printk的(\\ n \\ n); 返回NF_ACCEPT;
}静态INT __init ptcp_init(无效)
{
中期业绩; nfho.hook =(nf_hookfn *)ptcp_hook_func; / *钩子函数* /
nfho.hooknum = NF_INET_ pre_ROUTING; / *接收的数据包* /
nfho.pf = PF_INET; / * *的IPv4 /
nfho.priority = NF_IP_PRI_FIRST; / *最大钩优先* / RES = nf_register_hook(安培; nfho);
如果(RES℃,){
pr_err(print_tcp:错误nf_register_hook()\\ n);
返回水库;
} pr_debug(print_tcp:装\\ n);
返回0;
}静态无效__exit ptcp_exit(无效)
{
nf_unregister_hook(安培; nfho);
pr_debug(print_tcp:卸载\\ n);
}宏module_init(ptcp_init);
宏module_exit(ptcp_exit);MODULE_AUTHOR(萨姆Protsenko);
MODULE_DESCRIPTION(模块打印TCP数据包);
MODULE_LICENSE(GPL);
的Makefile
IFEQ($(KERNELRELEASE))KERNELDIR?= / lib / modules目录/ $(壳使用uname -r)/建模块:
$(MAKE)-C $(KERNELDIR)M = $(PWD)C = 1模块清洁:
$(MAKE)-C $(KERNELDIR)M = $(PWD)C = 1干净.PHONY:模块干净其他MODULE = print_tcp.o
CFLAGS _ $(MODULE):= -DDEBUG
OBJ-M:= $(MODULE)万一
说明
我建议你读这本书:[4]。特别是你有兴趣在接下来的章节:
- 第11章第4层协议
- TCP(传输控制协议)
- 从网络层(L3)与TCP接收数据包
- 发送数据包使用TCP
- TCP(传输控制协议)
- 第九章:Netfilter的
- Netfilter的钩子
如何获取Linux内核源$ C $ C
您可以使用的方式来获取内核源码code你preFER:
-
从你的发行版的内核源代码。例如。在Debian中你可以只安装
Linux的源代码
包(来源将被安装到/ usr / src目录
)。对于Ubuntu的看到这些说明。
从 kernel.org (更具体的
香草内核://混帐.kernel.org / CGIT / Linux的/内核/的git /托沃兹/ linux.git相对=nofollow>内核/的git /托沃兹/ linux.git
),使用的 Git的。例如。如果你需要k3.13,这是可以做到的方式旁边: $混帐混帐克隆://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ CD的Linux /
$ git的结帐v3.13
详细内容:
[1] 如何从sk_buff的
[2] 网络流量在Linux中控制核心
[5] <一个href=\"http://stackoverflow.com/questions/12073963/how-to-access-data-payload-from-tcphdr-sk-buff-struct-on-debian-64-bits\">How访问数据/从tcphdr
有效载荷更新
在这里钩捕获数据包这个例子吗?换句话说,就是它在TCP协议栈,这样我就不需要采取包丢失,重新排序,等照顾?
块引用>Netfilter的钩子在
ip_rcv()称为
函数(的这里),所以你基本上是在IPv4的层工作(这是在OSI网络层)。所以我相信丢包处理,包重组等为不可以在netfilter的钩子尚未处理。见下链接,见解:
- Netfilter的数据包流
- 在Linux的控制流网络
- 网络,通过内核(图)数据流
如果要在传输层的钩包(TCP) - 网络过滤不足以用于此任务,因为它的工作只在网络层(IPv4)的
In TCP Communication, when the packet is being transferred from ethernet to network(IP) layer, I want to print the data present in that packet?
I am working on linux.
I got some information that it can be done with the help of linux kernel code i.e in linux NAT Firewall code. But where I will get kernel source code? Where these coding is being done?
解决方案How to print data from TCP packets
Below is an example which does exactly what you need: hook received TCP packets and print their payloads. If you want to print some other information from received packet (like binary data), you just need to modify a bit the section under this comment:
/* ----- Print all needed information from received TCP packet ------ */
If you need to trace transmitted packets instead of received ones, you can replace this line:
nfho.hooknum = NF_INET_PRE_ROUTING;
with this one:
nfho.hooknum = NF_INET_POST_ROUTING;
Save next files and issue
make
command to build kernel module. Then dosudo insmod print_tcp.ko
to load it. After that you will be able to see sniffed information usingdmesg
command. If you want to unload your module, runsudo rmmod print_tcp
command.print_tcp.c:
#include <linux/module.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/ip.h> #include <linux/tcp.h> #define PTCP_WATCH_PORT 80 /* HTTP port */ static struct nf_hook_ops nfho; static unsigned int ptcp_hook_func(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct iphdr *iph; /* IPv4 header */ struct tcphdr *tcph; /* TCP header */ u16 sport, dport; /* Source and destination ports */ u32 saddr, daddr; /* Source and destination addresses */ unsigned char *user_data; /* TCP data begin pointer */ unsigned char *tail; /* TCP data end pointer */ unsigned char *it; /* TCP data iterator */ /* Network packet is empty, seems like some problem occurred. Skip it */ if (!skb) return NF_ACCEPT; iph = ip_hdr(skb); /* get IP header */ /* Skip if it's not TCP packet */ if (iph->protocol != IPPROTO_TCP) return NF_ACCEPT; tcph = tcp_hdr(skb); /* get TCP header */ /* Convert network endianness to host endiannes */ saddr = ntohl(iph->saddr); daddr = ntohl(iph->daddr); sport = ntohs(tcph->source); dport = ntohs(tcph->dest); /* Watch only port of interest */ if (sport != PTCP_WATCH_PORT) return NF_ACCEPT; /* Calculate pointers for begin and end of TCP packet data */ user_data = (unsigned char *)((unsigned char *)tcph + (tcph->doff * 4)); tail = skb_tail_pointer(skb); /* ----- Print all needed information from received TCP packet ------ */ /* Show only HTTP packets */ if (user_data[0] != 'H' || user_data[1] != 'T' || user_data[2] != 'T' || user_data[3] != 'P') { return NF_ACCEPT; } /* Print packet route */ pr_debug("print_tcp: %pI4h:%d -> %pI4h:%d\n", &saddr, sport, &daddr, dport); /* Print TCP packet data (payload) */ pr_debug("print_tcp: data:\n"); for (it = user_data; it != tail; ++it) { char c = *(char *)it; if (c == '\0') break; printk("%c", c); } printk("\n\n"); return NF_ACCEPT; } static int __init ptcp_init(void) { int res; nfho.hook = (nf_hookfn *)ptcp_hook_func; /* hook function */ nfho.hooknum = NF_INET_PRE_ROUTING; /* received packets */ nfho.pf = PF_INET; /* IPv4 */ nfho.priority = NF_IP_PRI_FIRST; /* max hook priority */ res = nf_register_hook(&nfho); if (res < 0) { pr_err("print_tcp: error in nf_register_hook()\n"); return res; } pr_debug("print_tcp: loaded\n"); return 0; } static void __exit ptcp_exit(void) { nf_unregister_hook(&nfho); pr_debug("print_tcp: unloaded\n"); } module_init(ptcp_init); module_exit(ptcp_exit); MODULE_AUTHOR("Sam Protsenko"); MODULE_DESCRIPTION("Module for printing TCP packet data"); MODULE_LICENSE("GPL");
Makefile:
ifeq ($(KERNELRELEASE),) KERNELDIR ?= /lib/modules/$(shell uname -r)/build module: $(MAKE) -C $(KERNELDIR) M=$(PWD) C=1 modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) C=1 clean .PHONY: module clean else MODULE = print_tcp.o CFLAGS_$(MODULE) := -DDEBUG obj-m := $(MODULE) endif
Explanation
I would recommend you to read this book: [4]. Particularly you are interested in next chapters:
- chapter 11: Layer 4 Protocols
- TCP (Transmission Control Protocol)
- Receiving Packets from the Network Layer (L3) with TCP
- Sending Packets with TCP
- chapter 9: Netfilter
- Netfilter Hooks
How to obtain Linux kernel source code
You can obtain kernel source code using one of ways you prefer:
Vanilla kernel from kernel.org (more specifically from kernel/git/torvalds/linux.git), using Git. E.g. if you need k3.13, it can be done next way:
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $ cd linux/ $ git checkout v3.13
Kernel sources from your distro. E.g. in Debian you can just install
linux-source
package (sources will be installed to/usr/src
). For Ubuntu see these instructions.
Details:
[1] How to get TCP header from sk_buff
[2] Network flow control in Linux kernel
[3] Writing Loadable Kernel Modules using netfilter hooks
[4] "Linux Kernel Networking: Implementation and Theory" by Rami Rosen
[5] How to access data/payload from tcphdr
UPDATE
where the hook captures packets for this example? In other words, is it upon TCP stack so that I don't need to take care of packet losing, reordering, etc.?
Netfilter hook is called in
ip_rcv()
function (here), so you are basically working in IPv4 layer (which is Network layer in OSI). So I believe packet loss handling, packet reordering etc. is not handled yet in that netfilter hook.See next links for insights:
If you want a hook packets upon Transport layer (TCP) -- netfilter is not sufficient for this task, as it works exclusively in Network layer (IPv4).
这篇关于打印TCP数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!