|
網絡地址轉換:NAT Netfitler為NAT在內核中維護了一張名為nat的表,用來處理所有和地址映射相關的操作。諸如filter、nat、mangle抑或raw這些在用戶空間所認為的“表”的概念,在內核中有的是以模塊的形式存在,如filter;有的是以子系統(tǒng)方式存在的,如nat,但它們都具有“表”的性質。因此,內核在處理它們時有很大一部操作都是相同的,例如表的初始化數據、表的注冊、鉤子函數的注冊等等。關于NAT表的初始化模板數據和表的注冊流程并不是本文的重點,大家可以對照第四篇博文中filter表的相關分析來研究。本文還是側重于從整體上對整個NAT子系統(tǒng)的設計思想和原理進行,當然,有時間我還是會簡單和大家分析一NAT表的東西。因為最近確實太忙了,本來想著在四月份結束這個系列,無奈一轉眼就晃到了五月份,做IT的娃,都不容易??! 通過前面的幾篇文章我們已經知道,NAT的設計是獨立于連接跟蹤系統(tǒng)的,即連接跟蹤是NAT的基礎框架,我們還了解到連接跟蹤不會修改數據包,它只是負責維護數據包和其所屬的業(yè)務會話或數據連接狀態(tài)的相關信息而已。連接跟蹤最終是被iptables模塊所使用的,它所定義的那些狀態(tài)信息如NEW、ESTABLISHED、RELEATED等等,NAT統(tǒng)統(tǒng)不用關心。 根據前面的hook函數掛載圖我們可以清晰的知道,對于那些需要被本機轉發(fā)的數據包,注冊在NF_IP_PRE_ROUTING點的ip_nat_in ()函數完成對其目的地址轉換的操作,注冊在NF_IP_POST_ROUTING點的ip_nat_out()函數完成源地址轉換任務。如果在編譯Linux內核源碼時打開了CONFIG_IP_NF_NAT_LOCAL選項,則注冊在NF_IP_LOCAL_OUT和NF_IP_LOCAL_IN點的hook函數就會工作,最常見的用法的是用NF_IP_LOCAL_OUT點的ip_nat_local_fn()函數來改變本機發(fā)出報文的目的地址。至于注冊在NF_IP_LOCAL_IN點的ip_nat_fn()函數一般不會起作用,只是當數據包到達該HOOK點后會例行被調用一下。因為,NAT的所有規(guī)則只可能被配置到nat表的PREROUTING、POSTROUTING和OUTPUT三個點上,一般也很少有人去修改那些路由給本機的報文的源地址。 NAT的分類如下圖所示:相信大家在看iptables用戶指南都見過這么一句解釋: 只有每條連接的第一個數據包才會經過nat表,而屬于該連接的后續(xù)數據包會按照第一個數據包則會按照第一個報所執(zhí)行的動作進行處理,不再經過nat表。Netfilter為什么要做這個限制?有什么好處?它又是如何實現的?我們在接下來的分析中,將一一和大家探討這些問題。 在ip_nat_rule.c文件中定義了nat表的初始化數據模板nat_table,及相應的target實體:SNAT和DNAT,并將其掛在到全局xt[PF_INET].target鏈表中。關于NAT所注冊的幾個hook函數,其調用關系我們在前幾篇博文中也見過:
因此,我們的核心就集中在ip_nat_in()上。也就是說,當我們弄明白了ip_nat_fn()函數,你就差不多已經掌握了nat的精髓。ip_nat_in()函數定義定在ip_nat_standalone.c文件里。連接跟蹤作為NAT的基礎,而建立在連接跟蹤基礎上的狀態(tài)防火墻同樣服務于NAT系統(tǒng)。 關于ip_nat_fn()函數我們還是先梳理整體流程,以便大家對其有一個宏觀整體的把握,然后我們再來分析其實現細節(jié)。這里需要大家對連接跟蹤的狀態(tài)躍遷有一定了了解。
從流程圖可以看出,牽扯到的幾個關鍵函數都土黃色標注出來了。ip_nat_setup_info()函數主要是完成對數據包的連接跟蹤記錄ip_conntrack對象中相應成員的修改和替換,而manip_pkt()中才是真正對skb里面源/目的地址,端口以及數據包的校驗和字段修改的地方。
目的地址轉換:DNAT DNAT主要適用于將內部私有地址的服務發(fā)布到公網的情形。情形如下:
服務器上架設了 |