netfilter 和 iptables

一. netfilter

1. 什麼是entfilter 和 iptables

  • netfilter指整個項目名
  • 在這個項目裏面,netfilter特指內核中的netfilter框架,
  • iptables指用戶空間的配置工具。
  • netfilter在協議棧中添加了5個鉤子,允許內核模塊在這些鉤子的地方註冊回調函數,這樣經過鉤子的所有數據包都會被註冊在相應鉤子上的函數所處理,包括修改數據包內容、給數據包標記 或者丟掉數據包等。
  • netfilter框架負責維護鉤子上註冊的處理函數或者模塊,以及它們的優先級。
  • iptables是用戶空間的一個程序,通過netlink和內核的netfilter框架打交道,負責往鉤子上配置回調函數。
  • netfilter框架負責在需要的時候動態加載其它的內核模塊, 有 ip_conntrack、nf_conntrack、NAT subsystem等。

通常使用中 可能會感覺iptables代表了整個項目, 代表了防火牆, 但是在開發者中, 可能netfilter 纔是整個項目.

2. netfilter 鉤子 (hooks)

  • 內核協議棧中,有5個跟netfilter有關的鉤子,數據包經過每個鉤子時,都會檢查上面是否註冊有函數,如果有的話,就會調用相應的函數處理該數據包.

2.1 5個鉤子

  • NF_IP_PRE_ROUTING:
    • 接收的數據包剛進來,還沒有經過路由選擇,即還不知道數據包是要發給本機還是其它機器。
  • NF_IP_LOCAL_IN:
    • 已經經過路由選擇,並且該數據包的目的IP是本機,進入本地數據包處理流程。
  • NF_IP_FORWARD:
    • 已經經過路由選擇,但該數據包的目的IP不是本機,而是其它機器,進入forward流程。
  • NF_IP_LOCAL_OUT:
    • 本地程序要發出去的數據包剛到IP層,還沒進行路由選擇。
  • NF_IP_POST_ROUTING:
    • 本地程序發出去的數據包,或者轉發(forward)的數據包已經經過了路由選擇,即將交由下層發送出去。

2.2 位置圖

                      |
                      |   In
                      ↓
             +-----------------+ 
             | IP_PRE_ROUTING  | 
             +-----------------+    
                      |
                      ↓
             +_________________+            +---------------+
             |  Route table    | ---------> | IP_LOCAL_IN   |
             +_________________+            +---------------+
                      |                             |
                      |                             
                      |                     +_______________+
                      |                     |     local     |
                      |                     +_______________+
                      |                             |
                      |                             |
                      ↓                             ↓   
             +---------------+              +---------------+
             |  IP_FORWARD   |              | IP_LOCAL_OUT  |
             +---------------+              +---------------+
                      |                             |
                      |-----------------------------+
                      |                             
                      ↓                             
             +-----------------+
             | IP_POST_ROUTING |
             +-----------------+
                      |
                      | Out
                      ↓

  • 上面顯示的可以看出, 一個數據包只會經過 下面三種路徑的一種.
    • 本機收到的IP是本機的數據包: IP_PRE_ROUTING -> IP_LOCAL_IN
    • 本機收到目的地IP 不是本地的: IP_PRE_ROUTING -> IP_FORWARD -> IP_POST_ROUTING
    • 本機發出的數據包: IP_LOCAL_OUT -> IP_POST_ROUTING

2.3 iptables 中的表(tables)

  • iptables 是使用表(tables) 來分配管它的規則的(rule) , 根據rule 的作用劃分了幾個表, 比如用啦過濾數據包 的rule 放在了 filter 表中, 用來處理 地址轉換的 rule 放在了 nat 表中, 其中rule 就是 應用在 netfilter 鉤子上的函數, 用來修改 數據包的內容或者過濾數據包, 目前 iptables 支持的表有:
  1. filter

    • filter 表內的 rule 用來過濾數據, 用來控制讓那些數據可以通過, 那些數據不可以通過.
  2. nat

    • nat 表內的 rule 用來控制網絡地址轉換, 控制要不要進行地址過濾, 以及如何修改源地址和目的地址, 從而影響數據包的路由, 達到連通的目的, 是路由器的必備功能.
  3. Mangle

    • 該表內的 rule 用於修改IP數據包頭, 如修改 TTL, 同時也可以爲數據包添加一些標記, 便於後續其他模塊 對數據包處理,( 添加標記是指 網內核skb 結構中添加, 而不是給IP數據包加東西)
  4. raw 在 natfilter 裏面有個 connection tracking功能, 用來追蹤所有的連接, 而且可以看到 raw 表內的 rule 功能給數據包打的標記, 從而控制那些數據包不被 connection tracking 追蹤

  5. security 在cnetos7 中新加的, 用於設置和 SElinux 相關, 主要設置 一些SELinux 標記, 便於和 SELinux 相關的模塊來處理數據包.

