IP ネットワーク構築


NAT (natd) の設定

natd のための記述を追加する。

# vi /etc/rc.conf

追加する内容は次の通り。

gateway_enable="YES"
firewall_enable="YES"
firewall_script="/etc/rc.firewallnat"
#firewall_type="open"
natd_enable="YES"
natd_interface="ed1"
natd_flags="-same_ports -use_sockets"

ここでは ed1 であるが、構成に合わせて natd_interface はグローバルネットワーク側 I/F を指定する。
また、natd を動作させるだけなら firewall_type は open (素通し) でもいいが、 セキュリティ的に特権ポートを塞ぐなども行なった方がいいので、 rc.firewall をベースにカスタマイズし、 rc.firewallnat というスクリプトを作成した。

############
# Setup system for firewall service.

# 設定値の取り込み
if [ -f /etc/rc.conf ]; then
    . /etc/rc.conf
fi

# セキュリティレベル
if [ X"$1" != X"" ]; then
    firewall_type=$1
elif [ X"${firewall_type}" = X"" ]; then
    firewall_type="open"
fi

# natd_enable が YES でないか、natd_interface が未定義ならば処理しない
if [ X"${natd_enable}" != X"YES" -o X"${natd_interface}" = X"" ]; then
    exit
fi

############
# 実行コマンド
if [ "x$firewall_quiet" = "xYES" ]; then
    fwcmd="/sbin/ipfw -q"
else
    fwcmd="/sbin/ipfw"
fi

############
# ネットワーク I/F 設定
oif=${natd_interface}
oip=`/sbin/ifconfig ${oif} | /usr/bin/sed -n 's/^.*inet \([0-9\.]*\) .*$/\1/p'`
iif=`/bin/echo ${network_interface} | /usr/bin/sed -e 's/ *'${oif}' *//' -e 's/ *lo0 *//'`
iip="192.168.1.1"
inet="192.168.1.0"
imask="255.255.255.0"

############
# Flush out the list before we begin.
$fwcmd -f flush

############
# NAT
$fwcmd add 100 divert natd all from any to any via ${natd_interface}

############
# ループバック
$fwcmd add 210 pass all from any to any via lo0
$fwcmd add 220 deny all from any to 127.0.0.0/8

############

# 既にコネクションの確立した TCP は許可
$fwcmd add 1000 pass tcp from any to any established

# IP フラグメントは許可
$fwcmd add 1100 pass all from any to any frag

############
# ICMP
# 0:エコー応答, 3:終点到達不能, 4:始点抑制, 5:方向転換, 8:エコー要求,
# 11:全体時間経過済, 12:パラメータ障害, 13:タイムスタンプ要求,
# 14:タイムスタンプ応答, 17:アドレスマスク要求, 18:アドレスマスク応答
# 外部への送信はエコー要求/応答/到達不能を許可、受信は他に 11 (for traceroute)
$fwcmd add 2000 pass icmp from any to any out via ${oif} icmptypes 0,3,8
$fwcmd add 2010 pass icmp from any to any in  via ${oif} icmptypes 0,3,8,11
$fwcmd add 2020 deny icmp from any to any     via ${oif}

############

# 内部プライベートネットワーク内通信と外部への送信は許可
$fwcmd add 3000 pass all from ${oip} to any out via ${oif}
$fwcmd add 3010 pass all from ${iip} to any out via ${iif}
$fwcmd add 3020 pass all from ${inet}:${imask} to any in via ${iif}
$fwcmd add 3030 pass udp from any 68 to any 67 in via ${iif}

# 外部からのプライベートアドレスを破棄
$fwcmd add 3100 deny all from 192.168.0.0/16 to any in via ${oif}
$fwcmd add 3110 deny all from 172.16.0.0/12  to any in via ${oif}
$fwcmd add 3120 deny all from 10.0.0.0/8     to any in via ${oif}

############

# SSH コネクション確立を許可
# $fwcmd add 10220 pass tcp from any to any 22 setup

# SMTP コネクション確立を許可
$fwcmd add 10250 pass tcp from any to any 25 setup

# DNS アクセスを許可
$fwcmd add 10530 pass udp from any 53 to any
$fwcmd add 10532 pass udp from any    to any 53
# $fwcmd add 10534 pass tcp from any    to any 53 setup

# DHCP サーバから DHCP クライアントへのパケットを許可
$fwcmd add 10680 pass udp from any 67 to any 68

# HTTP コネクション確立を許可
$fwcmd add 10800 pass tcp from any to any 80 setup

