首页 > 系统相关 >转载:使用 Linux tracepoint、perf 和 eBPF 跟踪数据包 (2017)

转载:使用 Linux tracepoint、perf 和 eBPF 跟踪数据包 (2017)

时间:2024-03-29 11:13:03浏览次数:30  
标签:perf eBPF 虚拟机 网络 网卡 网桥 内核 命名 数据包

http://arthurchiao.art/blog/trace-packet-with-tracepoint-perf-ebpf-zh/

Linux 允许在主机上用虚拟网卡(virtual interface)和网络命名空间(network namespace)构建复杂的网络。但出现故障时,排障(troubleshooting)相当痛苦。如果是 3 层路由问题,mtr 可以排上用场;但如果是更底层的问题,通常只能手动检查每个网 卡/网桥/网络命名空间/iptables 规则,用 tcpdump 抓一些包,以确定到底是什么状况。 如果不了解故障之前的网络配置,那排障时的感觉就像在走迷宫。

 

虚拟网卡:

虚拟网卡(Virtual Network Interface Card)是一种软件实现的网络接口,用于在虚拟化环境中模拟物理网络接口卡的功能。它在虚拟机和宿主机之间起到了桥接和连接的作用。

以下是虚拟网卡的一些主要作用:

  1. 网络连接:虚拟网卡提供了虚拟机与宿主机或其他虚拟机之间进行网络通信的接口。它使虚拟机能够通过网络与其他设备(如物理服务器、网络设备或其他虚拟机)进行通信。

  2. 网络隔离:每个虚拟机都可以有自己独立的虚拟网卡,使得虚拟机之间的网络流量可以相互隔离。这种隔离可以提供更高的安全性和防止不同虚拟机之间的干扰。

  3. 虚拟网络拓扑:通过虚拟网卡,可以创建复杂的虚拟网络拓扑,包括虚拟交换机、路由器和防火墙等网络设备的模拟。这允许虚拟机之间进行内部通信,并提供更灵活的网络配置选项。

  4. 网络性能优化:虚拟网卡可以针对虚拟化环境进行性能优化。它可以利用物理网卡的硬件加速功能,如SR-IOV(Single Root I/O Virtualization)或者使用虚拟化技术自身的优化机制,以提供更高的网络性能和吞吐量。

  5. 网络管理和监控:虚拟网卡可以与虚拟化管理工具集成,提供对虚拟机网络的管理和监控功能。管理员可以配置虚拟网卡的参数、监视网络流量和进行故障排除等操作。 

虚拟交换机:

网络命名空间(Network Namespace)是Linux内核提供的一种机制,用于在同一主机上创建独立的网络环境。每个网络命名空间都有自己独立的网络栈、网络接口、路由表和防火墙规则,它们之间相互隔离,就像是在同一主机上运行了多个独立的网络堆栈。

网络堆栈:常见的四层(?)

 

网桥通过学习和维护转发表来实现将一个网段的数据转发到另一个网段。当一个数据帧到达网桥时,网桥会进行以下步骤来决定如何转发该数据帧:

  1. 学习源MAC地址:网桥会检查数据帧中的源MAC地址,并将其与输入接口(即数据帧到达网桥的接口)相关联。它会将该源MAC地址和对应的输入接口记录到转发表中。

  2. 查找目标MAC地址:网桥会检查数据帧中的目标MAC地址。

  3. 查找目标MAC地址在转发表中的条目:网桥会查找转发表,看是否存在与目标MAC地址匹配的记录。

    a. 如果转发表中存在与目标MAC地址匹配的记录,网桥会获取与目标MAC地址对应的输出接口,然后将数据帧转发到该输出接口,以便达到目标网段。

    b. 如果转发表中不存在与目标MAC地址匹配的记录,网桥会将数据帧广播到所有其他接口,以便学习到目标MAC地址的位置,并将其添加到转发表中。

  4. 更新转发表:当网桥接收到新的数据帧时,它会根据源MAC地址进行学习,并更新转发表中的条目。这样,网桥可以不断更新和维护转发表,以适应网络中设备的变化。

