Linux主机上通过iptables实现NAT功能

     

实验:如下模型,node1为内网主机,IP地址为192.168.10.2node3为外网主机,IP地址为10.72.37.177(假设此地址为公网地址),node3上提供web serverFTP Server的功能;内网主机node2主机有2块网卡,地址分别为eth0:192.168.10.1eth2:10.72.37.91(假设此地址为公网地址);

现要求在node2上通过iptables配置实现SNAT功能,并做如下限制:

1、node1可以访问node3提供的web服务和ftp服务

2node1只可以ping连接、ssh连接node3

                            

SNAT实现的过程:

node1node2都是内网主机处于同一网段,所以node1是默认直接可以pingnode2主机上eth1的地址192.168.10.1;将node1主机的网关指向192.168.10.1后,node1就可以直接pingnode2eth0上的外网地址10.72.37.91

但此时内网主机node1肯定是无法ping通外网主机node3的地址,此时开启node2主机的路由转发功能,即可实现将node1的请求报文,经由node2转发送到node3主机上,但是node3响应此报文时,发现源地址为192.168.10.1,与自己不在同一网段内,便会交由网关去转发,而node3的网关默认也是无法识别此网络,所以响应报文也就无法返回到node2

所以即可以配置,node2node1的请求报文转发出去之前,将请求报文的源地址由192.168.10.2转换为10.72.37.91后再送至node3主机上,此过程中node2同时会自动生成一张NAT会话表,记录下经由node2被转发的每一条记录;

node3封装响应报文时,发现源地址为10.72.37.91,所以响应报文的目标地址就会是10.72.37.91,响应报文即会被返回给node2,此时node2上就会查询NAT会话表,自动再做目标地址转换,将响应报文送至node1,此即实现了内网主机node1与外网主机node3通信了;iptablesSNAT即是实现此功能;

此过程中报文在node1node2node3之间传输路径如下图:

