ここまでくれば、料理するべきパケットを選別する方法は分かっています。ルール を完全なものにするため、パケットに対してやるべきことを正確にカーネルに指示 する必要があります。
送信元 NAT を行うということは、送信元アドレスを何か別のものに変換するという ことです。これは POSTROUTING チェインのもとで、最終的にパケットが送信される 直前に行われます −これは重要な点で、というのも Linux ボックス自身の上で 行われる他のどんな操作(ルーティング、パケットフィルタリング)も、パケットは 書き換えないということを意味するからです。それはまた、`-o' (送信インタフェース)オプションで実現可能であるということでもあります。
送信元 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
IP マスカレードと呼ばれる送信元 NAT の特殊なケースがあります。これは、 標準的なダイヤルアップ接続などの、IP アドレスが動的に割り当てられる場合 にのみ利用すべきものです(静的に IP アドレスが割り当てられるなら、上記の SNAT を使ってください)。
IP マスカレードをやるのに、送信元アドレスを明示的に指定する必要はありません。 IP マスカレードは、パケットが出て行くインタフェースの送信元アドレスを利用 します。ですがもっと重要なのは、そのリンクが落ちた場合に、(切られてしまった) そのコネクションが忘れられてしまっても、新たに IP アドレスが割り当てられて コネクションが復帰したときに、ほとんど誤動作が起きないということです。
## Masquerade everything out ppp0.
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
これは PREROUTING チェインのもとで、パケットが入ってきたその時に行われます −これは、Linux ボックス自身の上で行われる他のどんな操作(ルーティング、 パケットフィルタリング)も、パケットはその「本当の」宛先を指しているところで 行うからです。それは `-i'(受信インタフェース)オプションで実現可能であると いうことでもあります。
宛先 NAT は、`-j DNAT' を使って指定し、`--to-destination' オプションにより、 特定の IP アドレス、IP アドレスの範囲、そして(UDP, TCP プロトコルの場合のみ) 特定のポート番号やポート番号の範囲を指定します。
## Change destination addresses to 5.6.7.8
# iptables -t nat -A PREROUTING -i eth0 -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 eth0 -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 eth0 \
-j DNAT --to 5.6.7.8:8080
リダイレクションと呼ばれる宛先 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
squid が透過型プロキシとして動作するよう設定する必要があるのに注意すること!
ほとんどの人には全く関係ない、巧妙なテクニックが NAT にはいくつかあります。 ここでは好奇心の強い人のためにドキュメント化しておきます。
ある範囲の IP アドレスが与えられ、使用する IP アドレスを、そのマシンが通信 したうち最も最近利用された IP アドレスをもとに選択します。これにより原始的 な負荷調整が行えます。
全く NAT を用いないコネクションを張らせる指定として `-j ACCEPT' があります。
デフォルトでは、ユーザによって与えられたルールの制約内で、コネクションの 変更を出来る限り小さくするべきです。つまり、その必要がなければ、ポート番号 を再マッピングしてはならないということです。
たとえあるコネクションに NAT が設定されていなくても、 先に張られた別のコネクションがその新たなコネクションにアドレス が重なるようにマッピングされている場合には、 送信元ポート変換が暗黙のうちに行われることがあります。 IP マスカレードのケースを考えると、これはかなり一般的なことです:
この暗黙の送信元マッピングに関して、ポートは三つのクラスに分けられます:
元のポートと異なるクラスのポートに暗黙のうちにマッピングされることは 決してありません。
ユーザが要求するコネクションを一意にマップすることができない場合、 その接続要求は廃棄されます。また、パケットが正しく構成されていなかったり、 NAT ボックスのメモリが不足しているなどの理由で、どのコネクションの一部とも 分類できなかったパケットも同様に破棄されます。
様々なアドレスを属性にしているパケットに対して、ある一つのアドレス をマッピングする 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 のとプライベート・インターネット・アドレスを使っていたとしても、 192.168.1.0/24 のソースアドレスを 1.2.3.0 のネットワークに単純に マッピングするだけで、衝突の恐れなしに NAT 可能です:
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
-j SNAT --to 1.2.3.0/24
同じ理屈が、NAT ボックス自身により使用されるアドレスにもあてはまります −これこそが (マスカレードされるパケットと、ボックス自身から来る「本当の」 パケットの間でインタフェースのアドレスを共有することによる)IP マスカレード の動作なのです。
その上、同じパケットを幾つもの異なるターゲットにマップ可能で、そのマッピング は共有されます。例えば、IP アドレス 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
NAT のコードは、OUTPUT チェインの中に DNAT ルールを挿入することを許可 しますが、カーネル 2.4 では完全にはサポートされていません (可能ではあるのですが、新しい設定オプション、ある程度のテスト、 そしてかなりのコーディングが必要になります。 それは誰かが Rusty にそうしたものを書くと請け負ってくれない場合の話ですが、 僕としては、すぐにそうなるとは期待していません)。
現在ある制限は、宛先をローカルマシンにしか変更できないことで (例:`j DNAT --to 127.0.0.1')、他のどのマシンにも変更できず、 そうでないとリプライが正しく転送されないのです。