在Linux环境下,可以使用以下工具和命令来创建和管理网络命名空间:

  1. ip命令:ip命令是一个功能强大的网络工具,可以用于创建和管理网络命名空间。以下是一些常用的ip命令选项:

    • 创建网络命名空间:ip netns add <namespace_name>
    • 删除网络命名空间:ip netns delete <namespace_name>
    • 在网络命名空间中执行命令:ip netns exec <namespace_name> <command>
  2. ip命令配合虚拟网络设备:通过创建虚拟网络设备并将其分配给网络命名空间,可以实现网络隔离。以下是一些相关命令选项:

    • 创建虚拟网络设备:ip link add <device_name> type veth peer name <peer_device_name>
    • 将设备分配给网络命名空间:ip link set <device_name> netns <namespace_name>
    • 配置网络设备的IP地址、路由等:ip addr add <ip_address>/<subnet_mask> dev <device_name>ip route add <destination_network> via <gateway> dev <device_name>
  3. nsenter命令:nsenter命令可以进入指定的网络命名空间,并在其中执行命令。以下是一个示例命令:

    • 进入网络命名空间:nsenter --net=<namespace_name> <command>
  4. 使用网络命名空间的应用程序:一些应用程序(如Docker、Kubernetes等)提供了内置的网络命名空间管理功能,可以通过它们来创建、管理和使用网络命名空间。

注意:创建和管理网络命名空间通常需要root权限或具有相应特权的用户权限。

这些工具和命令提供了创建、删除和管理网络命名空间的功能。可以使用它们来配置网络命名空间的网络接口、IP地址、路由规则和防火墙设置,以满足特定的需求和场景。

如果没有使用Docker或其他容器运行时工具,你可以手动使用Linux提供的命名空间和控制组等特性来实现容器的隔离访问。这需要更深入的了解和配置,而且相对复杂。下面是一个简化的示例,演示如何使用Linux命令行工具实现容器的隔离访问:

  1. 创建容器根文件系统:首先,创建一个目录作为容器的根文件系统,并将所需的文件和目录复制到其中,以构建容器的运行环境。例如,你可以使用debootstrap工具创建一个基本的Ubuntu根文件系统:

     
    sudo debootstrap bionic /path/to/rootfs
    
  2. 配置命名空间:使用unshare命令创建各种命名空间,实现进程、网络和文件系统的隔离。例如,创建PID命名空间和网络命名空间:

     
    sudo unshare --pid --fork --mount-proc=/path/to/rootfs/proc
    sudo unshare --net --fork --mount-proc=/path/to/rootfs/proc
    
  3. 挂载文件系统:在容器内部,使用mount命令挂载所需的文件系统。例如,挂载主机的根文件系统和其他必要的文件系统:

    awk(感觉有点问题,gpt回答的)
    sudo mount --bind / /path/to/rootfs
    sudo mount -t proc proc /path/to/rootfs/proc
    sudo mount -t sysfs sysfs /path/to/rootfs/sys
    
  4. 设置资源限制:使用cgroup工具设置容器的资源限制和分配。例如,限制容器的CPU使用和内存限制:

     
    sudo cgcreate -g cpu:/mycontainer
    sudo cgset -r cpu.cfs_quota_us=50000 /mycontainer
    sudo cgcreate -g memory:/mycontainer
    sudo cgset -r memory.limit_in_bytes=536870912 /mycontainer
    
  5. 执行容器进程:在容器的隔离环境中,执行容器的主进程。例如,使用chroot命令切换到容器的根文件系统,并启动容器中的应用程序:

     
    sudo chroot /path/to/rootfs /bin/bash

 

 

 

#破局

用 Linux 术语来说,就是转换到内核视角(the kernel point of view)。在这种视 角下,网络命名空间不再是容器(“containers”),而只是一些标签(labels)。内核、 数据包、网卡等此时都是“肉眼可见”的对象(objects)。

所以我想要的是这样一个工具,它可以直接告诉我 “嗨,我看到你的包了:它从属于这个 网络命名空间的这个网卡上发出,然后依次经过这些函数”。

 

