iptables之snat与dnat的经典应用

1、snat与dnat概述前端

1)snat概述node

何为snat?snat为源地址转换,它的典型应用环境为局域网主机共享单个公网IP地址上网,下面来看一下snat的工做原理web

在局域网当中,有多个PC使用ADSL路由器共享上网、每一个PC都配置了内网IP、当PC访问公网的时候,防火墙会根据咱们定义的规则将数据包中的源地址修改成防火墙外网接口的那个公网地址服务器

当公网的Web服务器接收到访问请求的时候,它记录下来的并非PC的内网地址,而是路由器的那个公网地址ssh

由于服务器所收到的数据包里面的源地址,已经被替换了,因此这就叫作SNAT (基于源地址转换)这样不只可让局域网中的客户端访问外网,同时也起到了必定的保护做用curl

2)dnat概述tcp

何为dnat?dnat为目标地址转换,它的典型应用环境为在互联网中发布位于企业局域网中的服务器,下面来看一下dnat的工做原理post

位于IDC中的一台Web服务器只配置了一个私有地址、在前端有一个防火墙或者NAT设备 ,当公网用户访问的时候,发出一个数据包测试

这个数据包里面写的目标地址为防火墙或者NAT设备的那个公网地址,当数据包到达防火墙或者NAT设备以后,它将会根据咱们定义的规则将这个数据包的目标地址给更改url

即将目标地址改成Web服务器的私有地址,而后再把这个数据包发送到内网的Web服务器、这样这个数据包就穿透了防火墙或NAT设备,从公网IP地址变成了一个对内网地址的访问了,这就是DNAT

2、snat与dnat应用

1)snat应用

 既然snat是为了解决公网地址不够而诞生的,那下面咱们就使用一例snat让局域网中的主机经过防火墙访问外网吧

一、环境说明

node1-做为防火墙
内网IP地址为:10.2.3.11
外网IP地址为:123.23.36.11

node2-做为内网客户端
内网IP地址为:10.2.3.12
默认网关地址为:10.2.3.11

web-做为公网的Web服务器
外网IP地址为:123.23.36.12

二、实验目标

让没有公网地址的局域网客户端,经过防火墙的公网地址访问外网
有时候服务器的带宽可能不够,因此咱们还要限制某些用户的上网行为

三、防火墙IP地址

