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

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

问题描述

在 TCP 通信中,当数据包从以太网传输到网络 (IP) 层时,我想打印该数据包中存在的数据?

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?

我在 linux 上工作.

I am working on linux.

我得到了一些信息,它可以在 linux 内核代码的帮助下完成,即在 linux NAT 防火墙代码中.但是我从哪里得到内核源代码呢?这些编码在哪里完成?

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?

推荐答案

如何从 TCP 数据包中打印数据

下面是一个完全符合您需要的示例:挂钩接收到的 TCP 数据包并打印其有效负载.如果您想从接收到的数据包中打印一些其他信息(如二进制数据),您只需要稍微修改此注释下的部分:

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:

/* ----- 从接收到的 TCP 数据包中打印所有需要的信息 ------ */

如果您需要跟踪传输的数据包而不是接收的数据包,您可以替换此行:

If you need to trace transmitted packets instead of received ones, you can replace this line:

nfho.hooknum = NF_INET_PRE_ROUTING;

有了这个:

nfho.hooknum = NF_INET_POST_ROUTING;

保存下一个文件并发出make命令来构建内核模块.然后执行 sudo insmod print_tcp.ko 加载它.之后,您将能够使用 dmesg 命令查看嗅探到的信息.如果要卸载模块,请运行 sudo rmmod print_tcp 命令.

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
", &saddr, sport,
                              &daddr, dport);

    /* Print TCP packet data (payload) */
    pr_debug("print_tcp: data:
");
    for (it = user_data; it != tail; ++it) {
        char c = *(char *)it;

        if (c == '')
            break;

        printk("%c", c);
    }
    printk("

");

    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()
");
        return res;
    }

    pr_debug("print_tcp: loaded
");
    return 0;
}

static void __exit ptcp_exit(void)
{
    nf_unregister_hook(&nfho);
    pr_debug("print_tcp: unloaded
");
}

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

说明

我建议您阅读这本书:[4].特别是您对下一章感兴趣:

Explanation

I would recommend you to read this book: [4]. Particularly you are interested in next chapters:

  • 第 11 章:第 4 层协议
    • TCP(传输控制协议)
      • 使用 TCP 从网络层 (L3) 接收数据包
      • 使用 TCP 发送数据包
      • Netfilter 钩子

      您可以使用您喜欢的一种方式获取内核源代码:

      You can obtain kernel source code using one of ways you prefer:

      1. 来自 kernel.org 的香草内核(更具体地说,来自 kernel/git/torvalds/linux.git),使用 Git.例如.如果你需要k3.13,可以通过以下方式完成:

      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
      

    • 来自发行版的内核源代码.例如.在 Debian 中,您只需安装 linux-source 包(源代码将安装到 /usr/src).对于 Ubuntu,请参阅这些说明.

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

      <小时>

      详情:

      [1] 如何从 sk_buff 获取 TCP 标头

      [2] Linux 内核中的网络流量控制

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

      [4] "Linux 内核网络:实现和理论"作者:拉米·罗森

      [5] 如何从 tcphdr 访问数据/有效负载

      钩子在哪里捕获这个例子的数据包?换句话说,它是否在 TCP 堆栈上,以便我不需要处理丢包、重新排序等问题?

      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 钩子在 ip_rcv() 函数中被调用(此处),因此您基本上是在 IPv4 层(OSI 中的网络层)中工作.所以我相信在那个 netfilter 钩子中还没有处理丢包处理、数据包重新排序等.

      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:

      如果您希望在传输层 (TCP) 上挂钩数据包 -- netfilter 不足以完成此任务,因为它仅在网络层 (IPv4) 中工作.

      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天全站免登陆