#巨人肩膀

perf & eBPF

 

 任何在 /proc/kallsyms 导出的符号(内核函数)和 tracepoint, 都可以插入 eBPF tracing 代码。

插入:

eBPF 内核探测:如何将任意系统调用转换成事件(2016)

http://arthurchiao.art/blog/ebpf-turn-syscall-to-event-zh/

基于 eBPF 可以将任何内核函数调用转换成可带任何 数据的用户空间事件。bcc 作为一个更上层的工具使这个过程更加方便。内核探测 代码用 C 写,数据处理代码用 Python。

 

当希望一个程序能对系统变化做出反应时,通常有 2 种可能的方式:

  • 一种是程序主动去轮询,检查系统变化;
  • 另一种,如果系统支持事件通知的话,让它主动通知程序

 

使用 push 还是 pull 取决于具体的问题。通常的经验是,

  • 如果事件频率相对于事件处理时间来说比较低,那 push 模型比较合适;
  • 如果事件频率很高,就采用 pull 模型,否则系统变得不稳定。

2 内核跟踪和 eBPF 简史

直到最近,唯一的通用方式是给内核打补丁,或者使用 SystemTap。SystemTap 是一个 tracing 系统,简单来说,它提供了一种领域特定语言(DSL),代码编译成内核模块, 然后热加载到运行中的内核。但出于安全考虑,一些生产系统禁止动态模块加载, 例如我研究 eBPF 时所用的系统就不允许。

另一种方式是给内核打补丁来触发事件,可能会基于 Netlink。这种方式不太方便,内 核 hacking 有副作用,例如新引入的特性也许有毒,而且会增加维护成本

将任何可跟踪的内核函数安全地转换成事件, 很可能将成为现实。在计算机科学的表述中,“安全地”经常是指通过“某种类型的虚拟机” 来执行代码,这里也不例外。事实上,Linux 内部的这个“虚拟机”已经存 在几年了,从 1997 年的 2.1.75 版本有了,称作伯克利包过滤器(Berkeley Packet Filter),缩写 BPF。从名字就可以看出,它最开始是为 BSD 防火墙开发的。它只有两 个寄存器,只允许前向跳转,这意味着无法用它实现循环(如果非要说行也可以:如果 你知道最大的循环次数,那可以手动做循环展开)。这样设计是为了保证程序会在有限步骤 内结束,而不会让操作系统卡住。

我们的目标是:每当有程序监听 TCP socket,就得到一个事件通知。当在 AF_INET + SOCK_STREAM 类型 socket 上调用系统调用 listen() 时,底层负责处理的内核函数就 是 inet_listen()。我们从用 kprobe 在它的入口做 hook,打印一个 “Hello, World” 开始。

from bcc import BPF

# Hello BPF Program
bpf_text = """
#include <net/inet_sock.h>
#include <bcc/proto.h>

// 1. Attach kprobe to "inet_listen"
int kprobe__inet_listen(struct pt_regs *ctx, struct socket *sock, int backlog)
{
    bpf_trace_printk("Hello World!\\n");
    return 0;
};
"""

# 2. Build and Inject program
b = BPF(text=bpf_text)

# 3. Print debug output
while True:
    print b.trace_readline()
  1. 依据命名规则,将探测点 attach 到 inet_listen 函数。例如按照这种规则,如果 my_probe 被调用,它 将会通过 b.attach_kprobe("inet_listen", "my_probe") 显式 attach
  2. 使用 LLM eBPF 编译,将生成的字节码用 bpf() 系统调用注入(inject)内核,并自动根据命名规则 attach 到 probe 点
  3. 从内核管道读取原始格式的输出

 

标签:perf,eBPF,虚拟机,网络,网卡,网桥,内核,命名,数据包
From: https://www.cnblogs.com/ycjstudy/p/18103154

