IPNAT(5)

名称
ipnat, ipnat.conf - IP NAT ファイルの形式

解説
ipnat が受け付けるファイルの形式は、以下の文法で記述されるものです。

ipmap :: = mapblock | redir | map .
map ::= mapit ifname ipmask "->" dstipmask [ mapport ] mapoptions.
map ::= mapit ifname fromto "->" dstipmask [ mapport ] mapoptions.
mapblock ::= "map-block" ifname ipmask "->" ipmask [ ports ] mapoptions.
redir ::= "rdr" ifname ipmask dport "->" ip [ "," ip ] rdrport rdroptions .
dport ::= "port" number [ "-" number ] .
ports ::= "ports" number | "auto" .
rdrport ::= "port" number .
mapit ::= "map" | "bimap" .
fromto ::= "from" object "to" object .
ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask .
dstipmask ::= ipmask | "range" ip "-" ip .
mapport ::= "portmap" tcpudp portspec .
mapoptions ::= [ tcpudp ] [ "frag" ] [ age ] [ clamp ] .
rdroptions ::= [ tcpudp | protocol ] [ rr ] [ "frag" ] [ age ] [ clamp ] .
object  = addr [ port-comp | port-range ] .
addr    = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
port-comp = "port" compare port-num .
port-range = "port" port-num range port-num .
rr ::= "round-robin" .
age ::= "age" decnumber [ "/" decnumber ] .
clamp ::= "mssclamp" decnumber .
tcpudp ::= "tcp/udp" | "tcp" | "udp" .
protocol ::= protocol-name | decnumber .
nummask ::= host-name [ "/" number ] .
portspec ::= "auto" | number ":" number .
ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers .
number ::= numbers [ number ] .
numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .

これに加え、# はコメントの開始として使用され、 NAT ルールと共に行末に登場する (前述) か、 それだけの行に登場します。 空行は無視されます。

標準的な NAT 機能では、ひとつのルールは map で始まり、 その後にインタフェースの指定が続きます。そのインタフェースから パケットが出て行く際にソースアドレスが書き換えられます。

書き換えられるパケットの選択は、もとのソースアドレスとの照合のみで 行なわれます。IP アドレスの指定にはネットマスクを指定する必要が あります。

もとのアドレスと置き換えられるアドレスは、IP番号/ネットマスクの組から 選ばれます。すべて 1 のネットマスクは、ホスト名が正しいことを表します。 1 が 31 個からなるネットマスク (255.255.255.254) は、ブロードキャスト アドレスとネットワークアドレスを取ったあとでホスト IP 番号を割り当てる 余裕がないため、正しくないと見なされます。

TCP パケットと UDP パケットの再マップの際には、ソースポート番号の変更 も可能です。TCP, UDP パケットともども、それぞれの規則で選択が可能です。 これらは、規則のうしろに再マップ先のポート番号の範囲を、 port-number:port-number の形式で指定します。

コマンド
IP フィルタの NAT コードが認識するコマンドが 4 個あります:

map アドレスもしくはネットワークひとつを、統制なしのラウンドロビン法で 他のアドレスに写像するときに用います。

rdr ある IP アドレスとポートの組から別の組に、パケットをリダイレクトする ときに用います。

bimap
    外部 IP アドレスと内部 IP アドレスとの間で双方向 NAT を設定するときに 用います。

map-block
    IP アドレスに基づく静的な変換を設定します。アドレスを絞り込み、目的の範囲に 収まるように変換するアルゴリズムに基づくものです。

照合処理

基本的な NAT 機能とパケットのリダイレクトにおいては、プロトコルとともに 変更可能性のあるアドレスを用いて、あるパケットを変更せねばならないか どうかをチェックします。 それぞれの規則の "->" の左辺は、その規則のパケット照合処理 部分です。

パケットの照合処理は、より複雑な比較が可能なように拡張されました。 変換されるアドレス部分においては、 IP アドレスとポート番号の比較は、ipf で使用可能な式を使用可能です。 単純な NAT ルールは次のように記述可能です:

map de0 10.1.0.0/16 -> 201.2.3.4/32

または

map de0 from 10.1.0.0/16 to any -> 201.2.3.4/32

"from" 節または "to" 節の前に感嘆符 ("!") を付けることで、 その節の否定を表すことができます。但し、map ルール中の "from" の否定や、rdr ルール中の "to" の否定は使えない可能性があることに 注意して下さい。このようなルールは次のようになります:

+map de0 from 10.1.0.0/16 ! to 10.1.0.0/16 -> 201.2.3.4/32

IP アドレスとポート番号のみ、比較対象にできます。 これは、すべての NAT ルールで使用可能です。

コマンド修飾語
各ルールの最後に、修飾語を使用してルールの動作を変更可能です。 修飾語は次の通りです:

protocol
    特定のプロトコルを、名前 (/etc/protocols にあるもの) か数値で指定可能です。 TCP および UDP の両方をサポートするための特殊ケースとして、 名前 tcp/udp が許されています。

round-robin
    この項を持つルールが成功裏に使用されると、 このルールは使用可能なルールの底に置かれます。 これにより、 適合する左辺を持つ各ルールが順番に一度ずつ使用されるようになります。

frag
    この修飾語は、現在のところ NAT 動作に影響ありません。

age NAT 設定全体に対して大域的に使用可能なタイムアウトよりも 厳密なものが使用したい場合、非 TCP においてはこれを使用して タイムアウトを設定可能です。

変換処理

