以前の環境(Debian-Sarge)でも同等のことをしていたのだけど、CentOS5.1でも同じことをする。固定IP回線と動的IP回線の2回線接続環境で、ルータ兼サーバPCは固定IPを利用し、LAN内のPCからは動的IPへ振るというもの。但し、一部のアクセスについてはLAN内PCからも固定IP経由で外部に接続する。
接続後に実行されるスクリプトは何処?
Debian(Sarge)なら /etc/network/interfaces にまとめられているのですぐ判ったけど、CentOSは何処...。 /etc/sysconfig/network-scripts/ にあるシェルスクリプトをひっくり返し、/sbin/adsl-* まで探ったりして /etc/ppp/ip-up.local が呼び出されていることに気づきました。呼び出し元は /etc/ppp/ip-up なんだが、この /etc/ppp/ip-up がどこから呼び出されているかというと、/etc/sysconfig/network-scripts/ifup-ppp のコメントに "# ifup-post for PPP is handled through /etc/ppp/ip-up" ってあるのだが、呼び出しているのはそこから起動されるpppdなのかな? おかげでなかなか気づきませんでしたよ。
デバイス名、ニックネーム、インターフェース
- デバイス名
- adsl-setupコマンドでppp0からppp1,ppp2って順に作られる。生成された設定保存ファイル /etc/sysconfig/network-scripts/ifcfg-ppp0 の中のDEVICE=ppp0がそれ。
- ニックネーム
- 基本的にデバイス名と同じ。GUI環境で「ネットワーク設定」を起動すると修正できるけど、要は設定保存ファイル"ifcfg-ppp0"のppp0の部分。なので、ifcfg-dynamicとファイル名を変更すると 接続コマンドで "# ifup dynamic " の様に指定できる。
- インターフェース
- 接続後に割り振られたインターフェース名で、接続順にppp0,ppp1...と割り振られる。つまり、"ifup ppp1" と接続コマンドを実行しても、1回線目ならppp0が割り振られる。ifconfigで出てくるデバイス名がこれで、iptables,iproute2コマンドで指定するのもこれ。
デフォルトだと全てppp0,ppp1と作られるのに、それぞれに特別な関連はなく、特にインターフェース名は接続されるまでどの番号に判らないし、障害などで回線切断後、自動再接続するとppp0とppp1がひっくり返る可能性もある。Debianも同じだったけど、これがopenSUSEになるとdsl0,dsl1の順になって全て固定される。1回線目にifup dsl1とやれば、ちゃんとifconfigでdsl1と確認できる。最初から決め打ち出来るのはファイヤウォールやルーティングが楽だよなぁ。この点だけとってもopenSUSEにしたかったよ。ちなみにハードのeth0,eth1...も同じで、こちらはカーネルが見つけた順番らしい。基本的に変わることはないけど、USB接続のイーサネットなんかは刺す位置によって順番が変わるでしょうね。
下準備
とりあえず新しいルーティングテーブルに名前をつけておく。viなどで /etc/iproute2/rt_tables に "200 lan2dip"と追記すればいいだけなんだけど、以下のコマンドでも可。
# echo "200 lan2dip" >> /etc/iproute2/rt_tables
参考環境は以下の通り
- 固定IP
- デバイス名 : ppp1
- ニックネーム : static
- デフォルトルート : yes (DEFROUTE=yes)
- 動的IP
- デバイス名 : ppp0
- ニックネーム : dynamic
- デフォルトルート : no (DEFROUTE=no)
- LAN側
- インターフェース : eth0
- IPアドレス : 192.168.0.1
- ネットワーク : 192.168.0.0/24
ip-up.localでまずは振分け
固定IPでも動的IPでも接続を行えばip-up.localが呼び出されるので、そこでは振分けだけにしておいて、各回線の設定はip-up.local.dynamicとかip-up.local.staticでする。渡される引数や環境変数は関係のあるものだけコメントに書いてます。
/etc/ppp/ip-up.local
#!/bin/sh # $1 = IFNAME = ppp0 # 割り振られたインターフェース # $4 = IPLOCAL = ddd.ddd.ddd.ddd # 割り振られたIPアドレス # $5 = IPREMOTE = rrr.rrr.rrr.rrr # 接続先のアドレス (peer) # $6 = = dynamic # ニックネーム # LINKNAME = ppp1 # デバイス名 [ -x "/etc/ppp/ip-up.local.${6}" ] && "/etc/ppp/ip-up.local.${6}" "$@"
ip-upからは実行可能であることが求められているので、実行権限の追加もお忘れ無く。これは後に出てくる ip-up.local.dynamicなどの個別ファイルも同じです。
# chmod u+x /etc/ppp/ip-up.local
ルーティングの設定
漸く本番のルーティング設定です。以下は、基本的にはLAN内から外部(Internet)へアクセスするときは動的IPから出て行くようにする。但し、192.168.0.5のPCから外部の22番ポート(SSH)だけは固定IPから出て行く様に設定してます。(リモート先へ自分ち以外からアクセスしないのなら、他はファイヤウォールでバッサリ弾けるしね。もちろん相応の認証は行ってますが、うざい不正アタックが無いのでログ管理も楽です。)
/etc/ppp/ip-up.local.dynmaic
#!/bin/sh ip route add 192.168.0.0/24 dev eth0 src 192.168.0.1 table lan2dip ip route add default via $IPREMOTE dev $IFNAME table lan2dip ip rule add from 192.168.0.0/24 table lan2dip ip rule add fwmark 1 table main iptables -t mangle -A PREROUTING -s 192.168.0.5/32 -p tcp -m tcp --dport 22 -j MARK --set-mark 0x1 ip route flush cache
Debianの時は「パケットへの印付けは、少なくとも MASQ と SNAT とに衝突してしまう」
というバグ? があったようなんだけど、さすがに今はないのでえらくスッキリ。ポート単位の振り分けが不要(PC単位だけの振分け)ならfwmark振り分けしている4行目と5行目は不要。また、例えば192.168.0.5からのアクセスは全て固定IP側に振分けてそれ以外は動的IP側へというならば、
ip route add 192.168.0.0/24 dev eth0 src 192.168.0.1 table lan2dip ip route add default via $IPREMOTE dev $IFNAME table lan2dip ip rule add from 192.168.0.0/24 table lan2dip ip rule add from 192.168.0.5/32 table main ip route flush cache
という感じで出来ます。ruleは後から設定した方から優先的に処理されていきます。っていうより、先に設定された方から処理していき、条件がマッチすれば単純に上書きされているだけかな。
切断時の処理
切断時はip-down.localが呼び出されますので、接続時に設定した物をそのまま削除するようにしておきます。
/etc/ppp/ip-down.local
#!/bin/sh # $1 = IFNAME = ppp0 # 割り振られたインターフェース # $4 = IPLOCAL = ddd.ddd.ddd.ddd # 割り振られたIPアドレス # $5 = IPREMOTE = rrr.rrr.rrr.rrr # 接続先のアドレス (peer) # $6 = = dynamic # ニックネーム # LINKNAME = ppp1 # デバイス名 [ -x "/etc/ppp/ip-down.local.${6}" ] && "/etc/ppp/ip-down.local.${6}" "$@"
/etc/ppp/ip-down.local.dynmaic
#!/bin/sh iptables -t mangle -D PREROUTING -s 192.168.0.5/32 -p tcp -m tcp --dport 22 -j MARK --set-mark 0x1 ip rule del from 192.168.0.0/24 table lan2dip ip rule del fwmark 1 table main ip route del 192.168.0.0/24 dev eth0 src 192.168.0.1 table lan2dip ip route del default via $IPREMOTE dev $IFNAME table lan2dip ip route flush cache
ルーティングの設定順序をわざわざひっくり返して削除する必要があるのかどうか疑問だけど、まぁ念のため。
接続直前に実行されるところは何処?
Debianでのpre-up的な物は何処かなと思ってたんだけど、とりあえず、回線設定ファイルで FIREWALL=STANDALONE なら /etc/ppp/firewall-standalone が、また FIREWALL=MASQUERADE なら /etc/ppp/firewall-masq が /sbin/adsl-connnet から読み込まれている。ちょっとDebianのpre-upとは違う気がしないでもないが、設定ファイルの内容が環境変数にセットされている状態で読み込まれるから、使い用はあるかな。初期の状態ではFirewall(iptables)をバッサリ削除して、簡易的な物に書き換えている様になっていたのには驚いた。iptablesでインターフェース名にppp+(ppp0やppp1...全てにマッチ)が使えるから、ipteblesが起動されたら読み込まれる(/etc/init.d/iptables save で保存しておく)ところに基本的なルールは全て書き込んでいるので、少なくとも今のところは使ってない。