相关文章

  • 【Learning eBPF-1】什么是 eBPF?为什么它很吊?
    本书中,eBPF被称为一种革命性的内核技术,被广泛应用于网络、观测和安全工具中。这种技术允许你在不重新编译内核的情况下,使能你的自定义工具,与内核数据进行交互。听起来很厉害。1.1追踪溯源,伯克利包过滤器eBPF的祖宗就是伯克利包过滤器,英文名:TheBerkeleyPacketFilter,......
  • 【Learning eBPF-0】引言
    本系列为《LearningeBPF》一书的翻译系列。(内容并非机翻,部分夹带私货)笔者学习自用,欢迎大家讨论学习。转载请联系笔者或注明出处,谢谢。各个章节内容:1)背景介绍:为啥eBPF很吊,以及内核如何支持这种超能力的。2)给出一个“HelloWorld”例子,介绍eBPF和`maps`的概念。3)深入......
  • 在Linux中,如何追踪TCP连接和网络数据包,如使用tcpdump或Wireshark?
    在Linux环境中,追踪TCP连接和网络数据包主要通过使用命令行工具tcpdump和图形化网络分析软件Wireshark来实现。以下是详细的操作步骤:1.使用tcpdumptcpdump是一个强大的命令行网络抓包工具,用于实时捕获和分析网络流量。以下是如何使用tcpdump追踪TCP连接和数据包:1.基本用法......
  • STM32收发HEX数据包
            在实际应用中,STM32的串口通信都是以数据包格式进行收发,这个数据包一般都包含包头和包尾,表示一个数据包。源代码在文末给出数据包格式:固定长度,含包头包尾可变包长,含包头包尾问题1:当数据包传输时,里面有数据与包头包尾重复怎么办?1:设置限幅,包头包尾设置为数......
  • 02-基于STM32F407MAC与DP83848实现以太网通讯六(IPerf网络速度测试)
    一、IPerf2网络测试工具Iperf2是一个用于测试网络带宽的工具。它是Iperf的旧版本,专注于提供基本的带宽测量功能。通过在客户端和服务器之间发送测试数据流并测量其性能,用户可以评估网络连接的速度和稳定性。Iperf2提供了一种简单而有效的方式来评估网络性能。IPerf3已经发布了,但......
  • NVIDIA H200 创下 MLPerf LLM 最新推理记录
    NVIDIAH200TensorCoreGPU和NVIDIATensorRT-LLM创下MLPerfLLM最新推理记录生成式人工智能正在解锁新的计算应用程序,通过持续的模型创新来极大地增强人类的能力。生成式AI模型(包括大型语言模型(LLM))用于制作营销文案、编写计算机代码、渲染详细图像、创作音......
  • [转帖]SPECjbb MultiJVM - Java Performance
     MovingonfromSPECCPU,weshiftovertoSPECjbb2015.SPECjbbisafromground-updevelopedbenchmarkthataimstocoverbothJavaperformanceandserver-likeworkloads,fromtheSPECwebsite:“TheSPECjbb2015benchmarkisbasedontheusagemodelofa......
  • iperf详解 ---- 灌包
    摘自:https://zhuanlan.zhihu.com/p/585534080我们前面介绍过(我今天学习了一下3个perf:iperf、netperf和qperf),iperf3是用于执行网络吞吐量测量的工具,可以测试TCP、UDP或SCTP的吞吐量。本文以iperf3.12为例,介绍一下iperf3命令的详细用法。  快速用例  要执行iperf3测试......
  • Perfection
    #简述关于HTB机器Perfection的渗透过程靶机:10.10.11.253攻击机:10.10.14.65#过程1、老样子,nmap扫描目标靶机nmap-A10.10.11.2532、发现只打开了22,80这两个常规端口,使用浏览器访问80端口,发现这个是一个计算加权分数的工具网站。3、使用dirsearch进行目录扫描,也只是扫出/abou......
  • Windows Packet Divert(WinDivert)是一个适用于Windows 10、Windows 11和Windows Server
    WindowsPacketDivert(WinDivert)是一个适用于Windows10、Windows11和WindowsServer的用户模式数据包捕获和重定向工具。WinDivert允许用户模式应用程序捕获/修改/丢弃发送到/从Windows网络堆栈的网络数据包。总之,WinDivert可以:捕获网络数据包过滤/丢弃网络数据包嗅探......