You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

eBPF Hook sys_enter_connect/bind跟踪点无法阻断特定进程Socket连接求助

问题根源与解决方法

你用tracepoint的sys_enter_connect/sys_enter_bind无法阻断连接的核心原因是:tracepoint是内核提供的观测性钩子,仅用于采集数据,其BPF程序的返回值不会影响原系统调用的执行流程。返回-1在这里没有任何阻断作用,系统调用会继续正常执行。

要实现系统调用阻断,需要使用能够修改系统调用返回值的钩子类型,比如fentry(推荐)或kprobe。以下是具体实现方案:

1. 使用fentry钩子拦截系统调用

fentry是内核4.17+提供的函数入口钩子,稳定性优于kprobe,直接hook系统调用的内核实现函数(如__sys_connect、__sys_bind),通过修改寄存器里的返回值来阻断调用。

示例代码

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/socket.h>
#include <linux/types.h>

// 拦截__sys_connect
SEC("fentry/__sys_connect")
int BPF_PROG(hook_sys_connect, int fd, struct sockaddr __user *uservaddr, int addrlen)
{
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid >> 32; // 获取进程PID
    char comm[16];
    
    // 获取当前进程名(最多15字符+结束符)
    bpf_get_current_comm(&comm, sizeof(comm));

    // 替换为你要拦截的PID或进程名
    if (pid == 1234 || __builtin_memcmp(comm, "target_proc", 11) == 0) {
        // 设置系统调用返回错误码(EPERM表示权限不足)
        *PT_REGS_RC(ctx) = -EPERM;
        return 0;
    }

    return 0;
}

// 拦截__sys_bind
SEC("fentry/__sys_bind")
int BPF_PROG(hook_sys_bind, int fd, struct sockaddr __user *addr, int addrlen)
{
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid >> 32;
    char comm[16];
    
    bpf_get_current_comm(&comm, sizeof(comm));

    if (pid == 1234 || __builtin_memcmp(comm, "target_proc", 11) == 0) {
        *PT_REGS_RC(ctx) = -EPERM;
        return 0;
    }

    return 0;
}

char _license[] SEC("license") = "GPL";

2. 低内核版本兼容方案(使用kprobe)

如果内核版本低于4.17,可改用kprobe钩子,原理类似,只是hook的是系统调用的入口点:

示例代码

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/socket.h>

// 拦截sys_connect的kprobe
SEC("kprobe/sys_connect")
int BPF_KPROBE(hook_sys_connect, int fd, struct sockaddr __user *uservaddr, int addrlen)
{
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid >> 32;
    char comm[16];
    
    bpf_get_current_comm(&comm, sizeof(comm));

    if (pid == 1234 || __builtin_memcmp(comm, "target_proc", 11) == 0) {
        // 修改返回值,阻断调用
        bpf_set_retval(ctx, -EPERM);
        return 0;
    }

    return 0;
}

// 拦截sys_bind的kprobe
SEC("kprobe/sys_bind")
int BPF_KPROBE(hook_sys_bind, int fd, struct sockaddr __user *addr, int addrlen)
{
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid >> 32;
    char comm[16];
    
    bpf_get_current_comm(&comm, sizeof(comm));

    if (pid == 1234 || __builtin_memcmp(comm, "target_proc", 11) == 0) {
        bpf_set_retval(ctx, -EPERM);
        return 0;
    }

    return 0;
}

char _license[] SEC("license") = "GPL";

3. 关键注意事项

  • 内核版本适配:fentry需要Linux 4.17+,kprobe兼容性更好但稳定性稍差;不同架构的系统调用名称可能有差异(如arm64下是sys_connect而非__sys_connect),需根据目标架构调整。
  • 权限要求:加载BPF程序需要CAP_BPF、CAP_PERFMON等权限,建议用root用户或赋予对应权限的用户执行。
  • 进程匹配准确性:bpf_get_current_comm获取的进程名是16字节长度,注意目标进程名的长度不要超过15字符,否则会被截断。
  • 验证阻断效果:可通过strace目标进程,确认系统调用是否返回-EPERM错误。

内容的提问来源于stack exchange,提问作者nvd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:15:54