Iptables

August 14, 2017

Iptables on ubuntu

查看 iptables 是否安裝

$ whereis iptables
iptables: /sbin/iptables /usr/share/iptables /usr/share/man/man8/iptables.8.gz

How Linux Firewall Works

Iptables firewall 可用於 Linux 內核中用於過濾 packet

Firewall Types

Netfilter 包含 tables;這些 tables 包含 chains;chains 包含單獨的 rules

如果傳遞的 packet 與任何 rules 匹配,則將對該 packet 應用規則 action

action 包含,acceptrejectignorepass 將數據包傳遞給其它規則以進行更多處理。

Netfilter 可以使用 IP address 和 port number 處理傳入或傳出流量。

Netfilter 由 iptables 命令管理和配置。

iptables Firewall Tables

netfilter 主要有三個 tables 可以處理 rule。其處裡順序為 raw -> mangle -> nat -> filter

Table Chains

iptables Firewall Tables 說明的每個 tables 都包含 chains,這些 chains 是 iptables 規則的集合。

可以創建自定義 chain 以保存 rules。

如果 packet 經過本地主機,將由 INPUT chain 規則處理。 如果 packet 要去另一個主機,它將由 OUTPUT chain 規則處理。 FORWARD chain 用於處理已訪問主機但發往另一主機的 packet。

Chain Policy

filter table 中的每個 chain 都有一個策略,該策略是預設操作。

從安全角度來看,應該 DROP 所有進入主機的 packet,並僅接受來自可信來源的 packet。

Adding iptables Rules

add a new rule

$ sudo iptables -A INPUT -i ens33 -p tcp --dport 80 -d 192.168.15.128 -j ACCEPT
# -A 添加新規則,默認情況下,除指定另一個 table,否則所有新規則都將添加到 filter table 中。
# -i 哪個網路介面卡進入主機的流量。如果未指定網路介面卡,則無論網路介面卡如何,該規則都將應用於所有傳入流量。
# -p 指定要處理的 packet protocol,範例為 TCP。
# -dport 指定目標 port number,範例為 80。
# -d 指定目標 IP address。如果未指定目標 IP address,則該規則將應用於 eth1 上的所有傳入流量,而不管 IP address 如何。
# -j 指定要執行的操作或 JUMP 操作,這裡我們使用 ACCEPT Policy 接受 packe。
$ sudo iptables -A OUTPUT -o ens33 -p tcp --sport 80 -j ACCEPT
# -A 用於向 OUTPUT chain 添加規則
# -o 指定用於傳出流量的網路卡介面
# -sport 指定來源 port number

可使用 http 或 https 等服務名稱,而不是 sport 或 dport 上的 port number。服務名稱可以在 /etc/services 檔案中找到。

$ sudo iptables -A INPUT -s 192.168.200.121 -j DROP # Block Specific IP Address in IPtables Firewall
$ sudo iptables -A INPUT -p tcp -s 192.168.200.121 -j DROP # block TCP traffic

Iptables Rules Order

添加 rules 時,會將其添加到 chain 的末尾。 可使用 -I 選項將其添加到頂部。 可以使用 I flag 將規則準確插入到所需的位置。

rules 的順序很重要

$ sudo iptables -I INPUT 2 -i ens33 -p udp -j ACCEPT
$ sudo iptables -I INPUT 3 -i ens33 -p udp --dport 80 -j DROP

第一條規則將接受所有 UDP 流量,然後第二條規則將被忽略,因為第一條規則已經接受了所有 UDP 流量,因此這裡的第二條規則毫無意義。

chain 中規則的順序很重要。

List iptables Rules

$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             Docker               tcp dpt:http
ACCEPT     udp  --  anywhere             anywhere
DROP       udp  --  anywhere             anywhere             udp dpt:80
$ sudo iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  anywhere             Docker               tcp dpt:http
2    ACCEPT     udp  --  anywhere             anywhere
3    DROP       udp  --  anywhere             anywhere             udp dpt:80
$ sudo iptables -L INPUT -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  0.0.0.0/0            192.168.15.128       tcp dpt:80
2    ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0
3    DROP       udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:80
$ sudo iptables -L -n --line-numbers
$ sudo iptables -L -v

使用 -Z 標誌將計數器重置為零

Deleting Rules

$ sudo iptables -D INPUT 3
$ sudo iptables -L INPUT --line-numbers # 原本的第三條規則被刪除
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  anywhere             Docker               tcp dpt:http
2    ACCEPT     udp  --  anywhere             anywhere
$ sudo iptables -L OUTPUT --line-number
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  anywhere             anywhere             tcp spt:http
$ sudo iptables -F OUTPUT
$ sudo iptables -L OUTPUT --line-number
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