2.4 鏈

  • 根據不同功能的 rule 在不同的表內, iptables 將表中的rule 在分類, 讓 rule 屬於 不同的鏈(chain), 有 chain來決定什麼時候觸發 chain 上的 那些rule.

  • iptables 的5個鏈分別對應5個鉤子:

    1. PREROUTING:
      • 數據包經過NF_IP_PRE_ROUTING 會觸發 chain 上的rule
    2. INPUT
      • 數據包經過 IP_LOCAL_IN 時會觸發 chain 上的 rule
    3. FORWARD
      • 數據包經過 IP_FORWARD 時 會觸發 chain 的rule
    4. OUTPUT
      • 數據包經過 IP_LOCAL_OUT時 會觸發chain 的rule
    5. POSTROUTING
      • 數據包經過 IP_POST_ROUTING 時會觸發 chain 的rule
  • 每個表都可以有多個 chains , 但是並不表示每個表都包含了多個 chains, 應爲有些表上的 chains 上時沒有意義的, 如 raw 上只有 connection tracking 有意義.

2.5 每個表包含的 chain

                                    |
                                    |   In
                                    |
                                    ↓                 ++---------------------++
                           +-----------------+        ||  raw                ||
                           | IP_PRE_ROUTING  | ------>||  (connection trak)  ||
                           +-----------------+        ||  mangle             ||
                                    |                 ||  nat (DNAT)         ||
                                    |                 ++---------------------++
                                    ↓                                                 ++-------------++
                           +_________________+            +---------------+           || mangle      ||
                           |  Route table    | ---------> | IP_LOCAL_IN   | --------> || filter      ||
                           +_________________+            +---------------+           || security    ||
                                    |                             |                   || nat {SNAT}  ||
                                    |                             |                   ++-------------++
                                    |                             |
                                    |                     +_______________+
                                    |                     |     local     |
                                    |                     +_______________+
                                    |                             |                   ++---------------------++
                                    |                             |                   ||  raw                ||
         ++----------++             ↓                             ↓                   ||  (connection track) ||
         ||  mangle  ||    +---------------+              +---------------+           ||  mangle             ||
         ||  filter  || <--|  IP_FORWARD   |              | IP_LOCAL_OUT  | --------> ||  nat(DNAT)          ||
         || security ||    +---------------+              +---------------+           ||  filter             ||
         ++----------++             |                             |                   ||  security           ||
                                    |-----------------------------+                   ++---------------------++
                                    |                             
                                    ↓                 ++----------++
                           +-----------------+        ||mangle    ||
                           | IP_POST_ROUTING | -----> ||nat(SNAT) ||
                           +-----------------+        ||          ||
                                    |                 ++----------++
                                    | Out
                                    ↓


  • 這裏以 NF_IP_PRE_ROUTING 爲例:
    • 數據包到了這裏, 首先會執行raw 表中的 PREROUTING (chain) 裏面的 rule,
    • 然後執行 connection tracking, 接着執行 managle 表中 PREROUTING 中的 rule,
    • 最後執行 nat(DNAT) 表中的 PREROUTING 裏的rule
  • 以 filter 爲例:
    • 只能註冊在 IP_LOCAL_IN, IP_FORWARD, 和 IP_LOCAL_OUT中, 所以只支持 INPUT, FORWARD 和OUTPUT 三個 chain

3. iptables 中的規則(Rules)

  • rule 存放在表的忒丁 chain 上, 每個 rule 都有兩部分信息.
    1. Matching
      • matching 是如何匹配一個數據包, 匹配條件很多, 比如, 協議類型, 源/目的 地址, 源/目的 端口, in/out 接口, 保內的數據以及連接狀態.
    2. Targets
      • target 是用於匹配到數據包後 如何做處理
        • DROP: 丟棄數據包, 不做任何處理
        • RETURN: 跳出當前chaing, 該 chain內的後續rule 不執行
        • QUEUE: 將數據包放入用戶空間, 由用戶程序處理
        • ACCEPT: 同意數據包通過, 執行後續 rule
        • 跳轉到其他用戶自定義的 chain 執行

4. iptables 語法

4.1 語法和選項

  • 語法: iptables [-t table] OPTION [chain] rule-specification
    • -t table 指定表名
    • OPTION 指定選項操作
    • chain 指定鏈chain
    • rule-speci 規則說明

4.2 選項

  • table
