iptables詳解

出處:http://www.cnblogs.com/davidwang456/p/3540837.html
基本概念:

1.防火牆工作在主機邊緣:對於進出本網絡或者本主機的數據報文,根據事先設定好的檢查規則對其檢查,對形跡可疑的報文一律按照事先定義好的處理機制做出相應處理

對linux而言tcp/ip協議棧是在內核當中,意味着報文的處理是在內核中處理的,也就是說防火牆必須在工作在內核中,防火牆必須在內核中完成tcp/ip報文所流進的位置,用規則去檢查,才真正能工作起來。

iptables用來衡量tcp/ip報文的屬性:源ip、目標ip、源端口、目標端口;

tcp標誌位: syn、syn+ack、ack、 fin、urg、psh、rst ;

2.應用網關

衆多代理服務器都是應用網關,比如squid(使用acl限制應用層)varish這一類代理服務等。

3,***檢測系統(IDS):

·網絡***檢測系統 NIDS

·主機***檢測系統 HIDS

對於IDS常用的檢測服務有:snort等

4.***防禦系統(IPS),比如蜜罐

部署一套***檢測系統是非常麻煩的,因爲必須檢測網絡任意一個位置

對於IPS常用的檢測服務有: tripwire 等

iptables基本概念

對linux來說,是能夠實現主機防火牆的功能組件,如果部署在網絡邊緣,那麼既可以扮演網絡防火牆的角色,而且是純軟件的

網絡數據走向:

請求報文à網關à路由à應用程序(等待用戶請求)à內核處理à路由à發送報文

iptables規則功能

表:

filter主要和主機自身有關,主要負責防火牆功能 過濾本機流入流出的數據包是默認使用的表;

input :負責過濾所有目標地址是本機地址的數據包,就是過濾進入主機的數據包;

forward :負責轉發流經主機但不進入本機的數據包,和NAT關係很大;

output :負責處理源地址的數據包,就是對本機發出的數據包;

NAT表:

負責網絡地址轉換,即來源於目的IP地址和端口的轉換,一般用於共享上網或特殊端口的轉換服務

snat :地址轉換

dnat :標地址轉換

pnat :標端口轉換

mangle 表:

將報文拆開來並修改報文標誌位,最後封裝起來

5個檢查點(內置鏈)

·PREROUTING

·INPUT

·FORWORD

·OUTPUT

·POSTROUTING

多條鏈整合起來叫做表,比如,在input這個鏈,既有magle的規則也可能有fileter的規則。因此在編寫規則的時候應該先指定表,再指定鏈

netfilter主要工作在tcp/ip協議棧上的,主要集中在tcp報文首部和udp報文首部

規則的屬性定義:

1.網絡層協議

主要集中在ip協議報文上

2.傳輸層協議屬性:

主要集中在

tcp

udp

icmp icmp其並不是真正意義傳輸層的,而是工作在網絡層和傳輸層之間的一種特殊的協議

3.ip報文的屬性:

IP報文的屬性爲: 源地址.目標地址

4.iptables規則匹配

iptables如何查看錶和鏈

大寫字母選項:可以實現某種功能,比如添加刪除清空規則鏈;

小寫字母選項:用來匹配及其他;

-L :list 列表

-n :數字格式顯示ip和端口;

--line-numbers:顯示行號;

-x : 顯示精確值,不要做單位換算;

-t : 指定表

 -t{fillter|nat|mangle|raw}

-v : 顯示詳細信息 -v -vvv -vvvv ..可以顯示更詳細的信息

5.其他子命令:

管理鏈:

-F :清空鏈

清空nat表中的input鏈,格式如下:

#iptables-t nat -F INPUT

#清空fllter表所有鏈:

#iptables-F

-P : 設定默認策略,爲指定鏈設置默認策略,格式如下:

#設置fllter表input鏈的默認規則爲丟棄

iptables-t fllter -P INPUT DROP

-N : 新建一條自定義鏈(內置鏈不能刪除,如果太多,可以自定義鏈)

#自定義連只能被調用纔可以發揮作用

iptables-N fillter_web

-X : 刪除自定義空鏈,如果鏈內有規則,則無法刪除

-Z :計算器清零

iptables-Z

-E :重命名自定義鏈

iptables管理規則:

-A :append附加規則,將新增的規則添加到鏈的尾部

-I[n] :插入爲第n條規則

-D : 刪除第n條規則

-R[n] : 替換第N條

表和鏈的對應關係:

fillter :INPUT FORWORD OUTPUT

nat : PREROUTING POSTROUTING OUTPUT

使用-t指定表來查看指定表內的規則:

#iptables-t nat -L -n

raw : prerouting output

iptables-t raw -L -n

mangle: prerouting input forword output postrouting

iptables-t mangle -L -n

#查看規則

