xtables-addons中的一个让我吃了一惊的模块DNETMAP
来源:互联网 发布:淘宝美妆店铺名字大全 编辑:程序博客网 时间:2024/04/29 14:18
这篇文章,我不想展开,本来我并不想写这么一篇文章,由于前段时间,我写了一个static-stateless-2-way-NAT-on-Linux-with-iptables发现自己重新造了轮子之后,我不得不讴歌一下自己。
下载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...
很显然,如果不是走火入了魔,基本都会使用第一种做法,DNETMAP也是这样。然而在我的static-stateless-2-way-NAT-on-Linux-with-iptables实现中,我采用了第二种方式,事实证明这也是非常不错的。
其次,我们来看第二个问题,如果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中来执行。
好了,事情就是这样,很晚了,碎碎念小小...我还是那样,自我否定,以对耻感的拒绝营建罪感的孤岛,并最终从罪感中获取力量,得以重生,事情不分大小,事情没大也没小。
下载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...
很显然,如果不是走火入了魔,基本都会使用第一种做法,DNETMAP也是这样。然而在我的static-stateless-2-way-NAT-on-Linux-with-iptables实现中,我采用了第二种方式,事实证明这也是非常不错的。
其次,我们来看第二个问题,如果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中来执行。
好了,事情就是这样,很晚了,碎碎念小小...我还是那样,自我否定,以对耻感的拒绝营建罪感的孤岛,并最终从罪感中获取力量,得以重生,事情不分大小,事情没大也没小。
1 0
- xtables-addons中的一个让我吃了一惊的模块DNETMAP
- 我使用的 Firefox Addons
- 该死的csdn,让我写的文章丢失了。我只想说,最近作了一个模块,发送mail的,先后我要发表一些相关的技术。
- 一个小细节让我整了一下午
- 指针操作,让我吃了一次亏
- 鸟儿吃了我种的草莓
- 我吃了同事的那个包子
- 救命!GNOME"吃"了我的男朋友!
- 猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,好不过瘾,又多吃了一个。第二天早上又吃了剩下的桃子的一半,又多吃了一个。以后每天都吃了前一天剩下的一半零一个,到第10天早上想再吃的时候,就剩下一
- 一个不起眼的手误,让我调了半小时
- 让我感动了一下午的帖子
- 让我纠结了一晚上的via协议
- 吃过一次后,便让我记住了那种属于广式腊味特有的香味
- 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一
- 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一
- Centos6下iptables配置Xtables-Addons和GeoIP屏蔽某个国家ip
- 儒学让我变成了一个理想主义者
- 管理是需要的。我是在99年接触csdn的。那时在csdn上看帖子,订程序员杂志,真是感觉获益非浅,由于工作的原因又一段时间没有上csdn。前几天和别的公司程序员聊天,我无意中说道,可以去csdn找找帮助呀,也许程序上的问题就解决了,他的回答让我吃了一惊,c
- 机器人操作系统ROS Indigo 入门学习(16)——记录和重放数据
- 机器人操作系统ROS Indigo 入门学习(17)——roswtf入门指南
- 机器人操作系统ROS Indigo 入门学习(18)——ROS wiki导航
- R语言学习(九)
- Introduction to configuration wrapper
- xtables-addons中的一个让我吃了一惊的模块DNETMAP
- poj2387 Til the Cows Come Home—Dijkstra模板
- [LeetCode] Find Minimum in Rotated Sorted Array
- dede中php标签不起作用无效
- 检查字符串中的结束标记
- Hdu 1387 Team Queue[队列 || 链表]
- 机器人操作系统ROS Indigo 入门学习(19)——接下来做什么
- 浅谈 PHP 与手机 APP 开发(API 接口开发)
- Android带清除按钮的EditText