filter:     默認表( 不使用-t 指定表時的默認), 包含的鏈有 INPUT, FORWARD, OUTPUT 
nat:        在創建新的連接時, 會查看此表. 包含的鏈有 PREROUTING, OUTPUT, POSTROUTING
mangle:     用於修改 數據包, 包含的鏈有: PREROUTING, OUTPUT, INPUT, FORWARD, POSTROUTING
raw:       該表用於和 NOTRACCK 配合設置耿總路由的豁免, 具有需要較高的優先級的鉤子上註冊, 因此 ip conntrack 或者其他表調用之前,  內置的鏈有 PREOUTING, OUTPUT
security:  用於設置強制訪問網絡規則, 配合 selinux 規則使用.
  • OPTIONS:
# 規則相關
-A:     --append 追加規則到所選擇的鏈的末端, 當 源/目的 地址爲多個時, 會爲每個可能的地址配備一個規則.
-I:     --insert 再選中的鏈中插入規則, 可以選擇規則號, 如果沒有指定則默認插入到 第一條
-D      --delete 刪除一條或多規則, 可以刪除規則號, 或者匹配規則
-C      --check 檢查選中鏈 是否存在和規範的規則,
-R      --replace 替換選中鏈中的 規則, 如果 源/目的 地址有多個, 會設置失敗, 規則號從 1開始

# 鏈相關
-N      --new-chain chain   創建一個新的用戶定義鏈.
-L      --list              列出選中鏈的所有規則, 如果沒有選擇鏈, 則列出所有, 常用於配合 -n (不使用 dns解析),
-F      --flush             清空選中鏈的 所有規則
-X      --delete-chain      刪除用戶自定義的空鏈.
-E      --rename-chain      重命名鏈
-P      --policy chain      指定鏈上到的 默認策略(ACCEPT, DROP, REJECT)

# 重要參數
-i:     --in-interface  指定接受 數據包的接口, (僅用作INPUT, FORWARD, PREROUTING 鏈), 可以使用 ! 符號表示取反, 
-o      --out-interface 指定發出數據包的接口 (作用 OUTPUT, FORWARD, OUTROUTING 鏈), 可用 ! 取反
-p:     --protocol      指定協議, 
        --sport:            源端口
        --dport:            目的端口
        --icmp-type:        指定協議爲 icmp 的類型,(Ping)
-s:     --source address    指定該條規則的定的源, 可以是 主機名, 網絡名, ip網段(掩碼), 也可以是 ip地址
-d:     --destination addr 指定該條規則的 目的地, 地址和 source 一樣
-m:     --match match   指定要使用的匹配項, 測試特定的擴展模塊, 匹配的合集構成了條件
-j:     --jump target   指定給你規則目標, 即, 如果匹配成功, 如何去做, 目標可以是用戶定義的鏈, 或者一個擴展.
-g:     --goto chain    指定用戶的 鏈中繼續處理 和 jump 不同, 彙報不會繼續.


# 其他選項
-v:     --verbose   更詳細的顯示
-w:     --wait  設置抓用鎖, 等待時間
-n:     --numeric 數字輸出, ip和 端口號 使用 數字顯示
  • -m 指定匹配模塊以及擴扎模塊

mulitiport:     指定多端口, 最大15個, 端口可以是 N-M,或範圍, 這些端口只能是同一個協議下的. 如 udp, tcp, dccp, sctp
            --dport     目的端口
            --sport     源端口
iprange:        指定ip範圍 
                --src-range 192.168.1.100-192.168.1.200  # 範圍內的源ip
                --dest-range

time:          如果分組到達時間在給定範圍內, 則匹配, 所有選項都可以設置,
                該項可以設置定時允許訪問網絡, 定時關閉訪問.
                --datestart hh:mm[:ss]      開始時間
                --datestop hh:mm[:ss]           結束時間

                --monthdays:    指定每月的 day1,day2... 通過匹配
                --weekdays:     指定每週的 day1, day2...  通過匹配


icmp:           如果協議是icmp , 則可以用這個選項
            --icmp-type {type[/code] |typename}
                允許指定ICMP烈性, 可以是數字類型, 名稱, 代碼, 或二者ICMP類型之一 iptables -p icmp -h

mac:            源端mac 匹配
  
limit:          限制, 該模塊用作有限速率匹配,  可以結合日誌做限速日誌,
            --limit 速率[秒/分/時/天][second/minute/hour/day]
                    最大平均速率, 指定值, 默認是3小時

            --limit-burst NUM
                    匹配最大的初始分組, 當達到上面設置的值, 將可以突破 NUM 次

hashlimit:      hashlimit 是使用hash 算法來記錄匹配一組連接的速率. 
                分組可以由每個主機組(源/目的 地址) 和/或 端口來匹配.
                可以使用N package.

length:         用與匹配長度.

