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" portnum [ "-" portnum ] .
ports ::= "ports" numports | "auto" .
rdrport ::= "port" portnum .
mapit ::= "map" | "bimap" .
fromto ::= "from" object "to" object .
ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask .
dstipmask ::= ipmask | "range" ip "-" ip .
mapport ::= "portmap" tcpudp portnumber ":" portnumber .
mapoptions ::= [ tcpudp ] [ "frag" ] [ age ] [ clamp ] .
rdroptions ::= [ tcpudp ] [ 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" | protocol .
protocol ::= protocol-name | decnumber .
nummask ::= host-name [ "/" decnumber ] .
portnumber ::= number { numbers } | "auto" .
ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers .
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

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 パケットのすべてはポートマップが行なわれ、IP アドレス のみが変更されるのは ICMP など他のプロトコルだけとなります。

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

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