Linux Inside に戻る

diald を使ってオンデマンドダイアリング


テレホーダイなどにはいっているといちいち ppp-on で電話をかけるのが面倒になりませんか? そういう時には diald です。必要に応じて Linux Box が電話をかけるようになり, Linux Box をダイアルアップルータのように使うことができます。

1. 準備

すでに ppp-on が動いている環境では,取り合えず必要なものは diald だけです。 適当な所 から持って来ましょう。コンパイルは Linux 用なので簡単です。基本的に

    
     # tar zxvf diald-0.99.1.tar.gz
     # cd diald
     # vi Makefile (5〜7行目をコメントアウト)
     # make && make install
    
   
で良いハズです。RHL 系のみなさんには RPM の方が良いでしょう。

カーネルは PPP と SLIP が使えるようにしておいてください。SLIP は忘れがちですが,diald は SLIP デバイスを利用してオンデマンド接続をするので SLIP サポートは必ず入れておいてください。

2.2.x カーネルの場合は SLIP ではなくて ethertap を使います。 README.ethertap を見ながら /etc/modules.conf に

    alias tap0      ethertap
    options tap0    -o tap0 unit=0
   

などと書いておきます。

2. 設定ファイルを書く

/etc/diald.conf というファイルを書きます。私の場合以下のようになっています。
    
     -- /etc/diald.conf ---------------------
     # リダイアルの間隔を 5 秒にする
     redial-timeout 5

     mode ppp
     accounting-log /var/log/account
     fifo /var/run/diald.ctl

     # 接続・切断の際実行するスクリプト(/etc/ppp/ip-* は使用しません)
     ip-up /usr/lib/diald/ip-up
     ip-down /usr/lib/diald/ip-down

     # PPP・モデムの設定
     pppd-options asyncmap 0x200A0000 bsdcomp 15 name negi
     connect '/etc/ppp/ppp-on-dialer'
     device /dev/ttyS0
     speed 115200
     modem
     lock
     crtscts
     dynamic
     defaultroute
     reroute

     # 発呼に使う仮の IP アドレス
     local 192.168.1.1
     remote 127.0.0.3

     # 時間設定
     restrict * * * * *
     impulse 160,20

     include /usr/lib/diald/standard.filter
     ----------------------------------------
    
   

重要と思われるポイントだけ書いていきます。まず fifo ですが,/var/run/diald.ctl という FIFO を mkfifo コマンドであらかじめ作っておく必要があります。 この設定をやっておかないと diald 付属の dctrl という Tcl/Tk ベースのコントロールパネルが使えません。

次に pppd-options ですが,ここに書かれた部分が pppd に引数として渡るようになっています。 見ればわかると思いますが,ここには最低限のものしか書かないでください。 /etc/ppp/options の中身にも注意。でないと diald とオプションが重なって,ちゃんと動作しません。bsdcomp は私の趣味です :-)

最後から4行目以降の設定は,モデムを切るタイミングに関する設定です。 restrict は接続する曜日などの条件を書きます。ウチの場合はいつでも OK ということになっています。impulse は時間設定です。この設定では,合計三分を考え 160 秒接続し,残り 20 秒は切るかどうか保留するという設定になっています。

最後の include は,diald のフィルタを読み込む設定です。気まぐれな DNS への参照などがあっても, ちゃんとフィルタリングしておけば電話をかけさせずに済みます。

3. 実際に使ってみよう

diald を使うのは簡単です。root になって /usr/sbin/diald を実行するだけです。rc.local にでも書いておけば良いでしょう。

/etc/resolv.conf にプロバイダの DNS アドレスを書いて,適当な所に ping してみましょう。自動的に電話をかければ大成功です。

4. FAQ

4.1 テレホーダイタイムの間だけダイアルさせたい

diald.conf に以下の様に書いておきます。

    
     restrict 08:00:00 23:00:00 * * *
     down
    
   

4.2 DNS を立ちあげているとダイアルしてくれない

標準の設定では DNS 同士の通信は無視するようになっています。 diald のフィルタ設定ファイルである /usr/lib/diald/standard.filter の中の

    
     ignore udp udp.dest=udp.domain,udp.source=udp.domain
    
   
という行をコメントアウトすることによって,DNS 同士の通信でもダイアルするようになります。

4.3 PPP 接続したパケットが行方不明になる