一个请求报文经由node2主机路由判断后,需要被转发出去的话,此请求报文则会经过node2主机上netfilter的链的顺序为PREROUTING--> FORWARD-->OUTROUTING,所以SNAT的规则需配置在OUTROUTING链上,而filter的规则就需要在FORWARD链上配置了(此路径中只有在FORWARD链上有filter功能表,PREROUTINGOUTROUTING链上不做filter

 

总结:为了实现node1可以与node3通信需做的配置有:

1node1主机的默认网关指向node2eth1的地址

1node2主机上的开启路由转发功能

2node2主机上配置SNAT功能

 

配置过程:

node1上:

#ping 192.168.10.1                                          ##是可以直接ping通的

#route add default gw192.168.10.1              ##添加路由指向192.168.10.1

#ping 10.72.37.91                                             ##即可pingnode2主机上的另一个地址

 

node2上:

#sysctl -wnet.ipv4.ip_forward=1                    ##开启node2主机上的路由转发功能

 

node1上:

#ping 10.72.37.177                                            ##此时,node1上暂且是无法pingnode3的,但是此时ping的请求包是已经可以发送到node3

 

node3上:

#iptables -t filter -A INPUT -j LOG                  ##node3主机的INPUT链上添加LOG功能

#tail /var/log/messages                                   ##即可看到,已记录到来自192.168.10.2node1ICMP请求报文

… … kernel: IN=eth0OUT= MAC=1c:6f:65:03:1b:9a:00:0c:29:fa:ea:2d:08:00 SRC=192.168.10.2DST=10.72.37.177 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=ICMP TYPE=8CODE=0 ID=4876 SEQ=9

         ##如果此时在OUTPUT链上也记录LOG的话,也是可以看到SRC=10.72.37.177DST=192.168.10.2的响应报文,只不过是这个响应报文最终无法送达node1

 

node2

#iptables -t nat -APOSTROUTING -s 192.168.10.0/24 -j SNAT --to-source 10.72.37.91

##node2主机上的的POSTROUTING链上向NAT表中添加,定义来自192.168.10.0的主机,无论是使用何种协议,无论访问哪个网络,通通代理出去,将源地址转换成10.72.37.91

#iptables -t nat -L POSTROUTING -nv            ##nat表的POSTROUTING链上即可看到我们添加的规则

 

    此时,node1即可以pingnode3,而在node3主机上的log中可以看到ICMP的请求报文SRC=10.72.37.91 DST=10.72.37.177和响应报文SRC=10.72.37.177DST=10.72.37.91;注意此时的与node3通信的IP地址已被SANT转换为10.72.37.91了;

 

node1

#curl -I http://10.72.37.177                ##测试连接node3web服务

#tail /var/log/nginx/access.log         ##node3上查看访问日志中,客户端源地址的已是被转换后的10.72.37.91

 

         按照要求node1只可以向node3发起pingshhweb访问请求,所以在node2上的filter表的FORWARD链上添加如下规则:

#iptables -t filter -P FORWARD DROP
#iptables -t filter -I FORWARD 1 -s192.168.10.0/24 -p icmp --icmp-type 8 -j ACCEPT
        ##转发来自192.168.10.0/24的ICMP协议的请求报文
#iptables -t filter -I FORWARD 1 -s10.72.37.0/24 -p icmp --icmp-type 0 -j ACCEPT
        ##转发来自10.72.37.0/24的ICMP协议的响应报文
#iptables -t filter-A FORWAORD -s 192.168.10.0/24 -p tcp -m state --state NEW -m multiport --destination-ports 21,22,80 -j ACCEPT
        ##转发来自192.168.10.0/24的状态为NEW,访问ftp,ssh,web的请求
#iptables -t filter -A FORWARD -m state--state ESTABLISHED,RELATED -j ACCEPT 
         ##转发所有状态为ESTABLISHED和RELATED(for ftp)状态的请求

 

    node1通过node3上的21端口和ftp server建立命令连接后,因为ftp server默认是工作在被动模式,所以node1还需访问node3上的一个大于1024的随机端口来建立数据连接,即需要node2上将所有所有大于1024的端口都转发至node3;但是本实验又要求只允许转发21,22,80端口;

    此时要求node3主机上需已装载内核模块nf_contrack_ftp这个模块可以监控ftp控制流,能够事先知道将要建立的ftp数据连接所使用的端口,从而可以允许相应的数据包通过,即使防火墙没有开放这个端口:

#modprobe nf_contrack_ftp          ##手动装载此内核模块

#lsmod | grep ftp                             ##此时即可看到已装载

    ##或者写到配置文件/etc/sysconfig/iptables-config,即可不需每次去手动装载,即使重启后也会自动装载,添加一行:IPTABLES_MOUDLES=”nf_contrack_ftp”

 

    假若node3没有装载内核模块nf_conntrack_ftp,在node1上连接node3上的ftp服务时,就会有如下报错信息:无法建立数据连接到(10.72.37.177) 端口 29814

lftp [email protected]:~> debug

lftp [email protected]:~> ls

---- 正在连接到 10.72.37.177(10.72.37.177) 端口 21

<--- 220 (vsFTPd 2.2.2)

---> FEAT

<--- 211-Features:

<--- EPRT

<--- EPSV

<--- MDTM

<--- PASV

<--- REST STREAM

<--- SIZE

<--- TVFS

<--- UTF8

<--- 211 End

---> OPTS UTF8 ON

<--- 200 Always in UTF8 mode.

---> USER user2

<--- 331 Please specify the password.

---> PASS XXXX

<--- 230 Login successful.     

---> PASV

<--- 227 Entering Passive Mode(10,72,37,177,116,118).

---- 正在建立数据连接到(10.72.37.177) 端口 29814

`ls‘ at 0 [正在建立数据连接...]

...

    以上,即基于node2主机上的FORWARD链实现了网络防火墙,内网主机通过node2访问外网时,通过FORWARD链实现了访问控制。

 

本文出自 “斑马Linux” 博客,请务必保留此出处http://zebralinux.blog.51cto.com/8627088/1560314

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。