# 利用防火墙iptables实现端口转发 ## 1. 前置知识 `端口转发条件:机器的root权限` `远程转发的时候,机器需要有外网ip` ### 1.1 iptables 下图简要描述了网络数据包通过 iptables 的过程:  iptables有很多表:  具体区别如下:  默认情况下修改的是filter表,如果我们想修改其他表,必须加上参数-t,由于我们今天讲的是端口转发,因此修改的会是nat表。 nat表由postrouting,output,prerouting三条链组成,我们说是修改nat表,其实修改的是链,链的具体属性如下: ```bash # PREROUTING链 # 的作用是在包刚刚到达防火墙时改变它的目的地址,是从外部连接过来时的转发 # OUTPUT链改 # 变本地产生的包的目的地址,是本机连接时的转发 # POSTROUTING链 # 在包就要离开防火墙之前改变其源地址 ``` ## 2. 实现 1.修改配置文件,使iptables允许ipv4转发: ```bash vim /etc/sysctl.conf #可以直接进文件修改 sysctl -w net.ipv4.ip_forward=1 #也可以用这条命令直接修改 sysctl -p #查看修改结果 ```   ### 2.1 本地端口转发 将`外网访问`本地的4444端口的流量转发到本地的22端口: ```bash iptables -t nat -A PREROUTING -p tcp --dport 4444 -j REDIRECT --to-ports 22 ``` 将`本地访问`本地的4444端口的流量转发到本地的22端口: ```bash iptables -t nat -A OUTPUT -p tcp --dport 4444 -j REDIRECT --to-ports 22 ```  ### 2.2 分流 通过PREROUTING链,将172.16.250.1网段访问4444端口的包转发到本机22端口,其他网段则正常访问4444端口,MASQUERADE类似于SNAT,只是不用写源地址。 ```bash iptables -t nat -A PREROUTING --source 172.16.250.1 -p tcp --dport 4444 -j DNAT --to-destination 172.16.250.3:22 iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE iptables -t nat -A POSTROUTING --dst 172.16.250.3 -p tcp --dport 22 -j MASQUERADE ``` ### 2.3 远程端口转发 `同样也需要改配置文件,使iptables允许ipv4转发` 假如我们想使用192.168.171.139:5555去访问192.168.171.1:9999端口,那么需要在192.168.171.139的机器上执行下面的命令: ```bash # 清空nat表 #iptables -F -t nat # 当有 TCP 数据包发往 192.168.171.139 的 5555 端口时,将其目标地址和端口转换为 192.168.171.1:9999 iptables -t nat -A PREROUTING --dst 192.168.171.139 -p tcp --dport 5555 -j DNAT --to-destination 192.168.171.1:9999 # 当数据包从本地网络发往 192.168.171.1 的 9999 端口时,将其源地址转换为 192.168.171.139 iptables -t nat -A POSTROUTING --dst 192.168.171.1 -p tcp --dport 9999 -j SNAT --to-source 192.168.171.139 ``` ### 2.4案例解释 #### 2.4.1问题1 > A主机192.168.10.1,B主机192.168.10.142,C主机192.168.10.6 > 实现A主机访问B的4444端口转发到C主机的6666端口 > iptables -t nat -A PREROUTING --dst 192.168.10.142 -p tcp --dport 4444 -j DNAT --to-destination 192.168.10.6:6666 > 这样主机C收到的请求HOST为主机A还是主机B #### 2.4.2解答1 ```bash #C 主机收到的请求中 Host 为 A 主机的 IP 地址,即 192.168.10.1。 执行的命令`iptables -t nat -A PREROUTING --dst 192.168.10.142 -p tcp --dport 4444 -j DNAT --to-destination 192.168.10.6:6666`,是在进行网络地址转换(DNAT)。这条规则的作用是:当有 TCP 数据包发往 B 主机(192.168.10.142)的 4444 端口时,将其目标地址转换为 C 主机(192.168.10.6)的 6666 端口。 # 从 C 主机的角度来看,它接收到的数据包的源地址仍然是 A 主机的地址(192.168.10.1),就好像是 A 主机直接与它进行通信一样。而 B 主机在这个过程中只是起到了一个“转接”的作用,数据包实际上并没有真正到达 B 主机。 ``` #### 2.4.3问题2 > 如果再加一句 > iptables -t nat -A POSTROUTING --dst 192.168.10.6 -p tcp --dport 6666 -j SNAT --to-source 192.168.10.142 > 这样主机C收到的请求HOST为主机A还是主机B #### 2.4.4解答 ```bash # C 主机收到的请求中 Host 为 B 主机的 IP 地址,即 192.168.10.142。 第一条命令`iptables -t nat -A PREROUTING --dst 192.168.10.142 -p tcp --dport 4444 -j DNAT --to-destination 192.168.10.6:6666`进行了目的网络地址转换(DNAT),将发往 B 主机 192.168.10.142 的 4444 端口的数据包的目标地址转换为 C 主机的 192.168.10.6:6666。 第二条命令`iptables -t nat -A POSTROUTING --dst 192.168.10.6 -p tcp --dport 6666 -j SNAT --to-source 192.168.10.142`进行了源网络地址转换(SNAT),将从 C 主机的 6666 端口发出的数据包的源地址转换为 192.168.10.142(B 主机的地址)。 # 这样,当 A 主机访问 B 主机的 4444 端口时,数据包实际上被转发到了 C 主机的 6666 端口,而 C 主机回复的数据包经过源地址转换后,其源地址变成了 B 主机的地址 192.168.10.142,所以从 A 主机的角度来看,就像是在与 B 主机进行通信。 ``` ## 3.删除规则 > 查询列表后,-D 删除指定表的指定链上num的规则 ```bash iptables -t nat -nL --line #查看已有规则 iptables -t nat -D PREROUTING 2 # 删除2号规则 iptables -F -t nat #删除NAT表所有规则 ```  ## 4.关闭转发 ```bash service iptables stop ``` 参考文章 ---- - [iptables](https://wiki.archlinux.org/title/iptables_%28%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%29) - [内网穿透——iptables端口转发](https://mp.weixin.qq.com/s/QOfORsSIcxuRXFj1xkUFcA)