rc.local などで,

    
     echo 1 > /proc/sys/net/ipv4/ip_dynaddr
    
   
としてみます。ただしこれは kernel 2.0.31 以降でないと使えません。

4.4 LAN に Windows があると勝手にダイアルしてしまう

LAN 上に Windows マシンがある場合 NetBIOS のブロードキャストが悪さをして勝手に接続してしまうことがあります。 定期的に接続してしまうケースはだいたいコレが原因です。 そんなわけで, このブロードキャストはフィルタリングした方がいいかも知れません。 具体的にはstandard.filter の
    
     accept udp 30 udp.dest=udp.netbios-ns
     accept udp 30 udp.source=udp.netbios-ns
    
   
この二行をコメントアウトします。 そして次の行のコメントを外します。
    
     #ignore udp udp.source=udp.netbios-ns,udp.dest=udp.netbios-ns
    
   

4.5 Netscape を終了するとダイアルしはじめてしまう

Netscape は終了する際に,接続先に FIN パケット (通信の終了を知らせるパケット) を飛ばします。実装としてはマトモなんですが, 無闇に電話を掛けられるのは困るのでフィルタリングしてしまいましょう。 standard.filter の accept tcp 15 tcp.syn の次の行あたりに
    
     ignore tcp tcp.fin
    
   
と入れます。

4.6 なんだかよくわからないけど不用意にダイアルしてしまう

その殆どが,リゾルバの解決がうまくいかない為, 外部の DNS に問合せようとしてダイアルをしてしまうというケースです。 /etc/hosts などを確認してみてください。 WINS 解決に DNS を使用してしまうという Windows の bug とも言える実装 のせいでそうなる場合がありますが,その場合は YAMAHA RT シリーズの FAQを見て設定してみてください。 それでも解決しない場合は tcpdump -i sl0 などとしてパケットを追ってみて下さい。

4.7 Linux-2.2 にしたら diald が動かない

kernel の Networking options で Packet socket を y にしてみます。

4.8 Linux-2.2 にしたら diald uses obsolete (PF_INET,SOCK_PACKET) と言われるようになった

