searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

使用systemtap跟踪ping关键流程

2025-04-27 10:30:30
0
0

ping命令的发送过程,是从用户态到网卡。接收过程,是从网卡到用户态。下面以ip发送函数ip_output和ip接收函数ip_rcv为例来跟踪特定的ping数据包。执行命令的环境为虚拟机,ip地址为192.168.122.33,目标机器为宿主机,ip地址为10.63.8.161。

global TARGET_IP = "10.63.8.161"
%{
#include <linux/ip.h>
#include <linux/skbuff.h>
#include <linux/inet.h>
%}
# --------- Helper Functions ---------#
#将IP字符串转换为整数
function ip_to_int(ip_str) %{
 struct in_addr addr;
 int ret = in4_pton(STAP_ARG_ip_str, -1, (u8*)&addr, '\0', NULL);
 if (ret >0) {
 STAP_RETURN(ntohl(addr.s_addr));
 } else {
 STAP_RETURN(0);
 }
%}

#获取IP协议、源地址、目标地址(返回多个值)
function get_ip_protocol:long(skb) %{
 struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
 struct iphdr *iph = ip_hdr(skb);
 STAP_RETURN(iph->protocol);
%}

function get_saddr:long(skb) %{
 struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
 struct iphdr *iph = ip_hdr(skb);
 STAP_RETURN(ntohl(iph->saddr));
%}

function get_daddr:long(skb) %{
 struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
 struct iphdr *iph = ip_hdr(skb);
 STAP_RETURN(ntohl(iph->daddr));
%}

# --------- Probe Handlers ---------#
probe kernel.function("ip_rcv") {
 skb = $skb 
 protocol = get_ip_protocol(skb)
 saddr = get_saddr(skb)
 daddr = get_daddr(skb)
 target = ip_to_int(TARGET_IP)

 if (protocol ==1 && (saddr == target || daddr == target)) {
 printf("[RCV %05d] %s ICMP %s -> %s\n", pid(), ctime(gettimeofday_s()),
 ip_ntop(htonl(saddr)), ip_ntop(htonl(daddr)))
 }
}

probe kernel.function("ip_output") {
 skb = $skb 
 protocol = get_ip_protocol(skb)
 saddr = get_saddr(skb)
 daddr = get_daddr(skb)
 target = ip_to_int(TARGET_IP)

 if (protocol ==1 && (saddr == target || daddr == target)) {
 printf("[SND %05d] %s ICMP %s -> %s\n",
 pid(), ctime(gettimeofday_s()),
 ip_ntop(htonl(saddr)), ip_ntop(htonl(daddr)))
 }
}

probe begin {
 println("[+] Tracing ICMP to/from: ", TARGET_IP)
}

脚本执行结果

[root@localhost ~]# stap -g ping_trace/ping_ip_filter_v6.stp     
[+] Tracing ICMP to/from: 10.63.8.161
[SND 14453] Wed Feb 12 10:58:42 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:42 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:43 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:43 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:44 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:44 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:45 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:45 2025 ICMP 10.63.8.161 -> 192.168.122.33
0条评论
0 / 1000
c****w
5文章数
0粉丝数
c****w
5 文章 | 0 粉丝
原创

使用systemtap跟踪ping关键流程

2025-04-27 10:30:30
0
0

ping命令的发送过程,是从用户态到网卡。接收过程,是从网卡到用户态。下面以ip发送函数ip_output和ip接收函数ip_rcv为例来跟踪特定的ping数据包。执行命令的环境为虚拟机,ip地址为192.168.122.33,目标机器为宿主机,ip地址为10.63.8.161。

global TARGET_IP = "10.63.8.161"
%{
#include <linux/ip.h>
#include <linux/skbuff.h>
#include <linux/inet.h>
%}
# --------- Helper Functions ---------#
#将IP字符串转换为整数
function ip_to_int(ip_str) %{
 struct in_addr addr;
 int ret = in4_pton(STAP_ARG_ip_str, -1, (u8*)&addr, '\0', NULL);
 if (ret >0) {
 STAP_RETURN(ntohl(addr.s_addr));
 } else {
 STAP_RETURN(0);
 }
%}

#获取IP协议、源地址、目标地址(返回多个值)
function get_ip_protocol:long(skb) %{
 struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
 struct iphdr *iph = ip_hdr(skb);
 STAP_RETURN(iph->protocol);
%}

function get_saddr:long(skb) %{
 struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
 struct iphdr *iph = ip_hdr(skb);
 STAP_RETURN(ntohl(iph->saddr));
%}

function get_daddr:long(skb) %{
 struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
 struct iphdr *iph = ip_hdr(skb);
 STAP_RETURN(ntohl(iph->daddr));
%}

# --------- Probe Handlers ---------#
probe kernel.function("ip_rcv") {
 skb = $skb 
 protocol = get_ip_protocol(skb)
 saddr = get_saddr(skb)
 daddr = get_daddr(skb)
 target = ip_to_int(TARGET_IP)

 if (protocol ==1 && (saddr == target || daddr == target)) {
 printf("[RCV %05d] %s ICMP %s -> %s\n", pid(), ctime(gettimeofday_s()),
 ip_ntop(htonl(saddr)), ip_ntop(htonl(daddr)))
 }
}

probe kernel.function("ip_output") {
 skb = $skb 
 protocol = get_ip_protocol(skb)
 saddr = get_saddr(skb)
 daddr = get_daddr(skb)
 target = ip_to_int(TARGET_IP)

 if (protocol ==1 && (saddr == target || daddr == target)) {
 printf("[SND %05d] %s ICMP %s -> %s\n",
 pid(), ctime(gettimeofday_s()),
 ip_ntop(htonl(saddr)), ip_ntop(htonl(daddr)))
 }
}

probe begin {
 println("[+] Tracing ICMP to/from: ", TARGET_IP)
}

脚本执行结果

[root@localhost ~]# stap -g ping_trace/ping_ip_filter_v6.stp     
[+] Tracing ICMP to/from: 10.63.8.161
[SND 14453] Wed Feb 12 10:58:42 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:42 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:43 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:43 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:44 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:44 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:45 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:45 2025 ICMP 10.63.8.161 -> 192.168.122.33
文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0