1. Iptables 設定檔¶
RHEL / CentOS / Fedora Linux 發行版中預設的設定檔是:
/etc/sysconfig/iptables – 系統執行指令碼通過讀取該檔案來啟用防火牆功能。
2. 基本操作:顯示預設規則¶
在命令列視窗輸入下面的指令:
iptables --line-numbers -n -L
其中 –line-numbers 參數表示給每行規則前面加個編號; -n 表示以數字形式顯示 IP 位址和連接埠等內容;-L 表示列出所有鏈(chain)中的規則。可以通過 iptables --help 來查看所有可用參數的含義。
可以得到類似下面的輸出(其中 # 號開頭的行為注釋說明):
# 下面是入站鏈(Chain INPUT)
Chain INPUT (policy ACCEPT)
num target prot opt source destination
# 下面的 RH-Firewall-1-INPUT 是該入站鏈 INPUT 的一條規則
# 即,將所有入站的串連交由後面的 RH-Firewall-1-INPUT 鏈 來處理
1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0
# 轉寄鏈
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0
# 出站鏈
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
# 下面 1~8 是入站鏈 RH-Firewall-1-INPUT 中的所有規則(rule)
Chain RH-Firewall-1-INPUT (2 references)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 255
3 ACCEPT udp -- 0.0.0.0/0 1.2.3.4 udp dpt:5353
4 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53
5 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
6 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:53
8 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
3. 基本操作:啟用防火牆¶
這裡的指令都是從 Linux 控制終端(命令列)直接輸入的。
輸入下面的兩條指令來啟用防火牆:
chkconfig iptables on
service iptables start
其中上一條是將 iptables 加入到系統服務,隨系統啟動而啟動;下一條是直接啟動 iptables 服務。
重起防火牆:
service iptables restart
停止防火牆:
service iptables stop
4. 基本操作:其它 iptables 操作指令¶
其它常用的通過 Linux 命令列(控制終端)對 iptables 進行操作的指令,請參考 Linux iptables 添加規則的指令。
5. 理解防火牆¶
上面列出的防火牆(iptables)中有 4 個鏈:
INPUT – 這是預設用來處理進入系統的資料包的規則集合。可以用來開啟或關閉傳入連接埠(如 80、443、25 和 110 等)和 IP 位址/子網(如 1.2.3.4/29)。
OUTPUT – 這是預設用來處理由系統產生(發出)的資料包的規則集合。可以用來開啟或關閉傳出連接埠和 IP 位址/子網。
FORWARD – 這也是一個預設的鏈,當資料包需要通過別的介面發送的時候就使用它。例如,網卡 eth0 串連到 ADSL/Cable 貓,eth1 串連到本地 LAN 的時候,可以使用 FORWARD 鏈溝通 LAN 與互連網,實現發送與接收。
RH-Firewall-1-INPUT - 這是一個使用者自訂的鏈。它被 INPUT 、 OUTPUT 和 FORWARD 鏈調用。
包匹配規則¶
每個包都從鏈的第一條規則開始匹配。
當它匹配到一條規則的時候才會被處理。
如果匹配到一條規則,會被跳轉到特定的目標(如 REJECT, ACCEPT, DROP)。
目標含義¶
ACCEPT 表示接受該資料包。
REJECT 表示丟棄該資料包,並且向遠程主機發送一條錯誤資訊。
DROP 表示丟棄該資料包,並且不向遠程主機或寄件者提供錯誤資訊。
6. 配置 /etc/sysconfig/iptables 檔案¶
雖然可以通過 iptables 指令來編輯防火牆規則,可是對於大量的規則來說一條一條的輸入總是很麻煩,實際上可以直接按照正確格式編輯 iptables 的設定檔,然後重新載入 iptables 即可使之生效。
要編輯 /etc/sysconfig/iptables,輸入:
# vi /etc/sysconfig/iptables
可以看到檔案中儲存的前述預設規則顯示如下:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 1.2.3.4 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
其中 -j 參數表示 jump 跳轉到。
可以看到其中的規則形式與我們通過命令列來輸入的規則是一樣的,因為啟用 iptables 的時候就是將此檔案中的指令一行一行的自動載入的,就像批處理一樣。
DROP 所有通訊¶
找到規則:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
上述規則表示預設接受(ACCEPT)所有三個鏈(INPUT、FORWARD、OUTPUT)上的通訊。可以將前面兩個改為預設丟棄(DROP)(因為本機發出的通訊一般是預設接受的,不需要改動):
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
記錄(LOG)並丟棄(DROP)發送欺騙資訊的源地址¶
在最後一行 COMMIT 之前添加如下規則:
-A INPUT -i eth0 -s 10.0.0.0/8 -j LOG --log-prefix "IP DROP SPOOF "
-A INPUT -i eth0 -s 172.16.0.0/12 -j LOG --log-prefix "IP DROP SPOOF "
-A INPUT -i eth0 -s 192.168.0.0/16 -j LOG --log-prefix "IP DROP SPOOF "
-A INPUT -i eth0 -s 224.0.0.0/4 -j LOG --log-prefix "IP DROP MULTICAST "
-A INPUT -i eth0 -s 240.0.0.0/5 -j LOG --log-prefix "IP DROP SPOOF "
-A INPUT -i eth0 -d 127.0.0.0/8 -j LOG --log-prefix "IP DROP LOOPBACK "
-A INPUT -i eth0 -s 169.254.0.0/16 -j LOG --log-prefix "IP DROP MULTICAST "
-A INPUT -i eth0 -s 0.0.0.0/8 -j LOG --log-prefix "IP DROP "
-A INPUT -i eth0 -s 240.0.0.0/4 -j LOG --log-prefix "IP DROP "
-A INPUT -i eth0 -s 255.255.255.255/32 -j LOG --log-prefix "IP DROP "
-A INPUT -i eth0 -s 168.254.0.0/16 -j LOG --log-prefix "IP DROP "
-A INPUT -i eth0 -s 248.0.0.0/5 -j LOG --log-prefix "IP DROP "
記錄並丟棄所有通訊包¶
找到下面的行:
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
它表示預設將所有不符合之前規則的通訊資料包 REJECT 掉。這是一種比較禮貌的做法。通常那些不符合前述規則的包也不是什麼好東西,所以我們可以直接丟棄而不回複出錯資訊。將其編輯為:
-A RH-Firewall-1-INPUT -j LOG
-A RH-Firewall-1-INPUT -j DROP
COMMIT
上面第一行先記錄,第二就直接將其丟棄。這實際上是針對所有通訊的一種預設操作。
開啟連接埠¶
要開啟 80 連接埠(HTTP 伺服器連接埠),在 COMMIT 一行之前(準確說應該是在預設操作之前,下同)添加如下規則:
-A RH-Firewall-1-INPUT -m tcp -p tcp --dport 80 -j ACCEPT
-p tcp 表示僅針對 tcp 協議的通訊。–dport 指定連接埠號碼。
要開啟 53 連接埠(DNS 伺服器連接埠),在 COMMIT 一行之前添加如下規則:
-A RH-Firewall-1-INPUT -m tcp -p tcp --dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -m udp -p tcp --dport 53 -j ACCEPT
同時針對 tcp 和 udp 協議開啟 53 連接埠。
要開啟 443 連接埠(HTTPS 加密串連伺服器連接埠),在 COMMIT 一行之前添加如下規則:
-A RH-Firewall-1-INPUT -m tcp -p tcp --dport 443 -j ACCEPT
要開啟 25 連接埠(SMTP 郵件伺服器連接埠),在 COMMIT 一行之前添加如下規則:
-A RH-Firewall-1-INPUT -m tcp -p tcp --dport 25 -j ACCEPT
另外還可以更加具體的進行規定,比如:
僅允許來自 192.168.1.0/24 的 SSH 串連¶
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 22 -j ACCEPT
為 192.168.1.0/24 開啟列印服務通訊¶
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 631 -j ACCEPT
允許合法的 NTP Client Access Server¶
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -m state --state NEW -p udp --dport 123 -j ACCEPT
開啟 FTP 連接埠 21 (ftp)¶
-A RH-Firewall-1-INPUT -m state --state NEW -p tcp --dport 21 -j ACCEPT
儲存並關閉該檔案(Ctrl+C, :wq)。編輯 /etc/sysconfig/iptables-config,輸入:
# vi /etc/sysconfig/iptables-config
確保 ftp 模組已經載入:
IPTABLES_MODULES="ip_conntrack_ftp"
要重新啟動防火牆,輸入以下指令:
# service iptables restart
# iptables -vnL --line-numbers
7. 編輯 /etc/sysctl.conf 以抵禦 DoS 和 Syn 攻擊¶
編輯檔案 /etc/sysctl.conf 以協助抵禦一些類型攻擊是挺有效,添加或者更改為如下參數設定:
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
#net.ipv4.icmp_ignore_bogus_error_messages = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
8. 變通的配置方式¶
下面是另一種變通的方式來配置防火牆,這樣就不需要編輯 /etc/sysconfig/iptables 等檔案了,而是建立一個類似於下面代碼的指令碼:
#!/bin/bash
# 一個防火牆自動設定指令碼範例
IPT="/sbin/iptables"
SPAMLIST="blockedip"
SPAMDROPMSG="BLOCKED IP DROP"
SYSCTL="/sbin/sysctl"
BLOCKEDIPS="/root/scripts/blocked.ips.txt"
# 防禦一些攻擊
echo "Setting sysctl IPv4 settings..."
$SYSCTL net.ipv4.ip_forward=0
$SYSCTL net.ipv4.conf.all.send_redirects=0
$SYSCTL net.ipv4.conf.default.send_redirects=0
$SYSCTL net.ipv4.conf.all.accept_source_route=0
$SYSCTL net.ipv4.conf.all.accept_redirects=0
$SYSCTL net.ipv4.conf.all.secure_redirects=0
$SYSCTL net.ipv4.conf.all.log_martians=1
$SYSCTL net.ipv4.conf.default.accept_source_route=0
$SYSCTL net.ipv4.conf.default.accept_redirects=0
$SYSCTL net.ipv4.conf.default.secure_redirects=0
$SYSCTL net.ipv4.icmp_echo_ignore_broadcasts=1
#$SYSCTL net.ipv4.icmp_ignore_bogus_error_messages=1
$SYSCTL net.ipv4.tcp_syncookies=1
$SYSCTL net.ipv4.conf.all.rp_filter=1
$SYSCTL net.ipv4.conf.default.rp_filter=1
$SYSCTL kernel.exec-shield=1
$SYSCTL kernel.randomize_va_space=1
echo "Starting IPv4 Firewall..."
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
# 載入模組
modprobe ip_conntrack
[ -f "$BLOCKEDIPS" ] && BADIPS=$(egrep -v -E "^#|^$" "${BLOCKEDIPS}")
# interface connected to the Internet
PUB_IF="eth0"
#Unlimited traffic for loopback
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# DROP all incomming traffic
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
if [ -f "${BLOCKEDIPS}" ];
then
# 建立一個新的 iptables 列表
$IPT -N $SPAMLIST
for ipblock in $BADIPS
do
$IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG "
$IPT -A $SPAMLIST -s $ipblock -j DROP
done
$IPT -I INPUT -j $SPAMLIST
$IPT -I OUTPUT -j $SPAMLIST
$IPT -I FORWARD -j $SPAMLIST
fi
# Block sync
$IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "Drop Sync"
$IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -j DROP
# Block Fragments
$IPT -A INPUT -i ${PUB_IF} -f -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "Fragments Packets"
$IPT -A INPUT -i ${PUB_IF} -f -j DROP
# Block bad stuff
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL ALL -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "NULL Packets"
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -j DROP # NULL packets
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "XMAS Packets"
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP #XMAS
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "Fin Packets Scan"
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -j DROP # FIN packet scans
$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
# Allow full outgoing connection but no incomming stuff
$IPT -A INPUT -i ${PUB_IF} -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -o ${PUB_IF} -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# Allow ssh
$IPT -A INPUT -i ${PUB_IF} -p tcp --destination-port 22 -j ACCEPT
# Allow http / https (open port 80 / 443)
$IPT -A INPUT -i ${PUB_IF} -p tcp --destination-port 80 -j ACCEPT
#$IPT -A INPUT -o ${PUB_IF} -p tcp --destination-port 443 -j ACCEPT
# allow incomming ICMP ping pong stuff
$IPT -A INPUT -i ${PUB_IF} -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
#$IPT -A OUTPUT -o ${PUB_IF} -p icmp --icmp-type 0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow port 53 tcp/udp (DNS Server)
$IPT -A INPUT -i ${PUB_IF} -p udp --dport 53 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
#$IPT -A OUTPUT -o ${PUB_IF} -p udp --sport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -i ${PUB_IF} -p tcp --destination-port 53 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
#$IPT -A OUTPUT -o ${PUB_IF} -p tcp --sport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Open port 110 (pop3) / 143
$IPT -A INPUT -i ${PUB_IF} -p tcp --destination-port 110 -j ACCEPT
$IPT -A INPUT -i ${PUB_IF} -p tcp --destination-port 143 -j ACCEPT
##### START 在下面添加上自己的特殊規則 ######
#
#
##### END 自己特殊規則結束 ############
# Do not log smb/windows sharing packets - too much logging
$IPT -A INPUT -p tcp -i ${PUB_IF} --dport 137:139 -j REJECT
$IPT -A INPUT -p udp -i ${PUB_IF} --dport 137:139 -j REJECT
# log everything else and drop
$IPT -A INPUT -j LOG
$IPT -A FORWARD -j LOG
$IPT -A INPUT -j DROP
exit 0