string:         對報文中的應用層數據做字符串模式匹配檢測, (通過算法實現)
            --algo(bm|kmp):     字符匹配查找時使用的算法
            --string 'STRING'   查找的字符
            --hex-string "HEX_STRING" : 使用16進制格式

connlimit:      每個IP併發連接數量限制
            --connlimit-upto n  連接數小於 n 匹配
            --connlimit-above n 連接數大於 n 匹配

state:          追蹤請求和相應之間報文狀態:
                5種狀態: 
                    INVALID: 無法識別的連接
                    ESTABLISHED 已建立的連接
                    NEW,        新連接請求
                    RELATED,    相關聯的連接 的一個新請求 
                    UNTRACKED   未追蹤的連接
                規則:
                    對進入的 ESTABLISHED 都應該放行
                    對出去的 ESTABLISHED 都應該放行
                    檢查管理 進入狀態的 NEW 連接
                    拒絕 進出 的 INVAIED 


ipvs:           匹配ipvs 連接特性
            --ipvs:     分組屬於ipvs 連接
            --vproto proto :    匹配vip 協議, 按 編號或名稱, 如 TCP
            --vaddr:    vip 地址,
            --vport:    匹配vip 端口號
            --vdir:     vip 報文流向
            --vmethod:  ipvs 轉發方式
  • 處理動作
ACCEPT:     允許數據包通過
DROP:       丟棄數據包, 不迴應
REJECT:     拒絕數據包通過, 會返回響應信息
LOG:        在日誌中記錄信息, 並放給下一個規則
QUEUE:      防火牆將數據包交給用戶空間
RETURN:     防火牆執行當前鏈的 後續 Rule, 並返回到調用鏈
REDIRECT:   端口從定向
MARK:       做防火牆標記
DNAT:       目標地址轉化
SNAT:       源地址轉換
MASQUEREAD: 地址僞裝

5. iptables 實戰示例

  1. 查看當前防火牆狀態

  1. 首先爲ssh 端口開放

  1. 此時可以看到默認規則是accept, 將其改爲 DROP 然後測試

  1. 開放 TCP 的 80端口

  • 此時會發現由於設置了 -P OUTPUT DROP 所以本機無法建立新的連接.
  • 所以需要設置 -P OUTPUT ACCEPT, 不過此處我使用了 -m state --state NEW,ESTABLISHED -j ACCEPT 對新建立的連接和 已建立的連接,放行

  1. 不讓其他主機ping 本機, 但是本機可以ping 其他地址
  • 這裏需要準備規則有
      1. 禁止其他地址的 icmp 協議進入, 或者本機 INPUT表默認是 DROP.
      1. 本機 OUTPUT 需要允許 ICMP協議包, 或者允許新建的連接和已建立的連接 (state NEW,ESTABLISHED)
      • -A OUTPUT -p icmp -j ACCEPT

6. iptables nat 轉發實例

6.1 環境

  • 網絡:

    • 外網: 192.168.10.0/24
    • 內網: 192.168.20.0/24
  • 服務端:

    • 外網IP: 192.168.10.11/24
    • 內網IP: 192.168.20.11/24
  • 客戶端:

    • IP: 192.168.20.3/24
  • 服務機

  • 客戶機

6.2 配置操作

  1. 服務端開啓內核的 ip 轉發
  2. 需要將服務端的 內網接入數據包配置轉發,
  3. 將客戶端的 默認路由設置爲 服務端的內網IP

6.3 操作

  1. 服務端開啓內核的轉發
[root@node10011 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf 
[root@node10011 ~]# grep forward /etc/sysctl.conf 
net.ipv4.ip_forward = 1
[root@node10011 ~]# sysctl -p
-------------------
# 或臨時生效
[root@node10011 ~]# echo 1 >  /proc/sys/net/ipv4/ip_forward
  1. 添加IP 轉發規則

  • iptables -t nat -I POSTROUTING -d 192.168.20.0/24 -j ACCEPT --to 192.168.10.11

  1. 客戶端添加默認路由信息
[fangfc@node10003 ~]$ ip route
169.254.0.0/16 dev eno33554960  scope link  metric 1003 
192.168.20.0/24 dev eno33554960  proto kernel  scope link  src 192.168.20.3 
[fangfc@node10003 ~]$ sudo ip route add default via 192.168.20.11 dev eno33554960
[fangfc@node10003 ~]$ 
[fangfc@node10003 ~]$ ip route
default via 192.168.20.11 dev eno33554960 
169.254.0.0/16 dev eno33554960  scope link  metric 1003 
192.168.20.0/24 dev eno33554960  proto kernel  scope link  src 192.168.20.3 
  • 添加DNS
    • vi /etc/resolv.conf

  1. 測試

END

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