[root@test3~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot optsource destination

Chain OUTPUT (policy ACCEPT)
target prot optsource destination

通過以上可以觀察到,每一個鏈都有默認策略:policy ACCEPT

通常只需要修改fllter表的默認策略即可,由此如果有報文請求來訪問本機的某個服務,那麼則會經過input鏈,因此進來的報文都是需要做過濾的,那麼出去的報文則不需要過濾,在有些特定的場所下也需要做過濾

所以寫規則的時候必須放將規則寫在正確鏈上,意義非常重大

規則和默認策略都有2個計數器,通過-v選項可以觀察規則的匹配情況

#iptables -t nat -L -n -v

[root@sshgw~]# iptables -L -n -v

ChainINPUT (policy ACCEPT 7 packets, 975 bytes)

pkts bytestarget prot opt in out source destination

0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0

0 0 DROP all -- eth2 * 101.61.0.0/10 0.0.0.0/0

0 0 DROP all -- eth2 * 127.0.0.0/8 0.0.0.0/0

0 0 DROP all -- eth2 * 162.254.0.0/16 0.0.0.0/0

0 0 DROP all -- eth2 * 192.0.0.0/24 0.0.0.0/0

0 0 DROP all -- eth2 * 192.0.2.0/24 0.0.0.0/0

0 0 DROP all -- eth2 * 197.18.0.0/15 0.0.0.0/0

0 0 DROP all -- eth2 * 197.51.100.0/24 0.0.0.0/0

0 0 DROP all -- eth2 * 203.0.111.0/24 0.0.0.0/0

0 0 DROP all -- eth2 * 224.0.0.0/4 0.0.0.0/0

0 0 DROP all -- eth2 * 240.0.0.0/4 0.0.0.0/0

776 37056 REFRESH_TEMP all -- 0.0.0.0/0 0.0.0.0/0

編寫規則語法:

iptables [-t 表] 大寫選項子命令 [規則號] 鏈名 匹配標準 -j 目標(規則)

目標:

DROP : 丟棄

REJECT : 拒絕

ACCEPT : 接受

RETURN : 返回主鏈繼續匹配

REDIRECT: 端口重定向

MASQUERADE :地址僞裝

DNAT : 目標地址轉換

SNAT :源地址轉換
MARK :打標籤

LOG

自定義鏈

匹配標準

iptables的匹配標準大致分爲兩類:

1.通用匹配

-s | --src | --source [!] IP/NETWORK

-d ------------------------

-i :指定數據報文流入接口 input prerouting forward

-o :指定數據報文流出接口 output postrouting forward

-p :明確說明只放行哪種協議的報文匹配規則

以當前主機爲例:

凡是來自於某個ip段的網絡訪問本機

[[email protected]]# iptables -A INPUT -s 10.0.10.0/24 -d 10.0.10.0/24 -j ACCEPT
[root@test3 xtables-1.4.7]# iptables -L -n -v

ChainINPUT (policy ACCEPT 10 packets, 1029 bytes)

pkts bytestarget prot opt in out source destination

22 1660 ACCEPT all -- 10.0.10.0/24 10.0.10.0/24

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 16 packets, 1536 bytes)
pkts bytes target prot opt in out source destination

pkts 被本機報文所匹配的個數

bytes 報文所有大小記起來之和

opt 額外的選項,--表示沒有

target 處理機制

prot 放行哪種協議

source 源地址

destination 目標地址

對於嚴謹的規則,一般默認規則都是拒絕未知,允許已知

如下所示:

只放行信任IP地址段,其他全部禁止

iptables-P INPUT DORP

iptables-A INPUT -s 10.0.10.0/24 -d 10.0.10.0/24 -j ACCEPT

iptables-P OUTPUT DORP

iptables-A OUTPUT -d 10.0.10.0/24 -s 10.0.10.0/24-j ACCEPT

保存規則

[root@test3~]# /etc/init.d/iptables save

iptables:Saving firewall rules to /etc/sysconfig/iptables:[ OK ]

保存規則至其他文件

[root@test3~]# iptables-save > /tmp/iptables

加載iptables文件規則

[root@test3~]# iptables-resotre < /tmp/iptables

1.2.規則的替換

首先來查看規則

[root@test3 ~]# iptables -L -n --line-number

ChainINPUT (policy ACCEPT)

num target prot opt source destination

1 ACCEPT all -- 10.0.10.0/24 10.0.10.0/24

ChainFORWARD (policy DROP)

num target prot opt source destination

ChainOUTPUT (policy ACCEPT)

num target prot opt source destination

替換規則:將規則1替換爲 eth0只能夠通過某個網段進來

[root@test3~]# iptables -R INPUT 1 -s 10.0.10.0/24-d 10.0.10.62 -i eth0 -j ACCEPT

[root@test3~]# iptables -L -n --line-number

ChainINPUT (policy ACCEPT)

num target prot opt source destination

1 ACCEPT all -- 10.0.10.0/24 10.0.10.62

2.擴展匹配

#所有的擴展匹配表示要使用-m來指定擴展的名稱來引用,而每個擴展模塊一般都會有自己特有的專用選項,在這些選項中,有些是必備的:

2.1隱含擴展

如下所示:

#端口之間必須是連續的

-p tcp--sport|--dport 21-80

#取反,非21-80的端口

-p tcp--sport|--dport !21-80

#檢測報文中的標誌位

--tcp-flagsSYN,ACK,RST,FIN, SYN

ALL #表示爲所有標誌位

NONE #表示沒有任何一個標誌位

#--tcp-flags ALL NONE #表示所有標誌位都檢測,但是其中多有都爲0

#--tcp-flage ALL SYN,FIN #表示SYN,FIN都爲1(即握手又斷開)

#生成環境下tcp-flags 用的非常多,意義非常重要

例:放行本機對web的訪問

[root@test3~]# iptables -A INPUT -d 10.0.10.62 -ptcp --dport 80 -j ACCEPT

[root@test3~]# iptables -L -n

ChainINPUT (policy DROP)

target prot opt source destination

ACCEPT all -- 10.0.10.0/24 10.0.10.62

ACCEPT tcp -- 0.0.0.0/0 10.0.10.62 tcp dpt:80

放行出去的報文,源端口爲80

[root@test3~]# iptables -A OUTPUT -s 10.0.10.62 -p tcp --sport 80 -j ACCEPT

查看匹配規則

[root@test3 ~]# iptables -L -n --line-number

ChainINPUT (policy DROP)

num target prot opt source destination

1 ACCEPT all -- 10.0.10.0/24 10.0.10.62

2 ACCEPT tcp -- 0.0.0.0/0 10.0.10.62 tcp dpt:80

ChainFORWARD (policy DROP)

num target prot opt source destination

ChainOUTPUT (policy DROP)

num target prot opt source destination

1 ACCEPT all -- 10.0.10.0/24 10.0.10.0/24

2 ACCEPT tcp -- 10.0.10.62 0.0.0.0/0 tcp spt:80

考慮要點:

(1)規則爲放行出去的響應報文

(2)考慮源IP地址爲本機,目標爲訪問的時候拆開報文纔可以獲知,而寫規則的時候是面向所有主機,所以這裏不用寫

(3)源端口:80 ,因爲用戶訪問的時候一定會訪問其80端口,無可非議的

