Next Previous Contents

6. 談談要怎樣 Mangle 封包

現在﹐我們知道如何去挑選那些我們要 mangle 的封包。為了要完善我們的規則﹐我們需要準確無� 的告訴核心﹐什麼� 是我們要對封包做的。

6.1 Source NAT

您想要做 Source NAT﹐是要去將連線的來源地址換成別的什麼的。這就要在它最後要送出去之前﹐於 POSTROUTING 鏈中完成了﹔這是一個非常重要的細節﹐因為它意味著所有在 Linux 主機本身上的其它東西 (routing, packet filtering) 都只看見那個還沒改變的封包。同時﹐這也就是說﹐`-o' (傳出界面) 選項可以派上用場了。

Source NAT 是用 `-j SNAT' 來指定的﹐同時﹐ `--to source' 則指定一個 IP 地址、或一段 IP 地址、以及一個可配選的埠口或一段值域的埠口(僅適用於 UDP 和 TCP 協定)。

## Change source addresses to 1.2.3.4.
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4

## Change source addresses to 1.2.3.4, 1.2.3.5 or 1.2.3.6
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6

## Change source addresses to 1.2.3.4, ports 1-1023
# iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to 1.2.3.4:1-1023

封包偽裝 (Masquerading)

有一個 Source NAT 之特例﹐叫做封包偽裝﹕它只用於動態分配的 IP 地址﹐例如標準的撥接(如果用靜態 IP 地址﹐則使用前述之 SNAT)。

您無需明確地將 masquerading 放進來源地址那裡去﹕它將會使用封包傳出界面作為來源地址。但更重要的是﹐如果該連接(link)斷掉的話﹐那麼連線 (connections﹐無可避免的將失掉) 也會被忘掉﹐當連線用新的 IP 地址回來的時候就會有問題了。

## Masquerade everything out ppp0.
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

6.2 Destination NAT

一旦封包進入﹐會由 PREROUTING 鏈完成處理﹔也就是說﹐除了該主機自己的其它東西(諸如﹕路由、封包過濾) 都將封包看成要送到 `真正' 目的地。另� ﹐那個 `-i' (傳入界面) 選項也可以在這裡使用。

需要修改本機產生的封包之目的地的話﹐那麼 OUTPUT 鏈就可以用上了﹐不過這並不常碰到。

Destination NAT 必須以 `-j DNAT' 來指定使用﹐同時用 `--to destination' 選項指定一個 IP 地址、或一段 IP 地址﹐以及可以配選一個埠口或一段埠口值域(只能用於 UDP 和 TCP 協定上面)。

## Change destination addresses to 5.6.7.8
# iptables -t nat -A PREROUTING -i eth1 -j DNAT --to 5.6.7.8

## Change destination addresses to 5.6.7.8, 5.6.7.9 or 5.6.7.10.
# iptables -t nat -A PREROUTING -i eth1 -j DNAT --to 5.6.7.8-5.6.7.10

## Change destination addresses of web traffic to 5.6.7.8, port 8080.
# iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 \
        -j DNAT --to 5.6.7.8:8080

## Redirect local packets to 1.2.3.4 to loopback.
# iptables -t nat -A OUTPUT -d 1.2.3.4 -j DNAT --to 127.0.0.1

重導向 (Redirection)

在 Destination NAT 有一個特別的情形﹕它是一個簡單的便利﹐完全等同於給傳入界面地址做 DNAT 一樣。

## Send incoming port-80 web traffic to our squid (transparent) proxy
# iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 \
        -j REDIRECT --to-port 3128

6.3 進一步的映對(Mappings)

還有許多 NAT 上面的解決方案是大多數人無需用到的。這裡不妨和那些有興趣的朋友探討一下﹕

同一範圍內的複合地址(Multiple Addresses)之選擇。

如果您已經指定了一段 IP 地址﹐ 而 IP 地址的使用選擇是基於機器所知連線目前最少使用之 IP。它可以提供最原始的平衡負載(load-balancing)。

建立空 NAT 映對

您可以使用 `-j ACCEPT' 目標來讓一個連線通過﹐而繞過 NAT 的處理。

標準的 NAT 行為(Behaviour)

預設的行為是在使用者制定的規則限制內﹐盡可能少的改變連線。換而言之﹐非不得已不要重映對(remap)埠口。

絕對來源埠口映對

如果其它連線已經被映對到新的連線﹐就算對於一個無需 NAT 的連線來說﹐來源埠口的轉換有時或是必須絕對存在的。讓我們假設一個封包偽裝的情形﹐這已經非常普遍了﹕

  1. 一個網頁連線由一台 192.1.1.1 的機器從 port 1024 建立﹐要連接到www.netscape.com port 80。
  2. 它被封包偽裝主機以其自己的 IP 地址(1.2.3.4)進行偽裝。
  3. 該封包偽裝主機嘗試由 1.2.3.4 (它的� 部界面地址) port 1024 來做一個網頁連線至www.netscape.com port 80。
  4. 然後 NAT 程式改變第二個連線的來源埠口為 1025﹐所以這兩個連線不至於相衝(clash)。

當這個絕對來源映對存在之時﹐埠口被拆分為三個等級﹕

任何一個埠口都不會被絕對映對到不同的等級去。

當 NAT 失效時會怎樣﹖

如果沒有辦法如用戶要求那樣獨一無二地映對連線﹐那麼連線就會被擋掉。當一個封包不能夠界定為任何連線的時候﹐結果也一樣﹐因為它們可算是畸形的﹐或者是該機器記憶體耗光了﹐諸如此類。

複合映對、重疊、和相衝(clash)

您可以設定 NAT 規則在同一個範圍之上映對封包﹔NAT 程式足以聰明的去避免相衝。比方說﹐用兩條規則將 192.168.1.1 和 192.168.1.2 這兩個來源地址分別映對到 1.2.3.4﹐是完全可行的。

再來﹐您可以映對到真實的、已用的 IP 地址﹐只要這些地址通過這個映對主機就行。所以﹐如果您獲得一個網路(1.2.3.0/24)﹐但有一個內部網路使用這些地址﹐而另一個使用私有地址 192.168.1.0/24 ﹐您就可以 NAT 那些 192.168.1.0/24 的來源地址到 1.2.3.0 網路之上﹐而無需擔心相衝﹕

# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
        -j SNAT --to 1.2.3.0/24

這同樣適用於那些 NAT 主機自己使用的地址﹕這其實就是封包偽裝如何工作的了(分享偽裝封包地址和來自主機本身封包之 `真實' 地址。 )

更甚者﹐您還可以映對相同的封包到許多不同的目標(targets)上去﹐而且它們都是共享的。例如﹐如果您不想映對任何東西到 1.2.3.5 上去﹐您可以這樣做﹕

# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
        -j SNAT --to 1.2.3.0-1.2.3.4 --to 1.2.3.6-1.2.3.254

改變本機產生的連線之目的地

如果本機產生的封包之目的地改變了(例如﹐用 OUTPUT 鏈)﹐而這樣會導致封包由不同的界面送出去﹐這樣來源地址也跟著變為那個界面。舉例子說﹐改變一個環迴(loopback)封包之目的地由 eth0 送出﹐會讓來源地址也由 127.0.0.1 變成 eth0 的地址﹔而不像其它來源地址映對那樣﹐這是立即完成的。當然﹐所有這些映對在回應封包進入時是顛倒過來的。


Next Previous Contents