# 外部 NTP サーバと自 NTP サーバ間のパケットを許可
$fwcmd add 11230 pass udp from any 123 to any 123

# 外部からの認証を拒否 (メールサーバによっては配信に支障が出ることもあり)
$fwcmd add 11130 reject tcp from any to any 113 in via ${oif} setup
$fwcmd add 11132 reject udp from any to any 113 in via ${oif}

# 外部からの SMB は不許可
$fwcmd add 11370 deny tcp from any to any 137-139 in via ${oif} setup
$fwcmd add 11372 deny udp from any to any 137-139 in via ${oif}

# 外部からの特権ポートへのアクセスは不許可、ロギング
$fwcmd add 20000 deny log tcp from any to any 1-1023 in via ${oif} setup
$fwcmd add 20010 deny log udp from any to any 1-1023 in via ${oif}

# 外部からの UDP ブロードキャストは破棄
$fwcmd add 20100 deny udp from any to 255.255.255.255 in via ${oif}

# NFS サーバ機能を使う場合、外部からの NFS は不許可
if [ "X${nfs_server_enable}" != X"YES" ]; then
    $fwcmd add 30000 deny tcp from any to any 2049 in via ${oif} setup
    $fwcmd add 30010 deny udp from any to any 2049 in via ${oif}
fi

# X サーバへの接続を不許可
if [ -x /usr/X11R6/bin/X ]; then
    $fwcmd add 30100 deny tcp from any to any 6000 in via ${oif} setup
    $fwcmd add 30110 deny udp from any to any 6000 in via ${oif}
fi

if [ "${firewall_type}" = "open" -o "${firewall_type}" = "OPEN" ]; then
    # 他のコネクション確立は許可
    $fwcmd add 40010 pass tcp from any to any setup
    # 他の UDP を全て許可
    $fwcmd add 65000 pass udp from any to any
else
    # 外部からのコネクション確立を不許可、ロギング
    $fwcmd add 40000 deny log tcp from any to any in via ${oif} setup
fi
# 残りのパケットは不許可

FreeBSD FAQ を見ると、 ipfw の性能は i486 66MHz CPU 時代で1つのルールの処理がμsオーダーだったらしい。 Celeron 533MHz の CPU 処理能力は1桁あがっているだろうから、 複数ルールが適用される実運用で ipfw によるパケットの遅延は1μsかそこらだろう、きっと。


DHCP サーバ (dhcpd) の設定

DHCP サーバには WIDE 版と ISC 版があるが、 私は ISC 版の方が馴染みがあるので (WIDE 版は Solaris で動かなかったのだ) 私は ISC 版を使う。
まず、パッケージのインストールする。

# pkg_add isc-dhcp-2.0.tgz

設定ファイル /usr/local/etc/dhcpd.conf を作成する。
この例では carrot と risotto は固定 IP アドレス。 動的アドレスは 192.168.1.100〜192.168.1.199 に設定。

# dhcpd.conf
#
# Configuration file for ISC dhcpd
#
server-identifier waffle.uminari.yi.org;

option domain-name "uminari.yi.org";
option domain-name-servers 192.168.1.1;

#
default-lease-time 10800;
max-lease-time 86400;

subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.100 192.168.1.199;
    option routers 192.168.1.1;
    option subnet-mask 255.255.255.0;
    option broadcast-address 192.168.1.255;
}

host carrot {
    hardware ethernet 01:23:45:67:89:ab;
    fixed-address carrot.uminari.yi.org;
    option host-name "carrot";
}

host risotto {
    hardware ethernet fe:dc:ba:98:76:54;
    fixed-address risotto.uminari.yi.org;
    option host-name "risotto";
}

ローカルネットワーク側のネットワーク I/F (fxp0) で起動するスクリプト /usr/local/etc/rc.d/dhcpd.sh を作成する。

#!/bin/sh
if [ -x /usr/local/sbin/dhcpd -a -f /usr/local/etc/dhcpd.conf ]; then
    /usr/local/sbin/dhcpd -q fxp0
    echo -n ' dhcpd'
fi

DNS サーバ (bind) の設定

まず先に入れ替えた DHCP パッケージに合わせてクライアントの方も入れ替え、 /etc/rc.conf に次の記述を入れる。

dhcp_program="/usr/local/sbin/dhclient"

グローバル IP アドレスの取得に DHCP を使用しているため、そのままでは /etc/resolv.conf が書き換えられてしまう。 本来ならば /usr/local/etc/dhclient.conf を書き換えて、domain-name-server を固定化するのが本来である。
また某 CATV インターネット接続のようにプロバイダから DHCP クライアントのホスト名を指定される場合も、 /usr/local/etc/dhclient.conf に記述する。