(4)目標端口:請求到來的時候事先無法斷定對方的端口是多少,所以不用寫

2.2協議匹配

通常對協議做匹配則使用 -p 參數 來指定協議即可

匹配UDP:UDP只有端口的匹配,沒有任何可用擴展,格式如下

-p udp--sport | --dport

匹配ICMP格式如下

-picmp --icmp-[number]

icmp常見類型:請求爲8(echo-request),響應爲0(echo-reply)

例:默認規則input output 都爲DROP,使其本機能ping(響應的報文)的報文出去

通過此機器去ping網關10.0.10.1 , 可結果卻提示not permitted,使其能通10.0.10.0/24網段中的所有主機

[root@test3~]#iptables -A OUTPUT -s 10.0.10.62 -d 10.0.10.0/24 -p icmp --icmp-type8 -j ACCEPT

可看到無法響應:0表示響應進來的報文規則,並沒有放行自己作爲服務端的的角色規則

[root@test3~]# iptables -A INPUT -s 10.0.10.0/24 -d 10.0.10.62 -p icmp --icmp-type0 -j ACCEPT

#ping 10.0.10.x

允許類型爲0(響應報文)出去

[root@test3~]# iptables -A OUTPUT -s 10.0.10.62 -d 10.0.10.0/24 -picmp --icmp-type 0 -j ACCEPT

例2:本機DNS服務器,要爲本地客戶端做遞歸查詢;iptables的input output默認爲drop 本機地址是10.0.10.62

[root@test3~]# iptables -A INPUT -d 10.0.10.62 -p udp --dprot 53 -j ACCEPT

[root@test3~]# iptables -A OUTPUT -S 10.0.10.62 -p udp --sprot 53 -j ACCEPT

客戶端請求可以進來,響應也可以出去,但是自己作爲客戶端請求別人是沒有辦法出去的,所以:

[root@test3~]# iptables -A OUTPUT -s 10.0.10.62 -p udp --dport 53 -j ACCEPT

[root@test3~]# iptables -A INPUT -d 10.0.10.62 -p udp --sprot 53 -j ACCEPT

如果爲tcp 則將以上udp改爲tcp即可

2.3 TCP協議的報文走向
iptables詳解

TCP連接的建立

雙方主機爲了實現tcp的通信,所以首先三次握手

客戶端主動發出了SYN,服務器端處於監聽狀態,隨時等待客戶端的請求信息;

服務器端接收到了SYN請求,從而回應用戶的請求,發送SYN_ACK ,從而轉換爲SYN_REVIN

客戶端在發出了請求,從發出的那一刻close狀態轉換爲SYN_SENT狀態

客戶端在SYN_SENT狀態中一旦收到了服務端發來的SYN_ACK 之後,轉換爲ESTABLISHED狀態,這時便可以開始傳送數據了,無論怎麼傳都是ESTABLISHED狀態

而服務器端收到了對方的ACK,同樣處於ESTABLISHED狀態

數據傳輸結束之後

客戶端從ESTABLEISHED狀態,發起四次斷開請求

客戶端發起FIN請求,從而進入等待狀態

服務端收到斷開請求之後,便發起ACK請求

客戶端收到服務端發來的ACK確認信息後,從而又發起FIN_2 請求

等待服務端發來的FIN請求之後,便確認

服務器端收到FIN併發送ACK之後,服務器端便處於CLOSE_WAIT便自己發送FIN,從而進入LAST ACK模式 ,

確認完後不能立刻斷開,還需要等待一定的時間(大約240秒),確認報文是否傳遞給對方

於是轉換爲CLOSED

iptables詳解
iptables中有一個擴張參數--status

此擴展可以追蹤tcp udp icmp等各種狀態

其能夠使用某種內核數據結構保持此前曾經建立的連接狀態時間的功能,稱爲連接追蹤

內核參數文件路徑爲:

[root@test3~]# ls /proc/sys/net/netfilter/

[root@test3~]# cat /proc/sys/net/netfilter/nf_conntrack_udp_timeout
30

以此爲例,在其30秒鐘內,曾經建立過的udp連接,這些連接都可以被追蹤到的,可以明確知道在這期間哪個客戶端曾經訪問過,只要基於請求的序列,能跟此前保持會話信息,即可查詢

2.4顯式擴展

在iptalbes中數據包和被跟蹤連接的4種不同狀態相關聯,這四種狀態分別是NEW、ESTABLISHED、RELATED及INVALID,除了本機產生的數據包由NAT表的OUTPUT鏈處理外,所有連接跟蹤都是在NAT表的PREROUTING鏈中進行處理的,也就是說iptables在NAT表的PREROUTING鏈裏從新計算所有數據包的狀態。如果發送一個流的初始化數據包,狀態就會在NAT表的OUTPUT鏈裏被設置爲NEW,當收到迴應的數據包時,狀態就會在NAT表的PREROUTING鏈裏被設置爲ESTABLISHED,如果第一個數據包不是本機生成的,那就回在NAT表PREROUTING鏈裏被設置爲NEW狀態,所以所有狀態的改變和計算都是在NAT表中的錶鏈和OUTPUT鏈裏完成的。

使用-m來指定其狀態並賦予匹配規則,語法如下

-mstate --state 狀態

NEW

ESTABLISHED

RELATED

INVALID

NEW:

NEW狀態的數據包說明這個數據包是收到的第一個數據包。比如收到一個SYN數據包,它是連接的第一個數據包,就會匹配NEW狀態。第一個包也可能不是SYN包,但它仍會被認爲是NEW狀態。

ESTABLISHED:

只要發送並接到應答,一個數據連接就從NEW變爲ESTABLISHED,而且該狀態會繼續匹配這個連接後繼數據包。

RELATED:

當一個連接和某個已處於ESTABLISHED狀態的連接有關係時,就被認爲是RELATED,也就是說,一個連接想要是RELATED的,首先要有個ESTABLISHED的連接,這個ESTABLISHED連接再產生一個主連接之外的連接,這個新的連接就是RELATED。

INVALID:

