C 用于过滤NFS请求的内核模块

C 用于过滤NFS请求的内核模块,c,linux-kernel,kernel-module,nfs,C,Linux Kernel,Kernel Module,Nfs,我正在开发一个概念验证内核模块,根据一些标准(客户端IP地址、执行的操作类型等)过滤NFS请求 我使用了中描述的黑客方法,但无法在该方法中检索客户端IP地址 我目前的想法是使用一个Netfilter钩子来拦截网络数据包,解析它们以识别操作并在那里应用过滤 他是我所说的例子。。它适用于内核版本4.15.0 #include <linux/kernel.h> /* We're doing kernel work */ #include <linux/module.h&g

我正在开发一个概念验证内核模块,根据一些标准(客户端IP地址、执行的操作类型等)过滤NFS请求 我使用了中描述的黑客方法,但无法在该方法中检索客户端IP地址

我目前的想法是使用一个Netfilter钩子来拦截网络数据包,解析它们以识别操作并在那里应用过滤

他是我所说的例子。。它适用于内核版本4.15.0

#include <linux/kernel.h>       /* We're doing kernel work */
#include <linux/module.h>       /* Specifically, a module, */
#include <linux/moduleparam.h>  /* which will have params */
#include <linux/unistd.h>       /* The list of system calls */
#include <linux/dirent.h>
#include <linux/cred.h>
#include <linux/syscalls.h>
#include <linux/init.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/tcp.h>

static struct nf_hook_ops nfin;

static unsigned int hook_func_in(void *priv,
                   struct sk_buff *skb,
                   const struct nf_hook_state *state)
{
    struct ethhdr *eth;
    struct iphdr *ip_header;
    struct tcphdr *tcph;
    char *data;

    eth = eth_hdr(skb);
    ip_header = ip_hdr(skb);
    tcph = tcp_hdr(skb);
    data = (char *)((unsigned char *)tcph + (tcph->doff * 4));
    /* Skip if it's not TCP packet */
    if (ip_header->protocol != IPPROTO_TCP)
        return NF_ACCEPT;
    printk("src mac %pM --- src IP addr:%pI4 --- protocol: %u\n", eth->h_source, &ip_header->saddr, ip_header->protocol);
    printk("TCP source : %hu, TCP  dest : %hu\n", ntohs(tcph->source), ntohs(tcph->dest));
    // Parse data pointer here..
    return NF_ACCEPT;
}

int init_module()
{
    nfin.hook     = hook_func_in;
    nfin.hooknum  = NF_INET_LOCAL_IN;
    nfin.pf       = PF_INET;
    nfin.priority = 0;
    nf_register_net_hook(&init_net, &nfin);
    return 0;
}

void cleanup_module()
{
    nf_unregister_net_hook(&init_net, &nfin);
}
#include/*我们正在做内核工作*/
#包括/*特别是模块*/
#包括/*其中将包含参数*/
#包括/*系统调用列表*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
静态结构nf_hook_ops nfin;
静态无符号整数hook\u func\u in(void*priv,
结构sk_buff*skb,
const struct nf_hook_state*状态)
{
结构ethhdr*eth;
结构iphdr*ip_头;
结构tcphdr*tcph;
字符*数据;
eth=eth_hdr(skb);
ip_头=ip_hdr(skb);
tcph=tcp_hdr(skb);
数据=(字符*)((无符号字符*)tcph+(tcph->doff*4));
/*如果不是TCP数据包,则跳过*/
如果(ip_头->协议!=IPPROTO_TCP)
返回NF_接受;
printk(“src mac%pM---src IP addr:%pI4---protocol:%u\n”,eth->h\u source,&IP\u header->saddr,IP\u header->protocol);
printk(“TCP源:%hu,TCP目标:%hu\n”,ntohs(tcph->source),ntohs(tcph->dest));
//在此解析数据指针。。
返回NF_接受;
}
int init_模块()
{
nfin.hook=hook\u func\u in;
nfin.hooknum=NF_INET_LOCAL_IN;
nfin.pf=pf_INET;
nfin.priority=0;
nf\u寄存器\u网络\u钩子(&init\u网络,&nfin);
返回0;
}
void cleanup_模块()
{
nf_注销网络钩子(&init_网络,&nfin);
}
如何解析数据指针以识别我正在处理的请求类型?或者如何解析来自sk_buff对象的RPC请求


这是执行此任务的正确方法吗?

“如何解析”、“如何解析”-太宽泛了。具体点。Linux内核中有大量NFS代码。顺便说一句,在尝试访问TCP头之前,如果(ip_头->协议!=IPPROTO_TCP)执行
更合适。这就是我想问的,是否有一些函数可以调用,将sk_buff解析为某个RPC/NFS对象?或者我应该自己解析它?如果是这样,我该怎么做?(我可以使用什么资源等)谢谢你的提示。穆罕默德,试着为你的内核安装SystemTap(是RHEL、CentOS、Debian还是Ubuntu?什么是
unaa-a
output?)。系统选项卡上有nfsdtop stap脚本,它可以访问一些内部nfs指针——nfsdtop.stp脚本收集并显示nfs查找,
\stap nfsd\u unlink.stp-c“sleep 0.2”
。另一个变体是修补内核源代码并使用跟踪工具它的Ubuntu
Linux Ubuntu VirtualBox 4.15.0-20-generic\21 Ubuntu SMP周二4月24日06:16:15 UTC 2018 x86\u 64 x86\u 64 GNU/Linux
。我会查看SystemTap并让您知道。