某日在openvpn服务器上配置iptables,配置完成,却发现forward中所有过滤居然都没有生效。传了个文件,发现流量居然都直接从input和output了,抓包后发现openvpn只是以其服务端口与两客户端建立了直接的连接实现了数据传输。百思不得其解,openvpn的的iptables示例明明就是在forward做过滤的啊。

百思不得其解之时,只好上水木社区求助。某大牛发来man page中的一段。大悟。

–client-to-client
Because the OpenVPN server mode handles multiple clients through
a single tun or tap interface, it is effectively a router. The
–client-to-client flag tells OpenVPN to internally route
client-to-client traffic rather than pushing all client-origi-
nating traffic to the TUN/TAP interface.

When this option is used, each client will “see” the other
clients which are currently connected. Otherwise, each client
will only see the server. Don’t use this option if you want to
firewall tunnel traffic using custom, per-client rules.

原来我一直都误以为client-to-client这个选项是用来控制两客户端可否通讯与否。没想到却根本不是这么一回事,后来一问同事,才发现大家都这么认为。原因何在,就是大家都太信任网上一些汉化的配置实例。看来,大多数时候我们有必要自己去翻阅英文的文档啊!

这几天折腾iptables,我使用了一个路由器,一台linux作为网关,一个windows主机。三台机器用交换机相连。我要实现的目标是,windows的网关指向linux主机,用iptables来限制上网。
原本按照iptables的理论,转发的数据应该只通过FORWARD链。于是我只要INPUT和FORWARD做了限制,默认为DROP,允许了一些自己认可的端口通过,OUTPUT默认为ACCEPT。这原本就是一个很标准的过滤。但是真正应用的时候,问题出现了,FORWARD链的过滤根本没有起作用。只有把OUTPUT改为DROP才能起作用。百思不得其解之时,我查看了一下windows的路由表。居然神奇地发现,路由表中居然把我请求过的目的地址的下一跳直接改成了我的路由器。即,只要我访问了一次,那么第二次他们根本就不会从我的linux通过。
抓包,发现linux给网关我的windows发了一个ICMP包。
在iptables中DROP掉此类型的ICMP数据,果然,一切正常。
查资料,原来就是一个简单的ICMP重定向~
恨当初自己没仔细看ICMP协议啊。
找出CCNA教程恶补。

当IP数据报应该被发送到另一个路由器时,收到数据报的路由器就要发送ICMP重定向差错报文给IP数据报的发送端。这在概念上是很简单的,正如图9-3所示的那样。只有当主机可以选择路由器发送分组的情况下,我们才可能看到ICMP重定向报文(回忆我们在图7-6中看过的例子)。
1)我们假定主机发送一份IP数据报给R1。这种选路决策经常发生,因为R1是该主机的默认路由。
2)R1收到数据报并且检查它的路由表,发现R2是发送该数据报的下一站。当它把数据报发送给R2时,R1检测到它正在发送的接口与数据报到达接口是相同的(即主机和两个路由器所在的LAN)。这样就给路由器发送重定向报文给原始发送端提供了线索。
3)R1发送一份ICMP重定向报文给主机,告诉它以后把数据报发送给R2而不是R1。

图9-3 ICMP重定向的例子
  重定向一般用来让具有很少选路信息的主机逐渐建立更完善的路由表。主机启动时路由表中可以只有一个默认表项(在图9-3所示的例子中,为R1或R2)。一旦默认路由发生差错,默认路由器将通知它进行重定向,并允许主机对路由表作相应的改动。ICMP重定向允许TCP/IP主机在进行选路时不需要具备智能特性,而把所有的智能特性放在路由器端。显然,在我们的例子中,R1和R2必须知道有关相连网络的更多拓扑结构的信息,但是连在LAN上的所有主机在启动时只需一个默认路由,通过接收重定向报文来逐步学习。