INVALID狀態說明數據包不能被識別屬於哪個連接或沒有任何狀態。

例:

對本機22端口做狀態監測:

進來的請求狀態爲new,而出去的狀態則爲ESTABLISHED,如果自動連接別人 狀態肯定爲NEW,如果正常去響應別人那麼狀態肯定是ESTABLISHED

[root@test3~]# iptables -I INPUT -s 10.0.10.0/24 -d 10.0.10.62 -p tcp --dport 22 -m state--state NEW,ESTABLISHED -j ACCEPT

出口的響應都必須是ESTABLISHED

[root@test3~]# iptables -A OUTPUT -s 10.0.10.62 -d 10.0.10.0/24 -p tcp --dport 22 -m state--state ESTABLISHED -j ACCEPT

[root@test3~]# iptables -L -n

ChainINPUT (policy ACCEPT)

target prot opt source destination

ACCEPT tcp -- 10.0.10.0/24 10.0.10.62 tcp dpt:22 state NEW,ESTABLISHED

ChainFORWARD (policy DROP)

target prot opt source destination

ChainOUTPUT (policy ACCEPT)

target prot opt source destination

ACCEPT tcp -- 10.0.10.62 10.0.10.0/24 tcp dpt:22state ESTABLISHED

多端口規則匹配

使用參數-m multiport 可以指定15個以內的非連續端口,比如21-22,80

-mmulitport

--src-prots

--dst-ports

--prots

#對多端口進行匹配,只要匹配以下端口,則全部放行

[root@test3~]# iptables -A INPUT -s 10.0.10.0/24 -d10.0.10.62 -p tcp -m state --state NEW -m mulitport--destination-ports 21,22,80 -j ACCEPT

多IP匹配,指定匹配的IP地址範圍:

-miprange

--src-range

--dst-range

指定匹配的連續ip段

[root@test3~]# iptables -A INPUT -s -m iprange --src-range 10.0.10.100-10.0.10.200

指定速率匹配

默認爲每秒匹配3個報文,基於令牌桶算法

-mlimit

--limit #NUMBER,表示允許收集多少個空閒令牌

--limit-burst #RATE,允許放行多少個報文

比如:ssh一分鐘之內只能建立20個鏈接,平均5秒一個,而一次性只能放行2個空閒令牌

--limit 20/min

--limit-burst 2

只有在大量空閒令牌存儲的情況下,纔可有limit-burst控制

例:控制NEW狀態的請求

[root@test3~]# iptables -A INPUT -s 10.0.10.0/24 -d 10.0.10.62 -m state --state NEW -mlimit --limit 12/min --limit 12/min --limit-burst 2 -j ACCEPT

例2:每次只允許2個ping包進來

[root@test3~]# iptables -F

[root@test3~]# iptables -A INPUT -s 10.0.10.0/24 -d 10.0.10.62 -p icmp --icmp-type 8 -mlimit --limit 20/min --limit-burst 5 -j ACCEPT

新建立一終端,在其終端ping10.0.10.62可以看到效果,不再演示

2.5對應用層進行匹配

對應用層編碼字符串做相似匹配,常用算法使用--alog來指定 ,一般來講算法一般爲bm和kmp

-msrting

--string ""

--algo {bm|kmp}

例:

·假如我們期望web站點頁面中任何包含"hello"的字符串的頁面,則禁止訪問,其他則放行

·請求報文中不會包含hello,一般來講只包含訪問某個頁面,那麼請求內容無非包含了請求某個鏈接而已

·響應報文中會封裝頁面的內容信息,因此 會出現在響應報文中,而不是請求報文

啓動httpd服務

[root@test3~]# /etc/init.d/httpd start

在web站點新建頁面1.html,內容爲"hello" , 2.html內容爲"word"

[root@test3domian]# echo hello > 1.html

[root@test3domian]# echo word > 2.html

在iptables的允許放行規則前面加一條更嚴謹的禁止規則:

[root@test3domian]# iptables -A OUTPUT -s 10.0.10.62 -p tcp --sport 80 -m string --string"hello" --algo kmp -j REJECT

再次訪問

[root@test3domian]# curl -dump http://10.0.10.62/2.html

word

[root@test3domian]# curl -dump http://10.0.10.62/1html

#請求已發出去但是一直沒有反應,我們來看一下防火牆規則是否被匹配到

[root@test3domian]# iptables -L -nv

ChainINPUT (policy ACCEPT 255 packets, 30024 bytes)

pkts bytes target prot opt in out source destination

ChainFORWARD (policy DROP 0 packets, 0 bytes)

pkts bytes target prot opt in out source destination

ChainOUTPUT (policy ACCEPT 201 packets, 29406 bytes)

pkts bytes target prot opt in out source destination

35 11209 REJECT tcp -- 10.0.10.62 0.0.0.0/0 tcp spt:80STRING match "hello" ALGO name kmp TO 65535 reject-withicmp-port-unreachable

基於時間限定

-m time

#指定日期起止範圍

--datestart

--datestop

#指定時間的起止範圍

--timestart

--timestop

#指定星期x範圍

--weekdays

#指定月份

--monthdays

3.基於iptables實現NAT功能

3.1基於SNAT功能的實現

考慮場景:爲解決IP地址不足,所以用NAT功能來實現成本節約

SNAT:源地址轉換(代理內部客戶端訪問外部網絡)在POSTROUTING或OUTPUT鏈上來做規則限制

參數選項:

-j SNAT --to-source IP

-j MASQUERADE

DNAT :目標地址轉換(將內部服務器公開至外部網絡)需在PREROUTING做限制

參數選項:

-j DNAT --to-destination IP:prot

NAT不但可以轉換目標地址,還可以映射目標端口

拓補圖如下:
iptables詳解
假設iptables爲網關服務器,192.168.0.0爲內網地址段 10.0.10.0 爲外網地址段

規劃:

服務器角色

服務器內網IP地址

iptables

10.0.10.62 、 192.168.0.4

client

10.0.10.60

web server

192.168.0.110

下面來配置服務器:

webserver服務器配置如下:

