0%

记一次有趣的iptables分析经历

前言

事情起因是一次修改家里VPN的路由方式,引发了一次关于iptables nat规则的思考。

网络

网络环境如下图,笔记本电脑通过VPN访问远程内网设备。

在VPN服务器中,通过一条NAT规则,将10段地址转为VPN服务器内网地址192.168.200.10以实现对内网设备的访问。VPN服务器与家里的内网设备不在同一个子网,两个子网间通过网关路由器进行转发,这样可以通过路由器做ACL规则以进行安全防护。

1
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE

起源

某天因为有了需要家里内网终端访问远程的笔记本电脑的需求,即192.168.100.0/24段对10.0.0.0/24段主动发起连接的需求。显然,在之前的网络结构中,只能实现VPN客户端对家里内网的单向访问,并无法实现互访。

要实现双向访问也并不难,这点以前就实现过类似需求,只需要把VPN服务器的MASQUERADE NAT规则去除,然后在家里的网关路由增加一条下面的规则即可:

1
2
3
4
5
# VPN SERVER 删除NAT规则
iptables -D POSTROUTING 1

# 路由器设置规则
route add -net 10.0.0.0/24 gw 192.168.100.10

数据包流转如下:

经过上面的规则设置,内网设备与VPN客户端已经可以实现双方ip的直接互访。但是问题也随之出现,考虑到安全问题,我需要设置ACL规则限制VPN客户端的访问范围,原本的方式只需要对VPN服务器的ip地址做ACL限制就行了,现在还需要在VPN服务器规则的基础上加入VPN客户端网段的限制,需要考虑和改动的规则更多了,一一改动显然是不够优雅的,而且也可能导致安全隐患(绕过ACL访问到内网设备)。

所以就准备恢复原本的访问模式,在VPN服务器重新启动NAT。

1
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE

但是我还没在网关上面删除10.0.0.0/24的静态路由,突发奇想试试内网客户端(DATA SERVER) ping 一下VPN客户端,发现是能ping通的!
而VPN客户端无法ping通内网客户端(DATA SERVER)。这好像误打误撞实现了我的需求,但是又不太对劲。

经过抓包分析,发现由内网客户端向VPN客户端发起请求时,VPN客户端的回应包不会被VPN服务器做NAT。

由此产生了本文的疑问,为什么明明符合了NAT规则,而iptables没有源地址为10.0.0.0/24的数据包作SNAT?

分析

首先抓取VPN客户端(LAPTOP) ping 内网客户端(DATA SERVER)的数据包。

数据包流转如下(来自抓包分析):

所以VPN客户端无法ping通内网客户端(DATA SERVER),但是可以ping通内网客户端(WORK)。

再看下从内网客户端(DATA SERVER)ping VPN客户端(LAPTOP)的数据包:


整个过程中奇怪的是从内网客户端(DATA SERVER)ping VPN客户端(LAPTOP)过程中,VPN客户端(LAPTOP)回应icmp请求时,VPN服务器收到数据包,是符合SNAT规则的,但是没有经过NAT就把数据包发送到网关路由器。

破案

根据上面的分析过程,可以推断,iptables在做SNAT的时候会先进行回话方向的判断的,即符合源ip规则发起的会话时会进行SNAT,若会话发起方不匹配源ip规则,则不会进行SNAT而是直接进行转发。

那么为什么会有这样的机制了,直接搜索snat相关的机制都是说能做源地址转发让终端上网之类的,没能解答我的疑问。

最终经过Google搜索iptables nat sessions找到一个论坛的问答解决了我的疑问。

题主正好提出了与我相同的疑问。


原文:https://unix.stackexchange.com/questions/484868/in-iptables-does-masquerade-match-only-on-new-connections-syn-packets