下載下傳xtables-addons,編譯,安裝,然後man xtables-addons,你會發現:
DNETMAP
The DNETMAP target allows dynamic two-way 1:1 mapping of IPv4 subnets. Single rule can map private subnet to shorter
public subnet creating and maintaining unambigeous private-public ip bindings. Second rule can be used to map new flows
to private subnet according to maintained bindings. Target allows efficient public IPv4 space usage and unambigeous NAT
at the same time.
...
--prefix addr/mask
--reuse
--persistent
--static
--ttl seconds
* /proc interface
Module creates following entries for each new specified subnet:
/proc/net/xt_DNETMAP/subnet_mask
/proc/net/xt_DNETMAP/subnet_mask_stat
Following write operations are supported via proc interface:
echo "+prenatIP:postnatIP" > /proc/net/xt_DNETMAP/subnet_mask
先說下這是個什麼東西吧。這是一個擴充iptables自帶NAT功能的NAT子產品,具體的功能自己自行去man。
這裡有一個功能是雙向的NAT,如果你不知道什麼是雙向NAT,那麼看看Cisco的static NAT配置手冊,所謂的雙向NAT就是和資料從哪個方向發起無關,如果你在一個方向配置了一條DNAT,那麼如果有一個流的第一個資料包從另一個方向而 來,NAT子產品會自動執行SNAT,這就是雙向NAT。我們來看一下使用DNETMAP子產品是怎麼配置的:
3. Map 192.168.0.0/24 to subnets 20.0.0.0/26 bidirectional way:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
iptables -t nat -A PREROUTING -j DNETMAP
If host 192.168.0.10 generates some traffic, it gets bound to first free IP in subnet - 20.0.0.0. Now any traffic
directed to 20.0.0.0 gets DNATed to 192.168.0.10 as long as there's an active (ttl>0) binding. There's no need to specify
--prefix parameter in PREROUTING rule, because this way it DNATs traffic to all active prefixes. You could specify prefix
it you'd like to make DNAT work for specific prefix only.
首 先,我不認為這是一個真正的雙向NAT,然而作者的本意真的就是想實作一個真正的雙向NAT。如果想主動在20.0.0.0/26段到 192.168.0.0/24段的方向上打開一個口子,必須首先由内向外主動先打一個口,且全部的反向流量都DNAT到了192.168.0.10,這合 理嗎?我想,鉗制這個實作達到最終目的的并非nf_conntrack,而是iptables。我再三強調,iptables的模式是“條件語句”而非 “祈使語句”,這就是說同一組matches不可能或者退一步說很難同時比對到兩個方向的資料流/資料包。是以:
1.要麼你就寫兩條NAT規則,這也是标準的做法;
2.要麼你就寫一個target,并且在規則中不設定任何match,這相當于一個祈使句,if(true);do sth...
其次,我們來看第二個問題,如果DNATMAP的作者也采用了上述第二種方式,那麼會怎樣。我的觀點是,如果DNETMAP也采用了僅使用單一 target的方式,那麼它也達到的效果要比我的static-stateless-2-way-NAT-on-Linux-with-iptables 更加perfect,這個more在于nf_conntrack。由于DNETMAP使用了nf_conntrack的接口,它這個NAT依然是基于 conntrack實作的,而conntrack和iptables規則的關聯點在conntrack結構體建立的當時,隻要規則中不寫任何match, 那麼任何方向到來的資料流的第一個資料包都會比對到這個規則,在target中做完全部的事,之後conntrack機制将會記住這個NAT結果,而不必 每次執行target。
我當時設計stateless-2-way-NAT-on-Linux-with-iptables的時候,最初的想法是stateless,也許這是我 對nf_conntrack的極端偏見導緻,這種偏見的形成來自多個方面,比如配置的NAT規則不能即時生效,這個局限導緻我在2012-2014年的時 間段中無數次的深夜呆在華麗麗銀行大廈裡的機房,還比如我在2004年初始接觸網絡的時候,對H3C/Cisco裝置的那種特殊的情感,再比如我對 iptables模式的不認同等,是以我希望能有一個毫無狀态的NAT,一個可以即時生效,類似Cisco的雙向靜态的NAT。在敲定了我的NAT一定得 是stateless的之後,我想它一定得是雙向的,這樣就不用配置兩條iptales規則了,這種想法還是來自對iptables的偏見,我熱愛 iptables,但是覺得它總是那麼美中不足。抛開所有這些偏見,xtables-addons的DNETMAP讓我看到了曙光,然而它還是沒有突破 iptables的“條件語句”模式帶來的那種可能造就深入人心的局限。新東西都是組合出來的,我的偏見給我帶來了一個stateless 2-way NAT實作,當我發現stateless僅僅就是極端帶來的偏見後,我決定抛棄它,保留2-way NAT,DNETMAP是statefull的,然而它在NAT操作中使用了match,如果将-s 192.168.0.0/24作為一個target的參數,問題就解決了。于是将我的2-way NAT的target only思想以及DNETMAP的statefull with nf_conntrack相結合,一個完美的NAT就出爐了。
最後,我想說一下我的自我讴歌。看看我們的接口設計是多麼的類似吧,同時有iptables接口和procfs接口(雖然我決定封閉procfs接口,但 這也是逆反心理帶來的好的或者不好的結果),procfs接口的操作方式,+/-方式添加/删除,另外,DNETMAP也注意到了xt_target結構 體裡面的checkentry問題,這事實上是iptables規則的連續排布導緻的,DNETMAP在checkentry中進行了NAT映射資料結構 的管理工作...
--------------------------------------------------
是 時候修剪我的stateless-2-way-NAT-on-Linux-with-iptables了,我将之重新命名為2-way-NAT-on- Linux-with-iptables,意味着它也是基于nf_conntrack的,是以它的iptables規則就可以安心配置在nat表中接受匹 配了。我在stateless-2-way-NAT-on-Linux-with-iptables中除了注冊了一個xt_target之外,還注冊了單 獨的nf_hook_ops用來執行實際操作,事實上,我的xt_target什麼都不做,僅僅是接收參數,将其配置到NAT映射容器中,由于重新擁抱了 nf_conntrack,是以這個單獨的nf_hook_ops将不再需要,一切都可以回到xt_target中來執行。
好了,事情就是這樣,很晚了,碎碎念小小...我還是那樣,自我否定,以對恥感的拒絕營建罪感的孤島,并最終從罪感中擷取力量,得以重生,事情不分大小,事情沒大也沒小。
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1612809