天天看點

關于Netfilter NF_HOOK宏的outdev參數bug

正确的方式要麼是不傳遞,要麼是傳遞指針的位址,即位址的位址。

因 為在該HOOK點可能存在多個HOOK函數,每一個函數都有可能改變skb的路由,即調用reroute,比如NAT,比如IP Mark等,這樣後續的HOOK函數看到的依然是舊的outdev參數,而不是reroute之後的skb_dst(skb)->dev。

設定預設路由

0.0.0.0/0 via 192.168.1.1 eth0

設定政策路由

iptables -t mangle -A OUTPUT -d 1.1.1.1 -j MARK --set-mark 100

ip rule fwmark 100 table my

ip route add 0.0.0.0/0 via 192.168.2.1 dev eth1 table my

防止mark 100的資料包從eth0出去(這實際上隻是為了展現問題而添加的多餘的一條規則)

iptables -A OUTPUT -d 1.1.1.1 -o eth0 -j DROP

效 果是到達1.1.1.1的資料包被DROP掉了。是的,政策路由确實生效了,問題在于進入OUTPUT的filter HOOK函數的時候,outdev還是舊的outdev。因為OUTPUT處在路由之後,如果其中的mangle表改變了skb的mark,那麼會 reroute,不幸的是,reroute并無法改變OUTPUT點上NF_HOOK的outdev參數值!

辦法很多,依次介紹:

a.使用setsockopt打mark而不是iptables打mark,繞開OUTPUT和路由的暧昧關系;

b. 修改NF_HOOK的dev參數為struct net_device **類型,然後在reroute中重路由成功後執行*out = (struct dst_entry*)skb_dst(skb)->dev;進而改變NF_HOOK中的outdev的值;

c.去掉NF_HOOK宏的outdev參數,需要時從skb_dst(skb)->dev中實時擷取;

很簡單,在ipt_do_table的開頭位置,即變量聲明的完結處,加入下面的代碼:

實時替換掉參數定義的out值。

d.使用非傳值機制!C語言是傳值的啊!使用連續的******可以為了尋址一個位元組周遊整個記憶體,即整個記憶體隻存儲一個位元組的值,其它的都被填滿為它的直接或者間接的位址,位址,位址...

一個實體隻能同時存在于一個位置!就像人一樣,進入了一個房間,外面就沒有這個人了,可惜程式設計語言不是這樣的。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1423292

繼續閱讀