[root@mode~]# /etc/init.d/httpd start

[root@modehtml]# echo 111 > test.html

#查看路由信息

[root@modehtml]# route -n
Kernel IP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface

192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1

10.0.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0

0.0.0.0 192.168.0.4 0.0.0.0 UG 0 0 0 eth1

0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth1

iptables服務器配置如下:

開啓路由轉發功能

[root@test3domian]# echo 1 > /proc/sys/net/ipv4/ip_forward

client配置如下:

#將eth1的網卡關閉,真正意義上斷開連接

[root@test~]# ifdown eth1

#添加直連路由

[root@test~]# route add default gw 10.0.10.62

[root@test~]# route -n

KernelIP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface

10.0.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0

0.0.0.0 10.0.10.62 0.0.0.0 UG 0 0 0 eth0

這時去ping192.168.0.0 段的地址是通的,如下所示

[root@test~]# ping 192.168.0.4

PING192.168.0.4 (192.168.0.4) 56(84) bytes of data.

64bytes from 192.168.0.4: icmp_seq=1 ttl=64 time=22.0 ms

64bytes from 192.168.0.4: icmp_seq=2 ttl=64 time=0.245 ms

查看是否可訪問webserver的web服務

[root@test ~]# curl -dumphttp://192.168.0.110/test.html

111

返回web server上查看訪問日誌

[root@modelogs]# tail access_log

10.0.10.60- - [02/Feb/2014:20:33:27 +0800] "POST /test.htmlHTTP/1.1" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu)libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

#源地址爲10.60 由此可見,由路由來實現兩臺主機的通信

如果想使用nat方式來實現任何來自10.0/24的網絡 通過此臺服務器想訪問web其他主機,都將源地址改爲iptables的ip地址

#凡是來自10.0.10.0網段的主機都將其轉換爲自己的ip地址

[root@test3domian]# iptables -t nat -A POSTROUTING-s 10.0.10.0/24 -j SNAT --to-source 192.168.0.4

返回client端再次訪問web server,並查看日誌

[root@mode logs]# tail access_log

10.0.10.60- - [02/Feb/2014:20:33:27 +0800] "POST /test.html HTTP/1.1" 200 4"-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

192.168.0.4- - [02/Feb/2014:20:37:13 +0800] "POST /test.htmlHTTP/1.1" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu)libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

由此可見,來源IP爲代理服務器,因此它是回給192.168.0.4的 ,由192.168.0.4通過nat路由表再返回給client

查看規則

[root@test3domian]# iptables -t nat -L -n -v

ChainPREROUTING (policy ACCEPT 3 packets, 387 bytes)

pkts bytes target prot opt in out source destination

ChainPOSTROUTING (policy ACCEPT 0 packets, 0 bytes)

pkts bytes target prot opt in out source destination

2 144 SNAT all -- 10.0.10.0/24 0.0.0.0/0 to:192.168.0.4

ChainOUTPUT (policy ACCEPT 0 packets, 0 bytes)

pkts bytes target prot opt in out source destination

將其狀態全部放行

[root@test3domian]# iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT

[root@test3domian]# iptables -A FORWARD -s10.0.10.0/24 -p tcp --dport 80 -m state --state NEW -j ACCEPT

再來測試:切換至Client

[root@test~]# curl -dump http://192.168.0.110/test.html
111

返回iptables服務器,查看規則匹配情況

[root@test3domian]# iptables -L -nv

ChainINPUT (policy ACCEPT 45 packets, 3241 bytes)

pkts bytes target prot opt in out source destination

ChainFORWARD (policy ACCEPT 0 packets, 0 bytes)

pkts bytes target prot opt in out source destination

27 2964 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 stateESTABLISHED

3 180 ACCEPT tcp -- 10.0.10.0/24 0.0.0.0/0 tcp dpt:80state NEW

ChainOUTPUT (policy ACCEPT 31 packets, 4064 bytes)

pkts bytes target prot opt in out source destination

通過規則匹配可以看到,首先其會先發起三次握手第一次由第二條規則先匹配到,而後來由狀態規則ESTABLISHED進行匹配

3.2定義DNAT的實現

如果構建大併發的環境時,NAT並不適用,一般來講能夠併發用戶請求的場景來講,在2-3W 已經非常龐大了,通常都是專業級硬件分發設備或應用來做分發,下面嘗試着使client能夠訪問web服務器,但期望的是今後訪問web服務器不是訪問192.168.0.110而是iptables服務器10.0.10.62

因爲是實驗環境,所以清空所有規則

[root@test3~]# iptables -t nat -F

[root@test3~]# iptables -F

[root@test3~]# iptables -P FORWARD ACCEPT

我們期望網關10.0.10.62爲用戶訪問目標,而不是192.168.0.110,但62上是沒有web服務的,所以有人訪問62的web服務必須將其轉換到110上

所以要在iptables服務器上操作:

[root@test3~]# iptables -t nat -A PREROUTING -d 10.0.10.62 -p tcp --dport 80 -j DNAT--to-destination 192.168.0.110

在客戶端測試:

[root@test~]# curl -dump http://10.0.10.62/test.html
111

如果將FORWARD鏈的規則改爲DROP那麼該如何來實現:

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

再次測試,果然無法訪問

它可以實現地址轉換,但是地址轉換後的報文是無法再轉發至內部主機中去,因爲forward規則給擋住了

可以將已經建立過連接的請求全部放行,於是乎:

[root@test3~]# iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@test3 ~]# iptables -A FORWARD -d 192.168.0.110 -p tcp --dport 80 -m state--state NEW -j ACCEPT

#目標地址必須是內部web地址 因爲forward鏈在路由之後纔可知其是否要進行轉發

#也就是意味着用戶的請求到達PREROUTING的時候,目標的地址已經改過了,當用戶的請求FORWARD之後目標地址已經是web地址

放行轉發ssh服務:

我們想請求iptables的22端口則轉發至web server端的22端口上去

[root@test3~]# iptables -t nat -A PREROUTING -d 10.0.10.62 -p tcp --dport 22 -j DNAT --to-destination 192.168.0.110