使用 -F 時忘記提及 chain 名稱,則將刪除所有鏈規則。

Replacing Rules

$ sudo iptables -I INPUT  -i ens33 -p udp -j ACCEPT
$ sudo iptables -L INPUT --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     udp  --  anywhere             anywhere
$ sudo iptables -R INPUT  1 -i ens33 -p tcp -j ACCEPT #新的規則替換 INPUT chain 中的第一個規則
$ sudo iptables -L INPUT --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  anywhere             anywhere

Listing Specific Table

$ sudo iptables -L -t filter
$ sudo iptables -L -t nat

Iptables User Defined Chain

$ sudo iptables -N cch_chain
$ sudo iptables -L cch_chain
Chain cch_chain (0 references)
target     prot opt source               destination
$ sudo iptables -L cchong_chain
iptables: No chain/target/match by that name.
$ sudo iptables -L cch_chain
Chain cch_chain (0 references)
target     prot opt source               destination
$ sudo iptables -E cch_chain cchong_chain # 從新命名
$ sudo iptables -L cchong_chain
Chain cchong_chain (0 references)
target     prot opt source               destination
$ sudo iptables -L cch_chain
iptables: No chain/target/match by that name.
$ sudo iptables -L cchong_chain
Chain cchong_chain (0 references)
target     prot opt source               destination
$ sudo iptables -X cchong_chain # 刪除 chain
$ sudo iptables -L cchong_chain
iptables: No chain/target/match by that name.

使用 -X 參數,沒給 chain 名稱,則將刪除所有用戶定義的 chains。但,無法刪除 INPUTOUTPUT 等原生 chains。

Redirection to a User Defined Chain

$ sudo iptables -N CCH_ICMP # 建立新 chain
$ sudo iptables -L CCH_ICMP  # 列出 CCH_ICMP chain
Chain CCH_ICMP (0 references)
target     prot opt source               destination
$ sudo iptables -A INPUT -p icmp -j CCH_ICMP # 將此規則重定向至 CCH_ICMP
$ sudo iptables -L CCH_ICMP # 其中有一條規則參照
Chain CCH_ICMP (1 references)
target     prot opt source               destination

Setting The Default Policy for Chains

$ sudo iptables -P INPUT DROP # INPUT chain 丟棄任何 packet,除非編寫規則以允許傳入流量。

SYN Flooding

攻擊者在不完成 TCP handshake 的情況下發送 SYN packets,因此接收主機將有許多打開的連接,使得伺服器變得太忙而無法回應其他客戶端。

使用 iptables 防火牆的 limit module 保護免受 SYN flooding

$ sudo iptables -A INPUT -i ens33 -p tcp --syn -m limit --limit 5/second -j ACCEPT
# 僅指定每秒 5 個 SYN packet。可以根據網路需求調整此值

如果會限制網路,可以使用 SYN Cookie

SYN Cookies

$ sudo vi /etc/sysctl.conf
net.ipv4.tcp_syncookies  1
$ sudo sysctl -p # save and reload

Drop INVALID State Packets

INVALID 狀態 packets 不屬於任何連接的 packet,應該丟棄。

$ sudo iptables -A INPUT -m state --state INVALID -j DROP # DROP 所有傳入的 INVALID packet

Drop Fragmented Packets

Fragmented Packets 是大型 packet 的碎片,應該丟棄。

$ sudo iptables -A INPUT -f -j DROP

Save iptables Rules

重新啟動 service,iptables 所有規則都不會保存,用以下方法保留它們

$ sudo iptables-save > /etc/working.iptables.rules
$ sudo iptables-restore < /etc/working.iptables.rules
$ sudo iptables - save - t filter # 保存特定的表
$ sudo apt-get install iptables-persistent -y
$ sudo netfilter-persistent save
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
$ sudo  netfilter-persistent reload
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables start
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables start

example

Block Facebook on IPtables Firewall

$ whois 157.240.15.35 | grep CIDR
CIDR:           157.240.0.0/16
$ sudo iptables -A OUTPUT -p tcp -d 157.240.0.0/16 -j DROP
$ sudo iptables -L OUTPUT
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             157.240.0.0/16

Block Ping ICMP Requests

$ sudo iptables -A INPUT --proto icmp -j DROP

scenario

Say there is a machine the local ip address of which is 192.168.0.6. You need to block connections on port 21, 22, 23, and 80 to your machine

$ sudo  iptables -A INPUT -s 192.168.0.6 -p tcp -m multiport --dport 21,22,23,80 -j DROP

Ref

iptables