[root@node1 ~]# ifconfig 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.2.3.11  netmask 255.255.255.0  broadcast 10.2.3.255
        inet6 fe80::20c:29ff:fe44:eff3  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:44:ef:f3  txqueuelen 1000  (Ethernet)
        RX packets 411  bytes 37244 (36.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 352  bytes 51581 (50.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 123.23.36.11  netmask 255.255.255.0  broadcast 123.23.36.255
        inet6 fe80::250:56ff:fe29:6e2b  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:29:6e:2b  txqueuelen 1000  (Ethernet)
        RX packets 21  bytes 2394 (2.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 18  bytes 2304 (2.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

四、公网Web服务器IP地址

[root@web ~]# ifconfig ens37
ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 123.23.36.12  netmask 255.255.255.0  broadcast 123.23.36.255
        inet6 fe80::250:56ff:fe26:e3  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:26:00:e3  txqueuelen 1000  (Ethernet)
        RX packets 13  bytes 1346 (1.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 25  bytes 2582 (2.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

五、在防火墙上打开内核转发

[root@node1 ~]# sysctl -p
net.ipv4.ip_forward = 1

六、将局域网客户端的默认网关指向防火墙的内网地址

[root@node2 ~]# ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.2.3.12  netmask 255.255.255.0  broadcast 10.2.3.255
        inet6 fe80::250:56ff:fe24:6bdf  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:24:6b:df  txqueuelen 1000  (Ethernet)
        RX packets 338  bytes 29396 (28.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 289  bytes 44907 (43.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@node2 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 | grep GATEWAY
GATEWAY="10.2.3.11"

[root@node2 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.2.3.11       0.0.0.0         UG    100    0        0 ens33
10.2.3.0        0.0.0.0         255.255.255.0   U     100    0        0 ens33

七、在没作snat以前访问Web服务器

[root@node2 ~]# curl 123.23.36.12
curl: (7) Failed connect to 123.23.36.12:80; 拒绝链接

八、编写防火墙规则

#若是公网地址非固定,则使用以下命令
[root@node1 ~]# iptables -t nat -A POSTROUTING -s 10.2.3.0/24 -o ens37 -j MASQUERADE

#若是公网地hi为固定,则使用以下命令
[root@node1 ~]# iptables -t nat -A POSTROUTING -s 10.2.3.0/24 -o ens37 -j SNAT --to-source 123.23.36.11
[root@node1 ~]# iptables -t nat -L -n
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  --  10.2.3.0/24          0.0.0.0/0            to:123.23.36.11

九、作完snat以后访问Web服务器

#在局域网客户端访问公网的Web服务器
[root@node2 ~]# curl 123.23.36.12
www.test.com
[root@node2 ~]# curl 123.23.36.12
www.test.com
[root@node2 ~]# curl 123.23.36.12
www.test.com

#在公网的Web服务器查看访问日志,能够看见是防火墙外部接口的公网地址
[root@web ~]# tail -f /var/log/httpd/access_log 
123.23.36.11 - - [04/Mar/2020:11:17:23 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
123.23.36.11 - - [04/Mar/2020:11:17:28 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
123.23.36.11 - - [04/Mar/2020:11:17:29 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"

十、为FORWARD链设置默认规则

提示:这样作的初衷就是为了更精准的控制内网客户端的上网行为

[root@node1 ~]# iptables -P FORWARD DROP

十一、再来访问Web服务器,能够看见访问失败

[root@node2 ~]# curl 123.23.36.12
curl: (7) Failed connect to 123.23.36.12:80; 链接超时

十二、在FORWARD链添加规则,容许10.2.3.12访问外网

#容许10.2.3.12这个客户端访问外网
[root@node1 ~]# iptables -t filter -I FORWARD -s 10.2.3.12 -j ACCEPT

#容许任何地址到任何地址的已创建连接和相关连接的数据包经过
[root@node1 ~]# iptables -t filter -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

#查看添加的规则
[root@node1 ~]# iptables -t filter -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
ACCEPT     all  --  10.2.3.12            0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

1三、添加规则以后,再来访问,能够看见访问成功

#在客户端访问Web服务器
[root@node2 ~]# curl 123.23.36.12
www.test.com

#在Web服务器上查看访问日志,即最后一条日志
[root@web ~]# tail -f /var/log/httpd/access_log 

123.23.36.11 - - [04/Mar/2020:11:17:23 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
123.23.36.11 - - [04/Mar/2020:11:17:28 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
123.23.36.11 - - [04/Mar/2020:11:17:29 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"

123.23.36.11 - - [04/Mar/2020:11:21:07 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"

123.23.36.11 - - [04/Mar/2020:11:33:30 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"

2)dnat应用

 既然dnat是为了解决公网用户不能直接访问内部服务器而出现的,那下面咱们就使用一例dnat将内网的Web服务发布出去同时映射SSH的22号端口,以供公网用户访问吧

一、环境说明

node1-做为防火墙
内网IP地址为:10.2.3.11
外网IP地址为:123.23.36.11
 
node2-做为内网Web服务器
内网IP地址为:10.2.3.12
 
internet-做为公网的Web服务器
外网IP地址为:123.23.36.12

二、实验目标

让互联网用户能够经过防火墙的公网地址访问位于IDC内部的Web服务器
同时对SSH作端口映射,让互联网用户经过链接防火墙公网地址的某个端口,就将请求转发到内部服务器的22号端口

三、在防火墙上打开内核转发

[root@node1 ~]# sysctl -p
net.ipv4.ip_forward = 1

四、编写防火墙规则

[root@node1 ~]# iptables -t nat -A PREROUTING -d 123.23.36.11 -p tcp --dport 80 -j DNAT --to-destination 10.2.3.12:80
[root@node1 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            123.23.36.11         tcp dpt:80 to:10.2.3.12:80

规则已经编写完成,如今就剩下访问验证了,那么,能访问吗? 能吗? 答案确定是不能,那为何不能?又是哪一个环节出了问题? 下面咱们来进行分析

不能访问,有两种状况:

其一是咱们在filter表的forward链上作了限制,由于我这是新环境,因此没有,那就能够排除这点

其二是咱们作完目标地址转换以后,没有作源地址转换,又或者是没将内网服务器的网关设置为防火墙的地址

如今排除了第一点,咱们来重点说一下第二点,你们能够想象一下,在没有作SNAT的状况下,若是咱们想上网,但却不想设置网关,你能出去吗?不能

同理,若是内网的Web服务器没有设置正确的网关,那么在作好目标地址转换以后, 内网的Web服务器确实会,收到公网用户的请求,可是当它回去的时候,殊不知道如何回去

由于咱们既没有在防火墙上作源地址转换,也没有给内网的Web服务器设置网关,因此在访问的时候,就出现了过得来回不去的状况,那这个时候该怎么办?两个办法, 以下所示:

第一种办法:在内部的Web服务器上,将网关指向防火墙的内部地址

[root@node2 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 | grep GATEWAY
GATEWAY="10.2.3.11"

第二种办法:在防火墙上,再来一次源地址转换,这样就至关于设置了网关 

[root@node1 ~]# iptables -t nat -A POSTROUTING -d 10.2.3.12 -p tcp --dport 80 -j SNAT --to-source 10.2.3.11
[root@node1 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            123.23.36.11         tcp dpt:80 to:10.2.3.12: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       tcp  --  0.0.0.0/0            10.2.3.12            tcp dpt:80 to:10.2.3.11

在这里,我本身使用的是第二种办法,通过测试以后,能够正常访问,但咱们先来聊一下数据包从外网进来的流程,结果到后面再说

实验环境的IP地址在上面我已经写清楚了,因此下面咱们来看一下流程
首先互联网的用户访问个人web服务器,可是web服务器位于内网,没办法直接给外部用户访问,然而作了目标地址转换,因此这个时候就是(123.23.36.12:随机端口--->123.23.3.11:80)
在进入filter表的prerouting链的时候,忽然发现一条名为:iptables -t nat -A PREROUTING -d 123.23.36.11 -p tcp --dport 80 -j DNAT --to-destination 10.2.3.12:80,的规则
嗯哼?这不是将访问我80端口的请求转发给10.2.3.12:80吗?对,没错,既然你符合我这个规则,那我就更改你的目标地址,因此这个时候就变成了(123.23.36.12:随机端口--->10.2.3.12:80)
其实这个时候已经能够正常访问了,可是它迷路了,由于没有给它作源地址转换,也没有在内部服务器设置网关,因此它不知道怎么回去
如今咱们假设已经作了源地址转换,加上咱们在filter表的forward上没作限制,因此这个时候就来到了postrouting链
进入postrouting链以后,忽然发现一条名为:iptables -t nat -A POSTROUTING -d 10.2.3.12 -p tcp --dport 80 -j SNAT --to-source 10.2.3.11,的规则
这个规则也就是至关于设置了网关让10.2.3.11回应同样,既然你符合个人条件,那么我就更改你的源地址,这个时候就变成了(10.2.3.12:随机--->10.2.3.11:80)
当上面的流程正常走完之后,数据包便可正常出去并回应给互联网的客户端了,在这两次变化的过程中,都会记录于Linux的ip_conntrack
当后面再有相同的请求时,它会发现是防火墙的内部地址在请求,因此这个时候就无须再找网关了,直接把数据返回给它了
当防火墙或者NAT设备收到返回的数据包之后,它便会根据ip_conntrack表中的条目进行转换,当转换完成之后,就把数据包返回给用户了

 五、使用公网地址访问内部Web服务器验证DNAT的应用

#公网用户访问Web服务
[root@internet ~]# curl 123.23.36.11
www.node2.com
[root@internet ~]# curl 123.23.36.11
www.node2.com
[root@internet ~]# curl 123.23.36.11
www.node2.com

#在内部Web服务器上查看,能够看见它的请求地址为防火墙的内部地址
[root@node2 ~]# tail -f /var/log/httpd/access_log 
10.2.3.11 - - [04/Mar/2020:15:20:49 +0800] "GET / HTTP/1.1" 200 14 "-" "curl/7.29.0"
10.2.3.11 - - [04/Mar/2020:15:20:50 +0800] "GET / HTTP/1.1" 200 14 "-" "curl/7.29.0"
10.2.3.11 - - [04/Mar/2020:15:20:50 +0800] "GET / HTTP/1.1" 200 14 "-" "curl/7.29.0"

六、将作SNAT的方式换位设置网关

提示:为何要这样呢?由于作SNAT看不到外部用户的真实地址,在日志中所见的是防火墙的内部地址在请求

#在防火墙上把SNAT删除
[root@node1 ~]# iptables -t nat -D POSTROUTING 1
[root@node1 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            123.23.36.11         tcp dpt:80 to:10.2.3.12: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

#将内部Web服务器的网关指向防火墙的内部地址
[root@node2 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 | grep GATEWAY
GATEWAY="10.2.3.11"

七、再次测试访问Web服务器

#公网用户访问Web服务
[root@internet ~]# curl 123.23.36.11
www.node2.com
[root@internet ~]# curl 123.23.36.11
www.node2.com
[root@internet ~]# curl 123.23.36.11
www.node2.com

#在内部Web服务器上查看,能够看见它的请求地址为外部用户的公网地址
[root@node2 ~]# tail -f /var/log/httpd/access_log 
123.23.36.12 - - [04/Mar/2020:15:28:18 +0800] "GET / HTTP/1.1" 200 14 "-" "curl/7.29.0"
123.23.36.12 - - [04/Mar/2020:15:28:18 +0800] "GET / HTTP/1.1" 200 14 "-" "curl/7.29.0"
123.23.36.12 - - [04/Mar/2020:15:28:19 +0800] "GET / HTTP/1.1" 200 14 "-" "curl/7.29.0"

 八、咱们最后再来一例,这也是比较经常使用的,那就是把SSH发布出去

#编写规则,和上面那个同样,要么作SNAT要么设置网关,这里我作的SNAT
[root@node1 ~]# iptables -t nat -A PREROUTING -d 123.23.36.11 -p tcp --dport 123 -j DNAT --to-destination 10.2.3.12:22
[root@node1 ~]# iptables -t nat -A POSTROUTING -d 10.2.3.12 -p tcp --dport 22 -j SNAT --to-source 10.2.3.11
[root@node1 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            123.23.36.11         tcp dpt:80 to:10.2.3.12:80
DNAT       tcp  --  0.0.0.0/0            123.23.36.11         tcp dpt:123 to:10.2.3.12: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       tcp  --  0.0.0.0/0            10.2.3.12            tcp dpt:22 to:10.2.3.11

#在外网的客户端测试链接,能够看见已经正常连上node2这台服务器
[root@internet ~]# ssh -p 123.23.36.11
The authenticity of host '[123.23.36.11]:123 ([123.23.36.11]:123)' cat't be established,
ECDSA key fingerprint is SHA256:HIcNf2L6t6dyhkwb/cg 10XDSKS8sj540WA070udVJ3W,
ECDSA key fingerprint is MD5:d1:03:f1:59:62:89:b4:e8:55:e6:18:14:09:0d:dc:de,
Are you sure you want to continue connecting (yes/no) yes
Warning:Permanetly added '[123.23.36.11]:123' (ECDSA) to the list of known hosts,
root@'123.23.36.11's password:
Last login:Wed Mar 4 15:37:03 2020 from 10.2.3.11
[root@node2 ~]# hostname
node2
[root@node2 ~]# hostname -I
10.2.3.12

【一我的,一个地方,一首歌,一段回忆】

相关文章
相关标签/搜索