2013-05-13 186 views
1

我正在嘗試創建Linux內核模塊,它將檢查傳入數據包。目前,我正在提取數據包的TCP報頭並讀取源端口和目標端口 - >但是,我得到的值不正確。我有鉤子函數:C - Linux - 內核模塊 - TCP標頭

unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, 
         const struct net_device *in, 
         const struct net_device *out, 
         int (*okfn)(struct sk_buff *)) 
{ 
    struct iphdr *ipp = (struct iphdr *)skb_network_header(skb); 
    struct tcphdr *hdr; 
    /* Using this to filter data from another machine */ 
    unsigned long ok_ip = 2396891328; 

    /* Some problem, empty network packet. Stop it now. */ 
    if (!skb) 
     return NF_ACCEPT; 

    /* Just to track only packets coming from 1 IP */ 
    if (ipp->saddr != ok_ip) 
     return NF_ACCEPT; 

    /* Incomming packet is TCP */ 
    if (ipp->protocol == IPPROTO_TCP) { 
     hdr = (struct tcphdr *) skb_transport_header(skb); 
     printk(" TCP ports: source: %d, dest: %d .\n", ntohs(hdr->source), 
                 ntohs(hdr->dest)); 
    } 
} 

現在,當我嘗試telnet端口(不聽那裏我得到):

[ 4252.961912] TCP ports: source: 17664, dest: 52 . 
[ 4253.453978] TCP ports: source: 17664, dest: 52 . 
[ 4253.953204] TCP ports: source: 17664, dest: 48 . 

當我telnet端口 - SSH守護進程監聽有:

[ 4299.239940] TCP ports: source: 17664, dest: 52 . 
[ 4299.240527] TCP ports: source: 17664, dest: 40 . 
[ 4299.552566] TCP ports: source: 17664, dest: 40 . 

從輸出中可以看到我得到了非常奇怪的結果,任何人都有想法,哪裏出現問題從?當我編譯模塊時,我沒有錯誤/警告。內核版本(頭文件):3.7.10。不使用SELinux或類似軟件。

+0

這可能與NAT重定向有關。即使您的數據包應該在端口21和22上,路由器會將其轉換爲動態端口,然後服務器實際上會從該端口獲取請求。在回來的路上,服務器的標題顯示了這一點,路由器將它轉發給你。我不認爲這個頭文件實際上已經改變(或封裝)了,因爲我認爲hte路由器進入了頭文件並且改變了它。 – Magn3s1um 2013-05-13 18:46:57

+0

您應該嘗試打印傳出數據包。如果他們顯示正確的端口,那麼路由器會爲您更改這些值。 – Magn3s1um 2013-05-13 18:50:46

+0

沒有NAT。 這兩臺機器都在ESX服務器上,沒有VLAN。機器具有IP:192.168.221.141/24和192.168.221.142/24,所以我沒有看到任何可以修改數據包的可能性。還有沒有iptables規則,都設置爲接受。 – LukasH 2013-05-13 20:41:15

回答

7

我有同樣的問題,寫一個網絡類的小型防火牆我剛剛發現了我遇到的問題。我錯了tcp頭文件。嘗試轉換爲TCP然後訪問端口。

這裏是它的工作

struct iphdr *ip_header;  // ip header struct 
struct tcphdr *tcp_header;  // tcp header struct 
struct udphdr *udp_header;  // udp header struct 
struct sk_buff *sock_buff; 

unsigned int sport , 
      dport; 


sock_buff = skb; 

if (!sock_buff) 
    return NF_ACCEPT; 

ip_header = (struct iphdr *)skb_network_header(sock_buff); 
if (!ip_header) 
    return NF_ACCEPT; 


//if TCP PACKET 
if(ip_header->protocol==IPPROTO_TCP) 
{ 
    //tcp_header = (struct tcphdr *)skb_transport_header(sock_buff); //doing the cast this way gave me the same problem 

    tcp_header= (struct tcphdr *)((__u32 *)ip_header+ ip_header->ihl); //this fixed the problem 

    sport = htons((unsigned short int) tcp_header->source); //sport now has the source port 
    dport = htons((unsigned short int) tcp_header->dest); //dport now has the dest port 
} 
+0

謝謝, 'tcp_header =(struct tcphdr *)((__ u32 *)ip_header + ip_header-> ihl);' 解決了我的問題。 – LukasH 2013-05-14 05:23:40

+2

你也可以使用這兩個函數來獲得IP頭和TCP頭'ip_hdr(sock_buff)'和'tcp_hdr(sock_buff)'' – IoT 2014-07-02 11:47:22

1

要想從套接字緩衝區(skb)的IP報頭或TCP頭,只是應用功能ip_hdr(skb)tcp_hdr(skb)的代碼片段。