bcc 是基于 LLVM 的工具集,用 Python 封装了底层机器相关的细节,bcc工具使得 eBPF 的使用更加方便,使用时内核探测代码用 C 写, 数据处理用 Python 。本文将使用 bcc工具抓取内核网络中的数据,包括抓取 backlog 信息、port 和 IP 信息、网络命名空间信息等。

eBPF 可以将任何内核函数调用转换成可带任何数据的用户空间事件。每当有程序监听 TCP socket,就得到一个事件通知。当在 AF_INETSOCK_STREAM 类型的 socket 上调用系统调用 listen() 时,底层负责处理的内核函数就是 inet_listen()。我们可以用 kprobe 在它的入口做 hook,从打印一个 Hello, World开始。

1. bcc程序代码:

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()

这个程序做了 3 件事情:

  • 依据命名规则,将探测点 attach 到 inet_listen 函数;
  • 使用 LLVM eBPF 编译,将生成的字节码用 bpf() 系统调用注入(inject)内核,并自动根据命名规则 attach 到 probe 点;
  • 从内核管道读取原始格式的输出,bpf_trace_printk() 可以将 tracing 信息打印到 /sys/kernel/debug/tracing/trace_pipe 下面的一个特殊管道。

2. 运行结果

运行此bcc程序,在另一个终端输入nc -l 0 4242,可以看到此bcc程序运行结果如下:

nc 是个单连接的小工具。

3. 获取 backlog 信息

“backlog” 是 TCP socket 允许建立的最大连接的数量(等待被 accept())。

将程序中的 bpf_trace_printk 修改为如下:

bpf_trace_printk("Listening with with up to %d pending connections!\\n", backlog);

重新运行程序,在另一个终端输入nc -l 0 4242,因为 nc 是一个单链接的小工具,所以 backlog 是 1,运行结果如下:

4. 获取 port 和 IP 信息

阅读内核 inet_listen 源码发现,我们需要从 socket 对象中拿到 inet_sock 字段 。从内核直接拷贝这两行代码,放到我们 tracing 程序的开始处:

// cast types. Intermediate cast not needed, kept for readability
struct sock *sk = sock->sk;
struct inet_sock *inet = inet_sk(sk);

port 可以从 inet->inet_sport 中获得,注意是网络序(大端)。IP 从 inet->inet_rcv_saddr 读取。现在将程序中的 bpf_trace_printk 修改为如下:

bpf_trace_printk("Listening on %x %d with %d pending connections\\n", inet->inet_rcv_saddr, inet->inet_sport, backlog);

重新运行程序,在另一个终端输入nc -l 0 4242,运行结果如下:

5. 获取网络空间命名信息

在用户空间,可以在/proc/PID/ns/net查看网络命名空间,格式类似于 net:[4026531957]。中括号中的数字是网络命名空间的 inode。这意味着,想获取命名空间,我们可以直接去读 proc 。但是,这种方式只适用于运行时间比较短的进程,而且还存在竞争。下面我们使用 eBPF 从 kernel 直接读取 inode 值,添加获取网络命名空间功能后的完整bcc程序如下:

from bcc import BPF# Hello BPF Program
bpf_text = """
#include <net/inet_sock.h>
#include <bcc/proto.h>
#include <net/sock.h>
// 1. Attach kprobe to "inet_listen"
int kprobe__inet_listen(struct pt_regs *ctx, struct socket *sock, int backlog)
{// cast types. Intermediate cast not needed, kept for readabilitystruct sock *sk = sock->sk;struct inet_sock *inet = (struct inet_sock *)sk;// Create an populate the variableu32 netns = 0;// Read the netns inode number, like /proc doesnetns = sk->__sk_common.skc_net.net->ns.inum;bpf_trace_printk("Listening on %x %d with %d pending connections in container %d \\n", inet->inet_rcv_saddr, inet->inet_sport, backlog, netns);return 0;
};
"""# 2. Build and Inject program
b = BPF(text=bpf_text)# 3. Print debug output
while True:print b.trace_readline()

运行时出现了这样的错误:

error: <unknown>:0:0: in function kprobe__inet_listen i32 (%struct.pt_regs*): too many args to 0x55a83e8f8320: i64 = Constant<6>

Clang 想告诉我们:bpf_trace_printk 带的参数太多了,这是 BPF 的限制。解决这个问题的办法就是使用 perf,它支持传递任意大小的结构体到用户空间。(注意需要 Linux 4.4 以上内核)

今天先分享到这里,下篇文章继续分享具体解决办法以及在eBPF内核探测中如何将任意系统调用转换成事件。