filter.c の以下の二行の AF_INET を AF_PACKET に変更します。
    
     (変更前)
     if ((snoopfd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0) {
     if ((fwdfd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0) {
    
   
    
     (変更後)
     if ((snoopfd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) < 0) {
     if ((fwdfd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) < 0) {
    
   
または,最新版(0.99.x)の diald に入れ替えます。

5. ファイアウォールと組み合わせる

PPP 接続だからといって,安全に気を抜いていいわけじゃありません。 特にテレホーダイなどを利用していると,23:00〜8:00 まで専用線と同様というのは普通のことで,その間, カンのいいクラッカなら簡単にあなたのマシンを踏台にしてしまうでしょう。 PPP 接続でもやはりファイアウォールは必要です。

市販のダイアルアップルータには, 大抵簡易ファイアウォールの機能が付いています。 しかしあなたの使っている OS は Linux なんです。 本格的なファイアウォールを作ってしまいましょう。

diald は,発呼する際に ip-up というスクリプトを実行するので このスクリプトにファイアウォールの設定を書けば 簡単にファイアウォールが実現できます。

以下はウチの設定です。

    
     -- /usr/lib/diald/ip-up ----------------
     #!/bin/sh
     umask 022

     # 変数をセットする
     iface=$1
     netmask=$2
     localip=$3
     remoteip=$4
     metric=$5

     # 今の自分の IP アドレスを保存する(patched dcc で使うんです)
     echo $localip >/var/run/myip

     # パケットフィルタをリセットする
     /sbin/ipfwadm -I -f

     # 変な IP を持つパケットを弾く
     /sbin/ipfwadm -I -a deny -S 127.0.0.0/24   -D $localip -W $iface
     /sbin/ipfwadm -I -a deny -S 10.0.0.0/8     -D $localip -W $iface
     /sbin/ipfwadm -I -a deny -S 192.168.0.0/16 -D $localip -W $iface

     # SMTP (sendmail 等)への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip  25 -W $iface

     # SUN RPC への接続を弾く
     /sbin/ipfwadm -I -a reject -b -P tcp -S 0/0 -D $localip 111 -W $iface
     /sbin/ipfwadm -I -a reject -b -P udp -S 0/0 -D $localip 111 -W $iface

     # identd への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 113 -W $iface

     # NetBIOS への接続を弾く
     /sbin/ipfwadm -I -a reject -b -P tcp -S 0/0 -D $localip 137:139 -W $iface
     /sbin/ipfwadm -I -a reject -b -P udp -S 0/0 -D $localip 137:139 -W $iface

     # lpr への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 515 -W $iface

     # skkserv への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 1178 -W $iface
     # ndtp (辞書サーバ) への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 2010 -W $iface
     # NFS への接続を弾く
     /sbin/ipfwadm -I -a reject -b -P tcp -S 0/0 -D $localip 2049 -W $iface
     /sbin/ipfwadm -I -a reject -b -P udp -S 0/0 -D $localip 2049 -W $iface
     # PostgreSQL への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 5432 -W $iface
     # Canna server への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 5680 -W $iface
     # X11 への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 6000 -W $iface
     # X11 font server への接続を弾く
     /sbin/ipfwadm -I -a reject -y -b -P tcp -S 0/0 -D $localip 7000 -W $iface
     ----------------------------------------

     -- /usr/lib/diald/ip-down --------------
     #!/bin/sh

     # ファイアウォールをリセットする
     /sbin/ipfwadm -I -f

     # IP アドレスを保存したファイルを消す
     rm -f /var/run/myip
     ----------------------------------------
    
   

6. おまけ

diald の man の翻訳やってますが,終わりそうにないので一部だけ...^^;
フィルタリングルールを書く時にとりあえず必要となるオプション達です。

man の翻訳(一部)

    accept <protocol-rule> <timeout> <packet-rule>
   

リンク制御の為のパケットマッチングルールを定義する。 accept ルールにマッチしたパケットは接続を促し, その接続を少なくとも <timeout> 秒だけ保持する。 <protocol-rule> は,あらかじめ prule ステートメントで定義されたプロトコルルールに当てはまらねければならない。 <timeout> の値は正の整数でなければならない。 <timeout> が 0 であることは, そのパケットに関連した接続が直ちに切断されるであろうことを意味する。

<packet-rule> パラメータは一つ, あるいはパケットが遭遇するはずの状態のリストである。 特別なケースとして,ルール "any" は全てのパケットとマッチする。 ルールは空白を含まないカンマで区切られた単語のリストとして書かれる。 それぞれの単語は幾つかのパケットのフィールド上のテストを指定する。 基本的な単語は以下のように書かれる。

    <変数名><op><値>
   
もしくは
    <変数名>&<bitmask><op><値>
   

<bitmask> の位置には任意の2進数ビットマスクを指定する。 <op> には "=","!=","<=",">=" が指定できる。 "<変数名>" や "<!変数名>" という短い二つの型式もある。 これは "<変数名>!=0","<変数名>=0" を簡略化したものである。

あらかじめ var ステートメントによって定義された変数名だけが, パケットルールで使用できる。値とビットマスクは 10 進数,8 進数,16 進数,ドット記法による IP アドレス, シンボリック名を指定することができる。 "tcp.<service>","udp.<service>" という型式のシンボリック名は /etc/services で定義された値とマッチする。シンボリック名はまた /etc/protocols によって定義されたプロトコルともマッチする。

    bringup <protocol-rule> <timeout> <packet-rule>
   

リンク制御のパケットマッチングルール定義する。 bringup ルールにマッチしたパケットは少なくとも <timeout> 秒の間接続を試みる。もしすでに接続されているならば, このルールは無視される。パラメータは厳密に accept コマンドと同様に記述する。

    keepup <protocol-rule> <timeout> <packet-rule>
   

リンク制御のパケットマッチングルール定義する。keepup ルールにマッチしたパケットは,もしすでに接続されているならば, 少なくとも<timeout> 秒の間は接続を保持する。このルールは, 接続が切れている場合は無視される。 パラメータは厳密に accept コマンドと同様に記述する。

    ignore <protocol-rule> <packet-rule>
   

リンク制御のパケットマッチングルール定義する。 ignore ルールにマッチしたパケットは無視され, またそれ以後のルールにもマッチしない。<timeout> を除くパラメータは厳密に accept コマンドと同様に記述する。



Linux Inside に戻る
おおつかまさひと(negi@KU3G.org)
Lastupdate: Thu Mar 23 03:29:51 2000.