iptables や firewalld などで日本国内からのアクセスのみ許可するようなルールを作成したいという背景のもと、アクセス許可するIPアドレスを一覧化する必要がありました。firewalld を設定するサーバにスクリプトを設置して実現できたので備忘録としてメモします。
情報元
APNIC または JPNIC で管理しているIPアドレスを一覧化して公開しており、今回はAPNICから引っ張ってきています(以下URL)
http://ftp.apnic.net/stats/apnic/delegated-apnic-latest
使用条件として以下の記載があります(日本語訳の不備はあしからず)。自由に使えるが正確性は保証しないとのこと。ありがとうございます。
これらのファイルは、これらのレポートに記載されている情報の使用に起因する損失または損害に対して、APNICが一切の責任を負わないという条件で、自由にダウンロードして使用することができます。
APNICは、これらの報告書の正確性を保証する能力を最大限発揮するよう努めています。 ただし、APNICはこの点に関していかなる保証もいたしません。
APNICとは、アジア太平洋地域のIPアドレスやAS番号の割り当てや管理を行っています。JPNICはその配下で日本国内における同管理を行っている機関です。詳しくは、JPNICとは。
やり方
まず、APNICから先ほどのIPアドレスの一覧を引っ張ってくるのですが、アジア全域のIP一覧となっているため、日本国内のIPを取り出す必要がある。
さらに、firewalld に読み込ませるためにはIPアドレスとサブネットが必要になるため、192.168.1.0/24 のような表示に整形する必要がある。※APNICから公表されている形式としては、以下のようになっている。
1 2 3 4 5 6 |
# grep 'JP|ipv4' delegated-apnic-latest|head -5 apnic|JP|ipv4|1.0.16.0|4096|20110412|allocated apnic|JP|ipv4|1.0.64.0|16384|20110412|allocated apnic|JP|ipv4|1.1.64.0|16384|20110412|allocated apnic|JP|ipv4|1.5.0.0|65536|20110401|allocated apnic|JP|ipv4|1.21.0.0|65536|20100616|allocated |
4カラム目がIPアドレス、その隣の5カラム目がIPの数。(例えば、/24 であれば256と記載されている。サブネットの形式では書かれていない。。。)ので、IPの数からサブネットを割り出す必要がでてくる。
答えからいうと以下で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#!/bin/sh DIR=DirectoryPath LST=${DIR}/jpip.list # JPNICより一覧を取得 wget -q http://ftp.apnic.net/stats/apnic/delegated-apnic-latest # 以前に作成したIPリスト内容を削除 :> ${LST} # IPアドレス/IP数を抽出 GREPIP=`grep "JP|ipv4" delegated-apnic-latest | awk 'BEGIN { FS="|";OFS="/" } { print $4,$5 }'` # IP数からサブネットマスクを割り出してリストに追記 for IP in ${GREPIP} do IPADDR=`echo ${IP} |awk -F/ '{ print $1 }'` IPCOUNT=`echo ${IP} |awk -F/ '{ print $2 }'` NETMASK=32 while [ ${IPCOUNT} -ne 1 ]; do IPCOUNT=$((${IPCOUNT} / 2)) NETMASK=$((${NETMASK} - 1)) done echo "${IPADDR}/${NETMASK}" >> ${LST} done |
簡単に説明をば。
「以前に作成したリスト内容を削除」で :> を使用しているが、以下のどちらかでも代用可能。
1 2 3 |
truncate -s 0 jpip.list または echo -n "" >jpip.list |
ファイルの内容を空にするので rm の後に touch でもよい気もするけど、その場合 inodeが変わってしまうし、このリスト自体はfirewalldに読み込ませることを前提としており、常に存在している必要がある。削除した時点でfirewalld的にはよくない気がするので(確認はしていない)削除→作成ではなく。内容を空に、を選択した。
「IPアドレス/IP数を抽出」は単純にほしいデータ(4~5カラム目)をgrepしているだけ。区切り文字を読み込むときは|を、書き出すときには / を指定しているくらい。
「IP数からサブネットマスクを割り出す」のは、ネットワークで使用可能なIPの数(/24なら256など)は÷2していくと最後は1になる。IPの数が1の場合のサブネットマスクは /32 なので、「IPの数÷2」するたびに32から1を引いていくと、IPの数が1になった時にサブネットマスクの値がわかる。ので、IPの数が1でない場合は、この処理を行うようwhileループを使う。
あと、補足の補足になるけど、「割る2」と「引く1」は expr でも同じことが当然できるんだけど、以下のようにすることで処理時間を短縮できる。
1 2 3 |
expr xx - 1 ではなく↓ $((xx - 1)) |
こうすることで処理時間が以下のように変わってくる。
1 2 3 |
real 2m27.489s user 0m26.315s sys 1m50.613s |
1 2 3 |
real 0m25.366s user 0m4.851s sys 0m19.034s |
real は今回の場合ネットワークの影響を受けるので参考にならないが、user/sys では5~6倍の差がでた。大きいですね。
おまけ
できました。あとはこれを一定期間ごとにcronで回すだけと思ったけど、ipv4 は APNIC の上位に位置する IANA においてすでに枯渇している状態のため、国内IPのリストが更新されることはない(はず)。枯渇状況については、IPv4アドレスの在庫枯渇に関して を参照。だけど、心配なので1日1回くらい深夜などの負荷の低い時間帯にでも動くようにしておけばよいかなぁ。。。
あとは、firewalld にて、作成したリストを読み込ませて許可するよう設定するだけ。それはまた別で。
以上です。
↓↓↓ 持っていると便利な一冊。