eBPF学习——抓取内核网络中的socket信息相关推荐

  1. 使用Debookee抓取同一网络中中任何设备的报文

    Debookee 是一款强大的网络流量拦截工具.借助MITM,Debookee能够拦截和监视同一网络中中任何设备的传入传出流量.它允许您从Mac(iPhone,iPad,Android,BlackBe ...

  2. 数据抓取,爬虫豆瓣读书书籍信息

    标题抓取豆瓣读书中的书籍信息 //思路: //先爬取网页html //将网页html进行分析,获取每个数据详情信息(在这里比较好找到作者,书名...等信息) //将每本书籍的详情信息进行抓取,转换为自 ...

  3. 内核网络中的GRO、RFS、RPS技术介绍和调优

    内核网络中的GRO.RFS.RPS技术介绍和调优 1. 前言 2. GRO(Generic Receive Offloading) 2.1 使用 ethtool 修改 GRO 配置 2.2 napi_ ...

  4. 用户态 tcpdump 如何实现抓到内核网络包的?

    用户态 tcpdump 如何实现抓到内核网络包的?运行在用户态的程序 tcpdump 是如何实现抓到内核态的包的呢?https://mp.weixin.qq.com/s/ZX8Jluh-RgJXcVh ...

  5. 抓取百度页面html,百度会抓取页面代码中的注释内容吗

    百度会抓取页面代码中的注释内容吗 内容导读:百度会抓取页面代码中的注释内容吗?答案是百度会抓取,但是在提取正文的时候会直接忽略掉,也就是说页面代码的注释内容不会影响到页面质量,所以大家尽管放心. 问题 ...

  6. python 爬虫学习:抓取智联招聘网站职位信息(二)

    在第一篇文章(python 爬虫学习:抓取智联招聘网站职位信息(一))中,我们介绍了爬取智联招聘网站上基于岗位关键字,及地区进行搜索的岗位信息,并对爬取到的岗位工资数据进行统计并生成直方图展示:同时进 ...

  7. 网络抓取与网络爬取的区别

    网络抓取,从其自身的含义到在商业领域使用的各种情况,以及未来商业领域的无限潜能来看,都相对复杂.当然,还有另一个常见的术语--网络爬取.可能别人会说两种说法意义相同,但其实还是有细微差别的,今天我们就 ...

  8. 关于fi dd ler 手机抓包 网卡地址地址_利用无线路由器如何抓取手机网络数据包【详细介绍】...

    当用户运用手机访问网络时,手机在不断接受与发送数据包,而这些数据包中包含了大量的用户信息,包括各种账号信息.聊天信息.发送接收文件.邮件.浏览的网页等.虽然很多信息是加密传输的,但还是会有大量信息是明 ...

  9. wireshark抓取聊天网络数据包

    wireshark抓取聊天网络数据包 一.实验任务 二.实验步骤 三.总结 总结 一.实验任务 据包.在两台及两台以上的电脑(已知IPv4地址)上运行 "疯狂聊天室"程序,通过wi ...

最新文章

  1. beamSearch算法原理
  2. python 定义变量怎么定义_python变量定义和定义规范
  3. 无刷新上传Excel后利用JQuery AJAX 显示进度条的实现方式
  4. 最长递增子序列_python_算法与数据结构
  5. 开发人员不可不知的六大JavaScript框架 传统网站网页转移动端方式
  6. 云架构师是做什么的_为什么以及如何成为云架构师
  7. linux6.5+5.4 vncserver配置
  8. c++ 字符串合并_Python基础字符串处理
  9. AndroidStudio安卓原生开发_Activity的启动模式部分singleTop启动模式和singleTask启动模式---Android原生开发工作笔记87
  10. asp.net 按钮点击调用FileUpload
  11. resin java_让resin4自动编译java文件
  12. 经济机器是如何运行的(观后感)
  13. C++多线程detach函数使用
  14. 通过Python获取维基百科中概念词条的维基信息
  15. 集群调度LSF-学习笔记
  16. win10安装红警运行出现FATALString Manager failed to initilaized properly
  17. 关于前端接口报错500原因
  18. Linux下Rsync+sersync实现数据实时同步
  19. java实现下载网络图片到本地
  20. 整数规划 - 数学建模

热门文章

  1. linux修改ssh端口和禁止root远程登陆设置
  2. SQLite.NET提供程序的选择
  3. spring 注解@PathVariable
  4. Networking 基本术语/概念
  5. 避无可避:Mesos安全问题的几点思考
  6. Neutron 物理部署方案 - 每天5分钟玩转 OpenStack(68)
  7. cuda_opencv 矩阵相加
  8. Android动态加载技术初探
  9. Win7开机蓝屏错误atikmpag.sys的解决方法
  10. java maven mvn clean package 打包执行流程