[root@test3~]# iptables -A FORWARD -d 192.168.0.110 -p tcp --dport 22 -m state --state NEW-j ACCEPT

進行登錄

[root@test~]# ssh 10.0.10.62

由此可見,以後想登陸10.62則登陸不上去了(可以更改爲非22端口等,不再說明了哦)

將80端口請求轉發至web端8080端口

更改apache服務的監聽端口:

Listen8080

切換至iptables服務端添加規則:

[root@test3~]# iptables -t nat -A PREROUTING -d 10.0.10.62 -p tcp --dport 80 -j DNAT--to-destination 192.168.0.110:8080

[root@test3~]# iptables -t nat -L -nv
Chain PREROUTING (policy ACCEPT 2 packets, 458 bytes)
pkts bytes target prot opt in out source destination
6 360 DNAT tcp -- 0.0.0.0/0 10.0.10.62 tcp dpt:80to:192.168.0.110:8080

Chain POSTROUTING (policy ACCEPT 9 packets, 564 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 3 packets, 204 bytes)
pkts bytes target prot opt in out source destination

在端口映射環境下如何放行web服務:

在做地址轉發的時候必須以轉換之後的端口和地址爲目標端口和目標ip地址

[root@test3~]# iptables -P FORWARD DROP
[root@test3 ~]# iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT
[root@test3 ~]# iptables -A FORWARD -d 192.168.0.110 -p tcp --dport 8080 -mstate --state NEW -j ACCEPT

假設在此服務器上還有mysql服務,假設mysql在內網工作在正常服務端口,但告知外面工作在6789端口上,那麼

進入mysql並授權

mysql>grant all on . to 'root'@'%' identified by '123456';

mysql>flush privileges;

在iptables服務器上添加規則如下

[root@test3 ~]# iptables -t nat -A PREROUTING-d 10.0.10.62 -p tcp --dport 6789 -j DNAT --to-destination 192.168.0.110:3306

[root@test3~]# iptables -A FORWARD -d 192.168.0.110 -p tcp --dport 3306 -m state --stateNEW -j ACCEPT

[root@test~]# mysql -uroot -h10.0.10.62 -P6789 -p

切換至client端進行測試

[root@test~]# mysql -uroot -h10.0.10.62 -P6789 -p

4.ip_conntrack 功能

其擴展模塊路徑爲

/proc/net/nf_conntrack

/proc/sys/net/nf_conntrack_max

不同版本的值和相關信息未必一致

[root@test3~]# cat /proc/sys/net/nf_conntrack_max
31860

比起紅帽5的值已經大的太多了

#這些超時時間非常長,如下所示:

[root@test3 ~]# cat/proc/net/nf_conntrack
ipv4 2 tcp 6 431999ESTABLISHED src=10.0.10.62 dst=10.0.10.1sport=22 dport=59448 src=10.0.10.1 dst=10.0.10.62 sport=59448 dport=22[ASSURED] mark=0 secmark=0 use=2

#可以在某些時候將值儘量調低,如果不盡量追蹤過長時間

[root@test3~]# cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
432000 #5天時間

如果沒有特殊需求的話,將其值調低,這樣可以保證被追蹤的連接儘早被記錄的文件中清除出去,已騰出空間供其他被追蹤使用

既然追蹤連接功能有限制而且對性能有很大的影響爲何還要開啓呢?

啓動其功能的原因在於 在某些場景中必須追蹤狀態,才能達到目的,如果在併發連接非常大的場景下啓用連接追蹤是不明智的

因此需自己判斷好應用場景,不得不啓用,連接數也非常大,方法如下:

(1).調小nf_conntrack_tcp_timeout_established

(2).調大 /proc/sys/net/nf_conntrack_max #需要一定的內存容量,只要空間充足即可

擴展模塊connlimit:

connlimit 連接數限制,一般可以實現控制某源ip地址發起來某連接個數的

--connlimit-above[number] #連接數的上限,如果某個連接數的個數超過爲某個值之後(高於),通常用取反的方法來放行:

#iptables-A INPUT -s 10.0.10.0/24 -p tcp --dport 80 -m connlimit ! --connlimit-above 5-j ACCEPT

hashlimit,limit #能夠分析每個ip地址的速率

5.recent模塊

利用iptables的recent模塊來抵禦DOS***: 22,建立一個列表,保存有所有訪問過指定的服務的客戶端IP 對本機ssh: 遠程連接

(1).利用connlimit模塊將單IP的併發設置爲3;會誤殺使用NAT上網的用戶,可以根據實際情況增大該值;

iptables-I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP

第二句是記錄訪問tcp 22端口的新連接,記錄名稱爲SSH --set 記錄數據包的來源IP,如果IP已經存在將更新已經存在的條目

(2).利用recent和state模塊限制單IP在300s內只能與本機建立2個新連接。被限制五分鐘後即可恢復訪問

iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent--set --name SSH
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent--update --seconds 300 --hitcount 3 --name SSH -j LOG --log-prefix "SSHAttach: "
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent--update --seconds 300 --hitcount 3 --name SSH -j DROP

第三句是指SSH記錄中的IP,300s內發起超過3次連接則拒絕此IP的連接。
--update 是指每次建立連接都更新列表;
--seconds必須與--rcheck或者--update同時使用
--hitcount必須與--rcheck或者--update同時使用

(3).iptables的記錄:/proc/net/xt_recent/SSH

也可以使用下面的這句記錄日誌:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent--update --name SSH --second 300 --hitcount 3 -j LOG --log-prefix "SSHAttack"

6.netfilter 第三方擴展模塊,Layer 7

Layer 7能夠識別大部分協議,比如QQ BT 迅雷 等

iptables/netfilter 是工作在tcp/ip協議棧上的一規則生成框架,iptables只是規則編寫工具,讓iptables識別layer 7

系統自帶的iptables並不識別Layer 7 ,所以必須對其進行打補丁

1 向內核的netfilter打補丁

2 向iptables打補丁

(實驗中我們使用紅帽專用的源碼專用內核)

