通过之前的学习,我们认识了防火墙的表、链结构,并学会了简单的编写防火墙的规则。Linux 防火墙在很多的时候承担着连接企业内、外网的重任,除了提供数据包过滤以外,还提供一些基本的网关应用。下面我们将了解防火墙中的SNAT 和DNAT策略。
SNAT(Source Network Address Translation,源地址转换)是Linux防火墙的一种地址转换操作,也是iptables命令中的一种数据包控制类型,其作用是根据特定的条件修改数据包的源IP地址。
局域网主机共享单个公网IP地址接入Internet(私有IP不能在Internet中正常路由)。
客户端往网关服务器发数据包,网关服务器将从客户端发送过来数据包的源IP地址由私网IP地址转换成公网IP地址进行转发,发送至需要访问的服务器。访问后,数据包返回往网关服务器,源IP地址会作为目的IP地址,目的IP地址会作为源IP地址进行传送,然后网关服务器会把从服务器返回来的数据包的目的IP地址由公网IP地址转换成私网IP地址进行返回到客户端。
注:SNAT的转换流程是从私网到公网,源IP地址改变,目标IP地址不变。
局域网各主机已正确设置IP地址、子网掩码、默认网关地址。
Linux网关开启IP路由转发。
临时打开
方式1:echo 1 > /proc/sys/net/ipv4/ip_forward
方式2:sysctl -w net.ipv4.ip_forward=1
永久打开
[root@localhost ~]# vim /etc/sysctl.conf
###将此行写入配置文件
net.ipv4.ip_forward = 1
###读取修改后的配置
[root@localhost ~]# sysctl -p
客户端(192.168.145.15)想要进入网关服务器的ens32端口(192.168.145.50),通过网关服务器SNAT进行IP地址转换,从ens33端口(12.0.0.50)发送给Web服务器(12.0.0.200)
客户端设置(Centos 7-1)
ip地址相关设置
###配置ip地址和网关
[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens32
ADDR=192.168.145.15
NETMASK=255.255.255.0
GATEWAY=192.168.145.50
[root@localhost ~]# systemctl restart network
[root@localhost ~]# ifconfig
ens32: flags=4163 mtu 1500
inet 192.168.145.15 netmask 255.255.255.0 broadcast 192.168.145.255
inet6 fe80::fd54:3fb4:558d:82fb prefixlen 64 scopeid 0x20
ether 00:0c:29:33:c5:93 txqueuelen 1000 (Ethernet)
RX packets 506452 bytes 704984469 (672.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 192066 bytes 12499794 (11.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
设置防火墙以及规则
###关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
setenforce: SELinux is disabled
###清除所有规则
[root@localhost ~]# iptables -F && iptables -t nat -F
网关服务器设置(Centos 7-2)
网关服务器需要设置两个网卡,所以在虚拟机上需要添加一个网络适配器,设置完重启后生效。
ip地址相关设置
[root@localhost ~]# cd /etc/sysconfig/network-scripts/
###修改ens33ip地址
[root@localhost network-scripts]# vim ifcfg-ens33
IPADDR=192.168.145.50
###复制ens33配置文件为ens36配置文件
[root@localhost network-scripts]# cp ifcfg-ens33 ifcfg-ens36
[root@localhost network-scripts]# ls
ifcfg-ens33 ifdown-post ifup-eth ifup-sit
ifcfg-ens36 ifdown-ppp ifup-ib ifup-Team
ifcfg-lo ifdown-routes ifup-ippp ifup-TeamPort
ifdown ifdown-sit ifup-ipv6 ifup-tunnel
ifdown-bnep ifdown-Team ifup-isdn ifup-wireless
ifdown-eth ifdown-TeamPort ifup-plip init.ipv6-global
ifdown-ib ifdown-tunnel ifup-plusb network-functions
ifdown-ippp ifup ifup-post network-functions-ipv6
ifdown-ipv6 ifup-aliases ifup-ppp
ifdown-isdn ifup-bnep ifup-routes
[root@localhost network-scripts]# vim ifcfg-ens36
###修改连接名称,可以没有
NAME=ens36
###网卡设备名称,必须要有
DEVICE=ens36
###删除UID标识,让系统自动分配
#UUID=b7f32ab4-a3b6-4b32-be62-812cb1a30c17
###修改ip地址
IPADDR=12.0.0.50
###重启网卡服务
[root@localhost network-scripts]# systemctl restart network
[root@localhost network-scripts]# ifconfig
ens33: flags=4163 mtu 1500
inet 192.168.145.50 netmask 255.255.255.0 broadcast 192.168.145.255
inet6 fe80::c8e2:a658:18d3:92cd prefixlen 64 scopeid 0x20
ether 00:0c:29:20:88:32 txqueuelen 1000 (Ethernet)
RX packets 383 bytes 52823 (51.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 210 bytes 24147 (23.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens36: flags=4163 mtu 1500
inet 12.0.0.50 netmask 255.0.0.0 broadcast 12.255.255.255
inet6 fe80::e7d:fb55:adfc:c796 prefixlen 64 scopeid 0x20
ether 00:0c:29:20:88:3c txqueuelen 1000 (Ethernet)
RX packets 352 bytes 36564 (35.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 115 bytes 13564 (13.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
设置防火墙以及规则
###关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
###将光盘挂载
[root@localhost ~]# mount /dev/sr0 /mnt
mount: /dev/sr0 写保护,将以只读方式挂载
###安装iptables防火墙相关服务
[root@localhost ~]# yum install -y iptables*
###启动iptables防火墙
[root@localhost ~]# systemctl start iptables.service
[root@localhost ~]# systemctl enable iptables.service
Created symlink from /etc/systemd/system/basic.target.wants/iptables.service to /usr/lib/systemd/system/iptables.service.
[root@localhost ~]# systemctl stop iptables.services
Failed to stop iptables.services.service: Unit iptables.services.service not loaded.
###清除所有规则
[root@localhost ~]# iptables -F && iptables -t nat -F
[root@localhost ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
###设置客户端只允许192.168.145.0网段主机通过的规则
[root@localhost ~]# iptables -t filter -A FORWARD -s 192.168.145.0/24 -j ACCEPT
[root@localhost ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 192.168.145.0/24 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
设置SNAT策略
###设置永久打开SNAT策略
[root@localhost ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
###设置路由转发功能
[root@localhost ~]# sysctl -p
net.ipv4.ip_forward = 1
###设置192.168.145.0网段的主机通过ens36网卡接口转换成12.0.0.50的IP地址
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.145.0/24 -o ens36 -j SNAT --to 12.0.0.50
[root@localhost ~]# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 192.168.145.0/24 0.0.0.0/0 to:12.0.0.50
Web服务器设置(Centos 7-3)
ip地址相关设置
####配置ip地址和网关
[root@localhost html]# vi /etc/sysconfig/network-scripts/ifcfg-ens32
IPADDR=12.0.0.200
NETMASK=255.255.255.0
GATEWAY=12.0.0.50
###重启网络服务
[root@localhost html]# systemctl restart network
[root@localhost html]# ifconfig
ens32: flags=4163 mtu 1500
inet 12.0.0.200 netmask 255.255.255.0 broadcast 12.0.0.255
inet6 fe80::f7ca:c46d:5b2c:93a6 prefixlen 64 scopeid 0x20
ether 00:0c:29:fd:72:ff txqueuelen 1000 (Ethernet)
RX packets 25672 bytes 34762940 (33.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11097 bytes 795061 (776.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
设置防火墙以及相关服务
###关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
###清除所有规则
[root@localhost ~]# iptables -F && iptables -t nat -F
###安装httpd服务
[root@localhost ~]# yum install -y httpd
###写数据在html中,为后面方便查看是否传输成功做判断
[root@localhost ~]# cd /var/www/html/
[root@localhost html]# ls
[root@localhost html]# echo "this is test web" > test.html
[root@localhost html]# cat test.html
this is test web
###启动httpd服务
[root@localhost html]# systemctl start httpd
测试实验结果
客户端访问服务端
服务端查看http日志
[root@localhost html]# cd /etc/httpd/logs/
[root@localhost logs]# ls
access_log error_log
###通过日志查看后面访问的源地址就是公网地址
[root@localhost logs]# grep 'test.html' access_log
192.168.145.45 - - [20/May/2023:15:48:56 +0800] "GET /test.html HTTP/1.1" 200 17 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
192.168.145.45 - - [20/May/2023:15:50:51 +0800] "GET /test.html HTTP/1.1" 200 17 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
192.168.145.45 - - [20/May/2023:15:51:16 +0800] "GET /test.html HTTP/1.1" 304 - "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
192.168.145.15 - - [20/May/2023:22:22:55 +0800] "GET /test.html HTTP/1.1" 200 17 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
12.0.0.50 - - [20/May/2023:22:29:27 +0800] "GET /test.html HTTP/1.1" 200 17 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
12.0.0.50 - - [20/May/2023:22:30:40 +0800] "GET /test.html HTTP/1.1" 200 17 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
一个IP地址做SNAT转换,一般可以让内网 100到200 台主机实现上网。
DNAT 的全称为Destination Network Address Translation,意思是目的地址转换,常用于防火墙中。
目的地址转换的作用是将一组本地内部的地址映射到一组全球地址。通常来说,合法地址的数量比起本地内部的地址数量来要少得多。RFC1918中的地址保留可以用地址重叠的方式来达到。当一个内部主机第一次放出的数据包通过防火墙时,动态NAT的实现方式与静态NAT相同,然后这次NAT就以表的形式保留在防火墙中。
在Internet中发布位于局域网内的服务器。
外网的客户端往网关服务器发数据包,网关服务器将从客户端发送过来数据包由公网的IP地址和端口转换成私网的IP地址和端口进行转发,然后网关服务器在将私网IP地址发送给需要访问的内网服务器。访问后,内网服务器发送数据包给网关服务器,网关服务器会将应答响应的数据包的源地址由私网的IP地址和端口转换成公网的IP地址和端口。
注:DNAT的转换流程是从公网到私网,源IP地址不变,目标IP地址改变。
局域网的服务器能够访问Internet
网关的外网地址有正确的DNS解析记录
Linux网关开启IP路由转发
DNAT转换1:发布内网的Web服务
#把从ens33进来的要访问web服务的数据包目的地址转换为 192.168.80.10
iptables -t nat -A PREROUTING -i ens33 -d 12.0.0.1 -p tcp --dport 80 -j DNAT --to 192.168.80.10
或
iptables -t nat -A PREROUTING -i ens33 -d 12.0.0.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.80.10
入站 外网网卡 外网IP 内网服务器IP
iptables -t nat -A PREROUTING -i ens33 -p tcp --dport 80 -j DNAT --to 192.168.80.10-192.168.80.20
DNAT转换2:发布时修改目标端口
#发布局域网内部的OpenSSH服务器,外网主机需使用250端口进行连接
iptables -t nat -A PREROUTING -i ens33 -d 12.0.0.1 -p tcp --dport 250 -j DNAT --to 192.168.80.10:22
注意:使用DNAT时,同时还有配合SNAT使用,才能实现响应数据包的正确返回。
内网服务器设置(Centos 7-1)
IP地址设置
[root@localhost ~]# cd /etc/sysconfig/nework-scripts/
[root@localhost network-scripts]# vim ifcfg-ens32
IPADDR=192.168.145.15
NETMASK=255.255.255.0
GATEWAY=192.168.145.50
###重启网卡
[root@localhost network-scripts]# systemctl restart network
防火墙设置以及服务设置
###关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
setenforce: SELinux is disabled
[root@localhost ~]# mount /dev/sr0 /mnt
mount: /dev/sr0 写保护,将以只读方式挂载
###安装httpd服务
[root@localhost ~]# yum install -y httpd
###启动httpd服务
[root@localhost ~]# systemctl start httpd
###写数据在html中,为后面方便查看是否传输成功做判断
[root@localhost ~]# cd /var/www/html/
[root@localhost html]# echo 'hello world' > test.html
网关服务器设置(Centos 7-2)
网关服务器需要设置两个网卡,所以在虚拟机上需要添加一个网络适配器,设置完重启后生效。
IP地址设置
###设置ens33接口
[root@localhost ~]# cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts]# vim ifcfg-ens33
IPADDR=192.168.145.50
NETMASK=255.255.255.0
###复制ens33配置文件为ens36配置文件
[root@localhost network-scripts]# cp ifcfg-ens33 ifcfg-ens36
[root@localhost network-scripts]# vim ifcfg-ens36
###修改连接名称,可以没有
NAME=ens36
###网卡设备名称,必须要有
DEVICE=ens36
###删除UID标识,让系统自动分配
#UUID=b7f32ab4-a3b6-4b32-be62-812cb1a30c17
###修改ip地址
IPADDR=12.0.0.50
NETMASK=255.255.255.0
###重启网卡
[root@localhost network-scripts]# systemctl restart network
[root@localhost network-scripts]# ifconfig
ens33: flags=4163 mtu 1500
inet 192.168.145.50 netmask 255.255.255.0 broadcast 192.168.145.255
inet6 fe80::c8e2:a658:18d3:92cd prefixlen 64 scopeid 0x20
ether 00:0c:29:20:88:32 txqueuelen 1000 (Ethernet)
RX packets 286 bytes 37887 (36.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 291 bytes 32263 (31.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens36: flags=4163 mtu 1500
inet 12.0.0.50 netmask 255.255.255.0 broadcast 12.0.0.255
inet6 fe80::20c:29ff:fe20:883c prefixlen 64 scopeid 0x20
ether 00:0c:29:20:88:3c txqueuelen 1000 (Ethernet)
RX packets 133 bytes 10306 (10.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 100 bytes 13875 (13.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
防火墙设置以及规则
###关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
setenforce: SELinux is disabled
###清楚所有规则
[root@localhost ~]# iptables -F && iptables -t nat -F
DNA策略设置
###设置永久打开SNAT策略
[root@localhost ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
###加载SNAT策略
[root@localhost ~]# sysctl -p
net.ipv4.ip_forward = 1
#添加DNAT策略,修改入站的目的地址
[root@localhost ~]# iptables -t nat -A PREROUTING -i ens33 -d 12.0.0.30 -p tcp --dport 8080 -j DNAT --to 192.168.145.15:80
[root@localhost ~]# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 12.0.0.30 tcp dpt:8080 to:192.168.145.20:80
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
设置SNAT策略
#添加SNAT策略,修改出站的源地址
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.145.0/24 -o ens33 -j SNAT --to 12.0.0.50
[root@localhost ~]# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 12.0.0.50 tcp dpt:8080 to:192.168.145.20:80
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 192.168.145.0/24 0.0.0.0/0 to:12.0.0.30
设置端口映射
#将192.168.145.15:22的IP地址和端口号映射为12.0.0.50:2345
[root@localhost ~]# iptables -t nat -A PREROUTING -i ens33 -d 12.0.0.50 -p tcp --dport 2345 -j DNAT --to 192.168.145.15:22
[root@localhost ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 12.0.0.50 tcp dpt:8080 to:192.168.80.20:80
DNAT tcp -- 0.0.0.0/0 12.0.0.50 tcp dpt:2345 to:192.168.145.15:22
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 192.168.80.0/24 0.0.0.0/0 to:12.0.0.30
外网客户端设置(Centos 7-3)
IP地址设置
[root@localhost ~]# cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts]# vim ifcfg-ens32
IPADDR=12.0.0.200
NETMASK=255.255.255.0
GATEWAY=192.168.145.50
[root@localhost network-scripts]# systemctl restart network
防火墙设置
###关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
setenforce: SELinux is disabled
测试实验结果
客户端访问服务端
主机型防火墙 主要使用 INPUT、OUTPUT 链,设置规则时一般要详细的指定到端口
网络型防火墙 主要使用 FORWARD 链,设置规则时很少去指定到端口,一般指定到IP地址或者到网段即可。
根据系统类型不同,可以分为windows系统的抓包和linux系统的抓包两种方式。在windows系统可以通过wireshark软件进行抓包;linux系统可以通过tcpdump命令进行抓包。
tcpdump tcp -i ens33 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
各个字段的含义:
tcp
:ip iocmp arp rarp和 tcp、udp、icmp这些协议选项等都要放到第一个参数的位置,用来过滤数据包的类型。
-i ens33
:只抓经过接口lens33的包。
-t
:不显示时间戳。
-s 0
:抓取数据包时默认抓取长度为68字节。加上此选项可以抓到完整的数据包。
-c 100
:只抓取100个数据包
dst port ! 22
:不抓取目标端口是22的数据包
src net 192.168.1.0/24
:数据包的源网络地址为192.168.1.0/24。
-w ./target.cap
:保存成cap文件,方便用ethereal (即wireshark)分析。
与此同时服务器进行tcpdump抓包
[root@localhost ~]# tcpdump -i ens32 -s 0 net 12.0.0.0/24 -w /opt/ens32.cap
tcpdump: listening on ens32, link-type EN10MB (Ethernet), capture size 262144 bytes
^C140 packets captured
140 packets received by filter
0 packets dropped by kernel
###将抓取的包拖到windows系统下
[root@localhost opt]# sz ens32.cap
最后通过wireshark软件进行查看
###导出(备份)所有表的规则
iptables-save > /opt/ipt.txt
###导入(还原)规则
iptables-restore < /opt/ipt.txt