メインスクリプトの勉強が完了したので、サブスクリプトに入ります。
サブスクリプトは二つのものからなっており、一つはIPアドレスリスト(つまりcidr.txt)を入手するスクリプトで、もう一つはIPアドレスリストの更新チェック(及びiptablesの自動更新)スクリプトです。
で、まずはIPアドレスリストの取得スクリプトから勉強していきます。以下に、このスクリプトを公開しているBLOGからスクリプトを転記します(ここも便宜上ナンバリングをします)。
01: # IPアドレスリスト取得関数定義
02: IPLISTGET(){
03: # https://nami.jp/ipv4bycc/から最新版IPアドレスリストを取得する
04: wget -q https://nami.jp/ipv4bycc/cidr.txt.gz
05: gunzip cidr.txt.gz
06: # 最新版IPアドレスリストが取得できなかった場合
07: if [ ! -f cidr.txt ]; then
08: if [ -f /tmp/cidr.txt ]; then
09: # バックアップがある場合はその旨をroot宛にメール通知して処理を打ち切る
10: echo cidr.txt was read from the backup! | mail -s $0 root
11: exit 1
12: else
13: # バックアップがない場合はその旨をroot宛にメール通知して処理を打ち切る
14: echo cidr.txt not found!|mail -s $0 root
15: exit 1
16: fi
17: fi
18: # 最新版IPアドレスリストを /tmpへバックアップする
19: /bin/mv cidr.txt /tmp/cidr.txt
20: }
コメント部分の解説は割愛するとして、まず最初は02行目と20行目です。これはもういいですね。ここでIPLISTGET関数を定義します。
この関数の内容が03行目~19行目にかかれているわけです。
04行目:
wgetコマンドを使って、https://nami.jp/ipv4bycc/cidr.txt.gzをダウンロードします。オプションでつけられている「-q」は、メッセージを表示しない、という意味です。
05行目:
gunzipコマンドを使って、ダウンロードしたgzファイルを展開します。
07行目:
ifは入れ子になっています。この行のif+条件文に対して、真の場合に返す値は08~16行目を実行します。この大きなifの方には偽の場合はありません。
さて、その条件ですが、「-f」によって、以下に続くファイルが存在するかどうかの確認を行います。そして「!」は否定を意味しますので、
if [ ! -f cidr.txt ]; then は、もしcidr.txtというファイルが(カレントディレクトリに)存在しないならば、then以下にすすめ(つまり真の場合=08~16行目にすすめ)という意味になります。
だから06行目のコメントは「# 最新版IPアドレスリストが取得できなかった場合」となっているわけですね。
08行目:
ここも条件式になっています。つまり元々の位置に(最新の)cidr.txtがなかった場合は、この行の条件式を実行することになります。その条件式は、/tmp/cidr.txtがある場合は、です。
10行目:
まずechoコマンドで文字列「cidr.txt was read from the backup!(cidr.txtはバックアップから読み込まれました!)」を作成し、それをパイプでmailコマンドに引き渡します(つまりechoで作成した文字列がメール本文になります)。
mailコマンドの「-s」オプションはサブジェクト、つまり件名を指定するオプションですが、そこに特殊変数$0を指定しています。特殊変数は「シェルスクリプト自身の名前を取得できる」んだそうで、実際に
$ echo cidr.txt was read from the backup! | mail -s $0 root
を試してみると、root宛にbashというサブジェクトでこのメール本文が届いていました。
※このスクリプトはメールを送信して処理を打ちきります。
ここで送信されている文字列「cidr.txt was read from the backup!(cidr.txtはバックアップから読み込まれました!)」の意味は、メインスクリプトが/tmp/cidr.txtからネットワークアドレスを読み込んで処理を行うスクリプトになっているため、バックアップ=古いcidr.txtから情報を読み込んで処理をしてしまっていますよ、と理解します(最初これに気づかず、このスクリプトで/tmp/cidr.txtからcidr.txtを生成しているのかと勘違いして訳がわからなくなっていた・・・)
11行目:
入れ子になっているif条件式のうち、真の場合を終了します。
12行目:
入れ子になっているif条件式のうち、偽の場合を開始します。
14行目:
10行目と同じ構造です。送信するメール本文の内容が異なります(偽の場合は/tmp/cidr.txtがなかったら、という条件となるため)。
15行目:
偽の場合を終了します。
16行目:
入れ子になっている方のifを閉じます。
17行目:
大きい方のifを閉じます。既に触れたように、大きい方のifには偽の場合は存在しません。
ここでのifは、カレントディレクトリにcidr.txtが無く(この条件が真である場合)、かつ/tmp/cidr.txtがあるならば(入れ子のifの真)このバックアップからcidr.txtを読み込むよ、というメールをrootに送り、、/tmp/cidr.txtもないならば(入れ子のifの偽)バックアップがないよ、というメールをrootに送る、ということです。
カレントディレクトリにcidr.txtが無いという条件の偽の場合とはすなわち、カレントディレクトリにcidr.txtが「ある」ということですから、そのまま処理を進めることが出きるということですからね。
06行目コメント以下に続くifは、rootにメールを送ると言う操作を行うものであり、バックアップからcidr.txtをどうこうするという類のものではないことに注意!
19行目:
最新のIPアドレスリストが取得できたならば(カレントディレクトリにcidr.txtができたならば)、そのcidr.txtを/tmp/cidr.txtにバックアップします(こうすることでバックアップは常に最新のIPアドレスリストになる)。
もし最新のそれが取得できていなかったらifに進み、処理が打ちきられるのでこの行は実行されないわけです。
これでIPアドレスリストを入手するスクリプトが完成しました。
極論すれば、このスクリプトを毎日実行し、かつメインスクリプトを毎日実行すれば常に(日にち単位での)最新IPアドレスリストに基づいて中国、韓国、台湾からのアクセスを除外することができる(はず)です。
しかし、これを毎日サーバで走らせるのは酷?だからなのか、実際にはこの二つのスクリプトの他に、IPアドレス更新チェックスクリプトが容易されています。
次はそれを見ていく予定です。