如何从sk_buff读取实际目的地地址?

时间:2015-09-15 12:01:44

标签: linux linux-kernel linux-device-driver

我正在编写一个netfilter模块,根据目标IP检查丢弃数据包。

我注册了一个nf钩子

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钩子函数

    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钩子函数中获取实际的目标地址?

2 个答案:

答案 0 :(得分:3)

我发现您发布的代码段没有任何问题。

当您在网络浏览器中打开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

正如您所看到的,www.google.com已被DNS服务器 192.168.1.1 解析为 216.58.220.36 ,这也是我案例中的默认网关。请注意,在 nslookup 期间,我的dest_ip为192.168.1.1。

DNS解析后,我的系统会发送dest_ip 216.58.220.36 的TCP和HTTP消息。

<强> test.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);

罗伊

答案 1 :(得分:1)

你的代码似乎没有逻辑错误。您的问题根植于网络结构(如下所述)或Web服务器计算机。现在服务器可以检测查询是来自Web浏览器还是其他一些软件 你不能在最终用户的互联网电脑上做这种过滤。问题是从你的电脑到谷歌服务器有一些障碍,如代理,路由器的设置,防火墙/网关交叉。您的电脑似乎只获得自己的本地网络网关/代理地址 一些建议来解决这个问题

从不同的网络测试您的应用,以确认您自己的防火墙/代理不是问题的原因 如果您有一些资源,使用路由器和交换机进行简单的互联网,并尝试访问托管在您自己的互联网上的网站。如果你没有硬件,那么尝试一些网络仿真器/模拟器来测试你的代码。 NS2 / NS3和OMNET免费提供很多教程。

问题的根源在于您在某种程度上受到防火墙的保护。您的10.169.95.255是本地IP,这意味着您无法跨越自己的网络。