interface "ed1" {
    supersede domain-name "uminari.yi.org";
    prepend domain-name-servers 127.0.0.1;
    send host-name "cj8888888-a";
}

ここでは、その方法を使わず、dhclinet-script の make_resolv_conf 関数部を修正し、DNS サーバ情報を反映する先を /etc/named.conf とし、 DHCP で受け取った DNS サーバ情報は、 DNS サーバが要求をフォワードする先として利用するように修正する。

まず dhclient-script をコピーしてから修正する。

# cp /usr/local/etc/dhclient-script /etc
# vi /etc/dhclient-script

dhclient-script の記述の中で

  echo search $new_domain_name >/etc/resolv.conf
  for nameserver in $new_domain_name_servers; do
    echo nameserver $nameserver >>/etc/resolv.conf
  done

と記述されている箇所(2ヶ所)を次のように書き換える。

  cat <<E_NAMED >/etc/named.conf
options {
    directory "/etc/namedb";
    forwarders {
E_NAMED
  for nameserver in $new_domain_name_servers; do
    echo "        ${nameserver};" >>/etc/namedb/named.conf
  done
  echo "    };" >>/etc/namedb/named.conf
  echo "};" >>/etc/namedb/named.conf
  cat /etc/namedb/named.conf.base >>/etc/namedb/named.conf

これにより localhost とプライベートドメインに対してはプライマリサーバとして機能し、 それ以外のドメインは DHCP サーバから通知された DNS サーバへ要求をフォワードするようになる。
(本当は /etc/dhclient-exit-hooks に関連する処理を記述するのがスジなんだろうけど……)

/etc/resolv.conf は次の内容で作成する。

search uminari.yi.org
nameserver 127.0.0.1    

/etc/rc.conf に次の記述を入れる。

named_enable="YES"

/etc/namedb/named.conf.base を作成する。

     
acl "private" {
    127.0.0.1;   
    192.168.1.0/24;
};

zone "." {
    type hint;
    file "named.root";
};

zone "localhost" {
    type master;
    file "localhost.zone";
};

zone "0.0.127.in-addr.arpa" {
    type master;
    file "localhost.rev";
};

zone "uminari.yi.org" {
    notify no;
    type master;
    file "uminari.zone";
    allow-transfer { private; };
    allow-query { private; };
};

zone "1.168.192.in-addr.arpa" {
    notify no;
    type master;
    file "uminari.rev";
    allow-transfer { private; };
    allow-query { private; };
};

各正引きと逆引き用のファイルは次のようになる。

localhost.zone
@       IN      SOA     waffle.uminari.yi.org.  net.waffle.uminari.yi.org. (
                        00111100        ; Serial
                        10800           ; Refresh 3H
                        3600            ; Retry 1H
                        4320000         ; Expire 1200H
                        86400 )         ; Minimum 24H
                IN      NS      waffle.uminari.yi.org.
localhost.      IN      A       127.0.0.1
localhost.rev
@       IN      SOA     waffle.uminari.yi.org.  net.waffle.uminari.yi.org. (
                        00111100        ; Serial
                        10800           ; Refresh 3H
                        3600            ; Retry 1H
                        4320000         ; Expire 1200H
                        86400 )         ; Minimum 24H
                IN      NS      waffle.uminari.yi.org.
1               IN      PTR     localhost.
uminari.zone
@       IN      SOA     waffle.uminari.yi.org.  net.waffle.uminari.yi.org. (
                        00111100        ; Serial
                        10800           ; Refresh 3H
                        3600            ; Retry 1H
                        4320000         ; Expire 1200H
                        86400 )         ; Minimum 24H
                IN      NS      waffle.uminari.yi.org.
                IN      A       192.168.1.1
localhost       IN      A       127.0.0.1
waffle          IN      A       192.168.1.1
carrot          IN      A       192.168.1.2
risotto         IN      A       192.168.1.3
www             IN      CNAME   waffle
uminari.rev
@       IN      SOA     waffle.uminari.yi.org.  net.waffle.uminari.yi.org. (
                        00111100        ; Serial
                        10800           ; Refresh 3H
                        3600            ; Retry 1H
                        4320000         ; Expire 1200H
                        86400 )         ; Minimum 24H
                IN      NS      waffle.uminari.yi.org.
1               IN      PTR     waffle.uminari.yi.org.
2               IN      PTR     carrot.uminari.yi.org.
3               IN      PTR     risotto.uminari.yi.org.

[ Home LAN ]