アドレス変更お知らせスクリプト



2001/10/06 簡易版(コンパクト版)アップ
下の方にあります。

まだいじっている最中なので汚いコードですみません(^^;。また、公開用に少しいじったので、 不具合もあるかも。ま、とにかく、もっとよいコードを作ってください。

※ipaddr.pl は補助スクリプトです。
###############################################################

#!/usr/bin/perl

#
# ipaddrwatch.pl
# shimakero
# history
# 2001.05.28 small changes
#
# last modify  
# 2001.07.17 --->around "$changedcmd"
# 2001.07.29 --->around "$ipaddrcmd"
#

#
# dynamic configuration
#
my $ipaddrcmd = '/root/bin/ipaddr';
my $changedcmd = '/root/bin/action-ipaddr-changed';
my $interval = 180;
my $alarm_interval = 180;
my $interface = 'ppp0';
my $ipaddr_dir = '/root/.ipaddr';

#
# static configuration
#
my $HUP;
my $prevaddr = '0.0.0.0';
my $retry_max = 3;
my $retry_interval = 0.2;

my $PID = "$ipaddr_dir/ipaddrwatch.pid";
my $ADDR = "$ipaddr_dir/ipaddr";

$SIG{HUP} = \&sighup;

&main;

sub main()
{
    open(FO, ">$PID") or die("PID file write error...\n");
    print FO "$$\n";
    close FO;

    $prevaddr = &get_prev_ipaddr();

    $HUP = 1;
    while(1){
        if($HUP){
$HUP = 0;
$prevaddr = &get_prev_ipaddr();
        }

        my $addr = &get_ipaddr($interface);
        if($addr eq ''){
limitcall($alarm_interval, \&exec_cmd); # (1)
        }else{
if($prevaddr ne $addr){
    print "now $addr available on $interface\n";
    local(*AD);
    open(AD, ">$ADDR") or die("ADDRESS file write error...\n");
    print AD $addr;
    close(AD);
    limitcall($alarm_interval, \&exec_cmd);
}
$prevaddr = $addr;
        }
        sleep $interval;
    }
    exit 0;
}

sub sighup
{
    print "received HUP signal...\n";
    $HUP = 1;
}

sub limitcall($$@)
{
    my($sec, $sub, @arg) = @_;
    my @res;
    eval{
        local($SIG{ALRM}) = sub{die "__LIMITCALL__\n"};
        alarm $sec;
        @res = &{$sub}(@arg);
        alarm 0;
    };
    return $@, @res;
}

sub get_ipaddr($)
{
    my($iface) = @_;
    my $addr;
    for($lop = 0; $lop < $retry_max; $lop++){
        $addr  = `$ipaddrcmd $iface`;
        chomp($addr);
        last if($addr =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/);
        sleep $retry_interval;
    }
    return $addr;
}

sub get_prev_ipaddr()
{
    local(*AD);
    if(open(AD, "<$ADDR")){
        my @data = <AD>;
        my $addr = $data[0];
        chomp($addr);
        close(AD);
        return $addr;
    }else{
        print "ADDRESS file read error...(Abort)\n";
        $prevaddr = '0.0.0.0';
    }
}

sub exec_cmd()
{
    return undef unless( -x $changedcmd );
    `$changedcmd 2> /dev/null`;
}

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


■ ご注意 ■

HTML化する際に実際にはない空白スペースが入っている場合がありますので注意してください。

以下の設定はテスト用の設定であり、root 権限で実行することを前提としています。実際の運用でセキュリティ的に問題があると思われる場合には適宜修正してください。


■ ipaddrwatch.pl 説明 ■

もちろんバックグラウンドで実行してください。

SIGHUP を送ると、$ADDR で指定したファイルを読み込んで、強制的にそれを前回のアドレスとします。テストのときに使用していた名残ですので、この部分は蛇足です。いらなければ関連個所を削除してしまうか、別の動作をさせるようにしてもかまいません(オススメできるのは perl を熟知している方のみ)。また、ここではデバイスが登録されていないとき(たとえばADSL 接続環境であっても、接続していないとき。ppp0 は未定義となる)もアクションを起こします((1)の部分)が、お好みで変更する余地はあるでしょう。

# static configuration 以下はスクリプトの内容が完全に理解できる場合のみ修正してもかまいません。

# dynamic configuration 以下は皆様のお好み、環境に合わせて変更が必要です。

my $ipaddr_dir = '/root/.ipaddr';

で使用するファイル類を格納するためのディレクトリを指定します。あらかじめ作成しておいてください。

my $interface = 'ppp0';

で監視するインターフェースを指定します。私の運用環境では ppp0 となっていますが、(私は ADSL 接続で、rp-pppoe という接続ツールを使用しています。これは私の環境の場合 eth2 を利用して ppp0 というトンネルデバイスを作ります。)CATV 環境で、DHCP によってアドレスが降られる場合などは ethX(X はあなたの環境による)となります。

my $interval = 10;

は監視インターバル(秒)を10秒に設定しています。これはまったくお好みでよいと思いますが、注意は必要です。あまり長いと、すでにアドレスが期限切れになっていた場合、それを知らずにアクセス、ということが起こります。そのアドレスの所有者が無ければかまいませんが、すでに誰かに振られていた場合、迷惑なアクセスです。これには注意してください。また、あまり短くてもマシンへの負担が大きくなります。

my $alarm_interval = 180; # 2000/05.28

はアドレスの変更を検知した時に実行するコマンドのタイムアウト(秒)設定です。実行するコマンドによって適当に設定してください。

my $changedcmd = '/root/bin/action-ipaddr-changed';

★修正(2001/06/10): 修正前 ..... my $cmd = 'perl /root/bin/rp-jump-page';
★修正(2001/07/17): 修正前 ..... my $cmd = '/root/bin/rp-jump-page';

ではアドレスの変更を検知した時に実行するコマンドを指定しています。皆さんで用意してください。ここで私が指定している action-ipaddr-changed はシンボリックリンクです。私はテスト環境ではシステムがらみの実行可能ファイル群へのシンボリックリンクを全て /root/bin/ に突っ込んでしまうのでこうなっているのです。ここに直でコマンドを記述してもよいですが、一時的に起動させたい場合もあるでしょうし、メンテナンスの手間もあるので、こうして他に用意したほうがよいでしょう。呼び出したいスクリプトにリンクします。例を書きましょう。

メールで連絡、というのもいい方法だと思います。が、ここでは「現在のアドレスを記載したHTMLを作成し、レンタルスペース上にFTPでアップロードする」と言うのを紹介しておきましょう。FTPアップロードはパケット盗聴される可能性もあるので運用する場合はその辺頭に入れておいてください。あと貸しドメインサービスを使う場合は更新スクリプトを呼び出したり、IDS(侵入検知)ツールの snort を使用したい場合は監視IPを変更して再起動する必要があるかもしれません。あと、アドレスの変遷履歴をログっておくのがお奨めです。まあ、それらをまとめて一つのスクリプトファイルを作っておくのがいいですね。
#!/bin/sh

#
# rp-jump-page.sh
# shimakero
# 2001.03.19
#

ADDR=`/root/bin/ipaddr ppp0`
USER='hogehoge'
PASS='XXXXXXXX'
TIMEOUT='30'
RHOST='ftp.hoge.hoge'
RDIR='/'
BASEFILE='/root/.ipaddr/jump-to-hoge.html.base'
UPFILE='/root/.ipaddr/jump-to-hoge.html'

/bin/sed -e 's/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]/$ADDR/g' $BASEFILE > $UPFILE
ncftpput -u $USER -p $PASS -t $TIMEOUT -R $RHOST $RDIR $UPFILE
BASEFILE は各自で用意。


あ、IP 拾うのはこんなの書いとく。
###############################################################

#!/bin/sh
#
# shimakero
# ipaddr.sh
# last modify 2001/06/12
# 

if [ $# -lt 1 ]; then
    echo 'Usage: ipaddr.sh interface'	
else
    /sbin/ifconfig $1 | grep inet | cut -d ' ' -f 12 | cut -b '6-'
fi

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


※本編もじつはあっさりとしたシェルスクリプトで書けるのであるが...。
まあ、その辺は許してもらいます。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


※結局書きました。1FDルータ用にコンパクトなのが必要だったためです。
簡易版です。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#!/bin/sh
#
# ipwatch.sh
# shimakero
# history 2001.10.07-
#

#
# dynamic configuration
#
IF=eth0
ACTION="/home/kero/action"
INTERVAL='3'
PREV='0.0.0.0'

#
# main
#
while [ 1 ];
do
    CURRENT=`/sbin/ifconfig $IF | grep inet | cut -d ' ' -f 12 | cut -b 6-`
    if ! [ $CURRENT = '' ]; then
	if ! [ $PREV = $CURRENT ]; then
	    if [ -x $ACTION ]; then
		$ACTION
	    else
		echo "$ACTION is not executable"
	    fi
	fi
	PREV="$CURRENT"
    fi
    sleep $INTERVAL
done

★追記

Linux マガジンという雑誌を立ち読みしてたら、7月号で似たようなことをやる記事がのっていました。わりとフツーに考えつくことなのね(^^;。でも細かいことは省略してたみたいです。その影響で検索されるかなー、と思って見直してたら、この紹介版にバグがみつかりました(2001/06)。失礼ーー m(_ _ )m。



トップページ