我正在编写一个 netfilter 模块来根据目标 IP 检查来丢弃数据包。
我注册了一个nf钩子(Hook)
nfho_out.hook = hook_func_out;
nfho_out.hooknum = NF_INET_LOCAL_OUT;
nfho_out.pf = PF_INET;
nfho_out.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho_out);
这是我的 nf 钩子(Hook)函数
unsigned int hook_func_out(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) {
struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);
struct udphdr *udp_header;
struct tcphdr *tcp_header;
struct list_head *p;
unsigned int src_ip = (unsigned int)ip_header->saddr;
unsigned int dest_ip = (unsigned int)ip_header->daddr;
unsigned int src_port = 0;
unsigned int dest_port = 0;
if (ip_header->protocol==17) {
udp_header = (struct udphdr *)skb_transport_header(skb);
src_port = (unsigned int)ntohs(udp_header->source);
} else if (ip_header->protocol == 6) {
tcp_header = (struct tcphdr *)skb_transport_header(skb);
src_port = (unsigned int)ntohs(tcp_header->source);
dest_port = (unsigned int)ntohs(tcp_header->dest);
}
printk(KERN_INFO "OUT packet info: src ip: %u, src port: %u; dest ip: %u, dest port: %u; proto: %u\n", src_ip, src_port, dest_ip, dest_port, ip_header->protocol);
printk(KERN_DEBUG "IP addres = %pI4 DEST = %pI4\n", &src_ip, &dest_ip);
....
....
}
我在网络浏览器中打开了 google.com,但无法获取 google.com 解析到的实际目标 IP 地址。问题是我总是得到一些奇怪的 IP 地址(因为我怀疑是代理或 dns 服务器)而不是实际的 IP 地址。
如何在nf hook函数中获取实际目的地址?
最佳答案
我没有发现您发布的代码片段有任何问题。
当您在网络浏览器中打开 www.google.com 时,首先解析 DNS,然后交换 HTTP 消息。因此你会看到在 DNS 解析过程中,dest_ip
是 GATEWAY/DNS SERVER ip。解析 DNS 后,在进一步的消息中,dest_ip
始终是 www.google.com 的已解析 IP。
首先通过在终端上发出以下命令来检查 www.google.com 解析了什么:
[s.roy@roy ~]$ nslookup www.google.com
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
Name: www.google.com
Address: 216.58.220.36
如您所见,DNS 服务器 192.168.1.1 将 www.google.com 解析为 216.58.220.36,这也是我的默认网关。请注意,在 nslookup 期间,我的 dest_ip
是 192.168.1.1。
DNS 解析后,我的系统将发送 TCP 和 HTTP 消息,dest_ip
为 216.58.220.36。
测试.c
static struct nf_hook_ops nfho_out;
static unsigned int hook_func_out(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);
struct udphdr *udp_header;
struct tcphdr *tcp_header;
struct list_head *p;
unsigned int src_ip = (unsigned int)ip_header->saddr;
unsigned int dest_ip = (unsigned int)ip_header->daddr;
unsigned int src_port = 0;
unsigned int dest_port = 0;
if (ip_header->protocol==17) {
udp_header = (struct udphdr *)skb_transport_header(skb);
src_port = (unsigned int)ntohs(udp_header->source);
} else if (ip_header->protocol == 6) {
tcp_header = (struct tcphdr *)skb_transport_header(skb);
src_port = (unsigned int)ntohs(tcp_header->source);
dest_port = (unsigned int)ntohs(tcp_header->dest);
}
printk(KERN_DEBUG "IP addres = %pI4 DEST = %pI4\n", &src_ip, &dest_ip);
return NF_ACCEPT;
}
static int __init test_init(void)
{
printk(KERN_INFO "Loading \n");
nfho_out.hook = hook_func_out;
nfho_out.hooknum = NF_INET_LOCAL_OUT;
nfho_out.pf = PF_INET;
nfho_out.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho_out);
return 0;
}
static void __exit test_exit(void)
{
printk(KERN_INFO "Unloading \n");
nf_unregister_hook(&nfho_out);
}
module_init(test_init);
module_exit(test_exit);
罗伊
关于linux - 如何从 sk_buff 读取实际目标地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32585573/