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

【一我的,一個地方,一首歌,一段回憶】

相關文章
相關標籤/搜索