我正在编写一个内核模块,它使用netfilter注册一个钩子。如果我ssh / telnet到加载模块的机器,则不会调用该处理程序。
struct nf_hook_ops my_hook_ops;
my_hook_ops.hook = hook_handler;
my_hook_ops.pf = PF_INET;
my_hook_ops.hooknum = NF_INET_PRE_ROUTING;
my_hook_ops.priority = NF_IP_PRI_FIRST;
nf_register_hook(&my_hook_ops);
处理程序功能:
unsigned int hook_handler(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
if(!skb)
return NF_ACCEPT;
struct iphdr* ip_header;
struct tcphdr* tcp_header;
union ip_address ipaddr;
printk(KERN_INFO "Entered handler\n");
if(skb->protocol == 8)
return NF_ACCEPT;
// Log the received packet
ip_header = ip_hdr(skb);
tcp_header = tcp_hdr(skb);
ipaddr.saddr = ip_header->saddr;
printk(KERN_INFO "Received packet:\nIP Address: %u.%u.%u.%u\nProtocol: %d\nSource port: %d\nDestination port: %d\n",
ipaddr.a[0],ipaddr.a[1],ipaddr.a[2],ipaddr.a[3],
skb->protocol,
tcp_header->source,
tcp_header->dest);
return NF_ACCEPT;
}
正在为协议8(外部网关协议)调用挂钩。第二个printk永远不会打印出来。我错过了什么吗?
答案 0 :(得分:3)
此处使用的协议与IANA分配的IP协议号不同,其中8个用于EGP,EGP已过时。
定义了sk_buff的协议字段,其中8表示ETH_P_IP。由于您的数据始终是IP流量,因此第一次条件检查始终为真。所以代码的第二部分永远不会被执行。
答案 1 :(得分:1)
有几点想法:
skb->protocol
不存在。您想要(*skb)->protocol
或者您想要以下成语:struct sk_buff *sock_buf = *skb;
if(sock_buff->protocol)
答案 2 :(得分:0)
您需要研究sk_buff
如何工作,协议字段由函数“eth_type_trans”初始化,该函数采用ETH_P_ *值。所有ETH_P_ *值都在if_ether中定义。以下是其中一些值。
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
您清楚地看到为Internet Protocol packet
定义了0x08。并且您的代码在8(即IP
数据包)的情况下明确返回
if(skb->protocol == 8)
return NF_ACCEPT;
您的ssh/telnet
明确的IP数据包并被上述代码拒绝。请使用if_ethr