打印TCP数据包 [英] Print TCP Packet Data

查看:683
本文介绍了打印TCP数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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



  • 第九章:Netfilter的

    • Netfilter的钩子


如何获取Linux内核源$ C ​​$ C

您可以使用的方式来获取内核源码code你preFER:


    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. 从你的发行版的内核源代码。例如。在Debian中你可以只安装 Linux的源代码包(来源将被安装到 / usr / src目录)。对于Ubuntu的看到这些说明



详细内容:

[1] 如何从sk_buff的

[2] 网络流量在Linux中控制核心

[3] 写作加载内核模块使用的netfilter钩子

[4] 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的钩子尚未处理。

见下链接,见解:

如果要在传输层的钩包(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 do sudo insmod print_tcp.ko to load it. After that you will be able to see sniffed information using dmesg command. If you want to unload your module, run sudo 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:

  1. 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
    

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

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