使用到的命令:

diff #比較兩個版本的不同並生成補丁

patch #實現將某個補丁文件,升級到當前比較老的版本上,使得其完成源碼升級

diff命令可以對目錄進行比較,能夠將老目錄和新目錄的文件逐個進行比較,將不一致的文件逐個創建補丁

爲自己的內核打補丁使其支持netfilter

RedHat src格式的rpm包:

http://ftp.redhat.com/redhat/linux/enterprise/6Server/en/os/SRPMS/

開始打補丁:

以下爲所需要用的工具包

[root@test3 iptables]# ll
總用量 88936
-rw-r--r-- 1 rootroot 546864 2月 2 19:15 iptables-1.4.20.tar.bz2
-rw-r--r-- 1 root root 90347331 2月 2 20:10 kernel-2.6.32-358.el6.src.rpm
-rw-r--r-- 1 root root 1420502月 2 19:14 l7-protocols-2009-05-28.tar.gz
-rw-r--r-- 1 root root 22754 2月 2 19:14 netfilter-layer7-v2.23.tar.bz2

解壓netfilter-layer7-v2.23.tar.bz2 至/usr/src

[root@test3 iptables]# tar xf linux-2.6.32-358.el6.tar.bz2 -C /usr/src/

[root@test3 src]# cd /usr/src/

[root@test3 src]# ln -s linux-2.6.32-358.el6 linux
[root@test3 src]# cd linux

[root@test3 linux]# cp /boot/config-2.6.32-358.el6.x86_64 .config

拷貝netfilter內核補丁

[root@test3 iptables]# tar xf netfilter-layer7-v2.23.tar.bz2 -C /usr/src/

[root@test3 netfilter-layer7-v2.23]# pwd
/usr/src/netfilter-layer7-v2.23
[root@test3 netfilter-layer7-v2.23]# ll
total 76
-rw-r--r-- 1 1000 1000 7414 Jul 14 2009 CHANGELOG #補丁版本變化新增功能
drwxr-xr-x 2 1000 1000 4096 Jul 14 2009iptables-1.4.3forward-for-kernel-2.6.20forward #補給iptables補丁
-rw-r--r-- 1 1000 1000 59232 Aug 29 14:08 kernel-2.6.32-layer7-2.23.patch #補給內核的補丁
-rw-r--r-- 1 1000 1000 2013 Jul 14 2009 README

[root@test3 netfilter-layer7-v2.23]# cd /usr/src/linux

#使用patch命令開始打補丁 將第一個斜線之前的所有內容去掉,直接把文件補當前內核源碼數做比較

#../是父目錄起始點

[root@test3 linux]# patch -p1 <../netfilter-layer7-v2.23/kernel-2.6.32-layer7-2.23.patch

開始編譯內核

解決make menuconfig的依賴關係問題,首先安裝ncurses

[root@test3 linux]# yum install ncurses-devel -y

進入內核編譯界面

[root@test3 linux]# make menuconfig

按照圖中內容依次選擇
iptables詳解
按空格選擇
iptables詳解
默認是沒有選擇的,按空格鍵將其選擇

保存退出

使用screen 模式來編譯內核,以防終端掉線等一些特殊意外情況發生

[root@test3 linux]# screen
make

make modules install

make install

安裝內核過程中,這個腳本會自動修改grub中的配置文件,而後重新啓動當前系統就可以使用當前內核了。

由於內核中新增了對Layer7 的支持,但是系統上已經安裝的iptables並不實現利用l7寫規則,所以必須向iptables打補丁

打完補丁後,還必須將其編譯至當前系統上

#編譯好之後可以看到會生成我們自己編譯的內核目錄,如下所示:

[root@test3 ~]# ls /lib/modules/
2.6.32-358.el6.x86_64 2.6.32-l7.1

編譯完成後,查看gurb.conf確保新內核被加載進來