"->" の右辺は、それ以前の制約条件との照合が既に成功している場合に、その パケットに書き込まれるアドレスとポートを指定する部分です。リダイレクトの 場合 (rdr) が最も単純です。新しいデスティネーションアドレスを その中で指定します。 map 規則に対しては、デスティネーションアドレスは、新しいアドレス の組 (ソースとデスティネーション) が一意的であると知られているアドレス になります。パケットが TCP か UDP パケットの場合、デスティネーション ポートとソースポートもこの等式に含めます。 アドレスの組が既に存在する場合、IP フィルタは、まず portmap で 指定した有効範囲内でポート番号を 1 つ増やします。そうしても一意的な アドレスの組が得られない場合、指定されたネットマスクの範囲内で ソースアドレスを 1 つ増やします。一意的なアドレスの組が決して得られない 場合、パケットは変換されません。map-block では、新規アドレスの組、 フリーなアドレスの組、一意的なアドレスの組を検索するやりかたがより限定 されます。ここでは、ポートの有効範囲に加えて、新しいソースアドレスを 何にするかを決定するアルゴリズムを使用します。IP アドレスは決して 変更されませんし、ポート番号も割り当てられた範囲を越えるものは 変更されません。

カーネルプロキシ

IP フィルタには、カーネルにロードされるコードの中に組み込まれた単純な プロキシがいくつか付いてきます。これにより、パケットをユーザプログラムを 通させずに 2 番目のチャネルを開けておくことが可能となります。

透過型プロキシ

真の透過型プロキシ処理 (transparent proxying) は、実際の発信元と コネクションのアドレスを決定するため、/dev/ipnat 経由で検索を 行なうプロキシプログラムを用いて、localhost (127.0.0.1) のポートに 対応付けるリダイレクト (rdr) 規則を用いて行なう必要があります。

負荷分散

rdr と組み合わせて 2 個のオプションを使用可能です。 これにより、原始的なラウンドロビンベースの負荷分散をサポートします。 最初のオプションは、rdr 用に 2 番目の終点を、次のように指定します:

rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp

これにより、203.1.2.3 と 203.1.2.4 へ交互に接続を送ります。 より多くのサーバに負荷を分散したい場合には、次のようにします:

rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp round-robin
rdr le0 203.1.2.3/32 port 80 -> 203.1.2.5 port 80 tcp round-robin

この場合、接続は 203.1.2.3 にまず向けられ、次に 203.1.2.4 に向けられ、 そして 203.1.2.5 に向けられ、最後に 203.1.2.3 に戻ります。 これを実現する際、必要に応じて自動的に、 ルールがリストの先頭から取り除かれて最後に追加されます。 これは、"ipnat -l" を使用したルール表示には影響せず、 内部的な適用順序にのみ影響します。

使用例

本セクションでは、map コマンドとその変形を扱います。

ppp0 インタフェース経由で、内部で使用する IP 番号がネットワーク 10 の パケットを、ISP (インターネットサービスプロバイダ) が提供してくれた 209.1.2.0 (8 ビットサブネット) に変更する場合、以下の規則を使います。

map ppp0 10.0.0.0/8 -> 209.1.2.0/24

ここで、16,000,000 個以上の IP アドレスを 254 個に絞り込もうとすること が問題なのは明らかでしょう。スコープを広げるために、TCP と UDP については ポート再マップを使うこともできます。

map ppp0 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000

これで、ネットワーク 10 で利用可能な空間のうち、不足分は ``アドレス'' 527,566 個分だけになります。これらの規則を結合させるとすると、次の ような指定が必要となります。

map ppp0 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000
map ppp0 10.0.0.0/8 -> 209.1.2.0/24

その結果、TCP/UDP パケットの全てはポート変換され、ICMPなど、 それ以外のプロトコルだけ、IP 番号だけが変換されます。 場合によっては、与えられた範囲内の全てへの同時アクセスを保証したい ことがあり、その場合には、実際のポート番号範囲の代わりに キーワード auto を使用したほうが適切なこともあります。 しかし、この場合は 24 ビットのアドレス空間を 8 個に絞り込むので、 IP アドレスごとにポート 1 つがデフォルトです。 どのようにこれを使用するかについての良い例は次のようになります。

map ppp0 172.192.0.0/16 -> 209.1.2.0/24 portmap tcp/udp auto

この例では、IP アドレスのそれぞれにつき、わずかな範囲 (252 個) のポートが 与えられる結果になります。ここでの問題は、map ディレクティブは 外向きのコネクションに対し利用可能な次のアドレス/ポートの組を 使用することを NAT コードに指示するので、 その結果、外部アドレス/ポートの組と内部アドレス/ポートの組の間の 関係の識別が容易でなくなることです。 この問題は次のように、map-block を使用することで克服できます。

map-block ppp0 172.192.0.0/16 -> 209.1.2.0/24 ports auto

例えば、この結果、172.192.0.0/24 は、209.1.2.0/32 に変換され、 172.192.0.0 から 172.192.0.255 の範囲の各アドレスは、 それぞれ自分用の 252 ポートを持つことになります。 先の map の用法と逆に、 何らかの理由により (例えば) 172.192.0.2 のユーザが 260 個の連続した 外向きコネクションを必要とする場合、map-block ならば 252 の範囲に 限定されますが、map コマンドの場合、次の IP アドレスに移行 することになります。

関連ファイル
/dev/ipnat
/etc/services
/etc/hosts

関連項目
ipnat(4), hosts(5), ipf(5), services(5), ipf(8), ipnat(8)