[root@test3 ~]# grep -v '#' /etc/grub.conf
default=1
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
titleCentOS (2.6.32-l7.1)
root (hd0,0)
kernel /vmlinuz-2.6.32-l7.1 roroot=UUID=1ef834d4-3eae-4c95-a6ad-8940bb466dce rd_NO_LUKS KEYBOARDTYPE=pcKEYTABLE=us rd_NO_MD crashkernel=auto.UTF-8 rd_NO_LVM rd_NO_DM rhgbquiet
initrd /initramfs-2.6.32-l7.1.img
title CentOS (2.6.32-358.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-358.el6.x86_64 roroot=UUID=1ef834d4-3eae-4c95-a6ad-8940bb466dce rd_NO_LUKS KEYBOARDTYPE=pcKEYTABLE=us rd_NO_MD crashkernel=auto.UTF-8 rd_NO_LVM rd_NO_DM rhgbquiet
initrd /initramfs-2.6.32-358.el6.x86_64.img

可以看到已經被加載進來,先不要急着更改啓動內核,先shutdown 將其關機 然後通過交互界面來選取相關內核,按回車進入

iptables詳解
選擇第一個,我們自己編譯的內核,回車

[root@test3 ~]#uname -r
2.6.32-l7.1

[root@test3 ~]# cd~/rpmbuild/SPECS/
[root@test3 SPECS]# ls
iptables.spec

對iptables.spec 進行rpm封裝,如下所示

iptables的安裝

  1. 在iptables官方下載源碼並打補丁後編譯安裝

在官網下載iptables-1.4.20.tar.bz2

[root@test3iptables]# cd /usr/src/netfilter-layer7-v2.23/
[root@test3 netfilter-layer7-v2.23]# ls
CHANGELOG kernel-2.6.32-layer7-2.23.patch
iptables-1.4.3forward-for-kernel-2.6.20forward README
[root@test3 netfilter-layer7-v2.23]# cdiptables-1.4.3forward-for-kernel-2.6.20forward/
[root@test3 iptables-1.4.3forward-for-kernel-2.6.20forward]# ll
libxt_layer7.c #layer7的模塊

libxt_layer7.man

#將其複製到源碼目錄中

[root@test3iptables]# tar xf iptables-1.4.20.tar.bz2
[root@test3 iptables]# cd iptables-1.4.20

#找到extensions目錄,extensions目錄內是iptables所支持的模塊

#將上面的libxt_layer7.c libxt_layer7.man複製進此目錄 並重新編譯即可

[root@test3extensions]# cp/usr/src/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/libxt_layer7.*./
[root@test3 extensions]# ls | grep lay
libxt_layer7.c
libxt_layer7.man

#要想編譯iptables,前提是先編譯好新內核後,並對新內核的源碼進行編譯,而且需要將之前的iptables卸載

#感覺有些麻煩,那麼有了第二種方法

  1. 下載src.rpm 格式包,安裝 打補丁 而後重新製作成rpm包

在官網下載 iptables-1.4.7-9.el6.src.rpm

[root@test3iptables]# rpm -ivh iptables-1.4.7-9.el6.src.rpm

之後會在家目錄生成rpmbuild的目錄

[root@test3iptables]# cd

[root@test3rpmbuild]# cd SOURCES/

[root@test3SOURCES]# ls

iptables-1.4.5-cloexec.patch iptables-1.4.7-opt_parser_v2.patch iptables-1.4.7-xt_AUDIT_v2.patch iptables.init

iptables-1.4.7 iptables-1.4.7.tar.bz2 iptables-1.4.7-xt_CHECKSUM.patch libxt_AUDIT.man

iptables-1.4.7-chain_maxnamelen.patch iptables-1.4.7-tproxy.patch iptables-config

解壓iptables-1.4.7.tar.bz2

[root@test3SOURCES]# tar xf iptables-1.4.7.tar.bz2

[root@test3extensions]# pwd
/root/rpmbuild/SOURCES/iptables-1.4.7/extensions

複製其目錄

[root@test3extensions]# cp/usr/src/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/libxt_layer7.*./

[root@test3SOURCES]# pwd
/root/rpmbuild/SOURCES

[root@test3SOURCES]# rm -f iptables-1.4.7.tar.bz2
[root@test3 SOURCES]# tar jcf iptables-1.4.7.tar.bz2 ./iptables-1.4.7/*

升級:

[root@test3 SPECS]# pwd
/root/rpmbuild/SPECS

編輯其配置文件並將其封裝

[root@test3 SPECS]#vim iptables.spec

修改參數

Release: 10%{?dist} #之前爲9% 將其值調大

將內核目錄改爲我們新建立的內核目錄

CFLAGS="$RPM_OPT_FLAGS-fno-strict-aliasing" \

./configure--enable-devel --enable-libipq --bindir=/bin --sbindir=/sbin --sysconfdir=/etc--libdir=/%{_lib} --libexecdir=/%{_lib} --mandir=%{_mandir} --includedir=%{_includedir}--with-xtlibdir=/%{_lib}/xtables-%{version} --with-kernel=/usr/src/linux/ --with-kbuild=/usr/src/linux/--with-ksource=/usr/src/linux/

製作rmp安裝包

[root@test3 SPECS]#rpmbuild -bb iptables.spec
[root@test3 x86_64]# pwd
/root/rpmbuild/RPMS/x86_64

#以下生成的爲iptables的升級包

[root@test3x86_64]# ls
iptables-1.4.7-10.el6.x86_64.rpm iptables-ipv6-1.4.7-10.el6.x86_64.rpm
iptables-devel-1.4.7-10.el6.x86_64.rpm

先來看一下當前iptables是什麼版本

[root@test3x86_64]# rpm -qa | grep iptables
iptables-1.4.7-9.el6.x86_64
iptables-ipv6-1.4.7-9.el6.x86_64

這裏我們來升級以下2個包

iptables-1.4.7-10.el6.x86_64.rpmiptables-ipv6-1.4.7-10.el6.x86_64.rpm

在升級之前先將iptables服務停止以防出錯

[root@test3x86_64]# /etc/init.d/iptables stop
[root@test3 x86_64]# rpm -Uvh iptables-1.4.7-10.el6.x86_64.rpmiptables-ipv6-1.4.7-10.el6.x86_64.rpm
[root@test3 x86_64]# /etc/init.d/iptables start

使layer7 能夠識別應用

[root@test3iptables]# tar xf l7-protocols-2009-05-28.tar.gz
[root@test3 iptables]# cd l7-protocols-2009-05-28

#直接make install

[root@test3l7-protocols-2009-05-28]# make install
[root@test3 l7-protocols-2009-05-28]# mkdir -p /etc/l7-protocols
[root@test3 l7-protocols-2009-05-28]# cp -rfa * /etc/l7-protocols

Layer 7所別的協議全部都在/etc/l7-protocols/protocols 目錄下

Layer 7的功能需要利用內核ACCT追蹤的功能,所以還必須修改內核參數,修改ACCT參數

[root@test3protocols]# sysctl -w net.netfilter.nf_conntrack_acct=1

[root@test3protocols]# sysctl -a | grep acct
net.netfilter.nf_conntrack_acct = 1

這時,我們的iptables已經支持Layer 7了

Layer 7的規則匹配:

決絕使用QQ

[root@test3protocols]# iptables -A FORWARD -i eth0 -m layer7 --l7proto qq -j REJECT

拒絕到本機內部http協議

[root@test3protocols]# iptables -A INPUT -d 本機ip -m layer7--l7proto http -j DROP

l7-filter uses thestandard iptables extension syntax
# iptables [specify table & chain] -m layer7 --l7proto [protocol name] -j[action]
# iptables -A FORWARD -i eth1 -m layer7 --l7proto qq -j REJECT

問題總結:

1、由於選擇移除了網絡中對無線網的支持功能,卻沒有關閉編譯移動網設備的驅動程序,使得編譯過程出錯;
2、沒有裝載nf_conntrack模塊時,net.netfilter.nf_conntrack_acct內核參數不會出現,因此,將無法配置;
3、剛啓動acct功能時,連接追蹤可能無法立即生效,需要稍等片刻後layer7的相關功能纔會被啓用;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章