grepでIPアドレスっぽい文字列を雑に検索してみた

仮想マシンをマイグレーションしてIPアドレスを変更するだけの簡単なお仕事があったのですが、IPアドレスを変更したことによる影響を調べる必要がありました(IPアドレスによるアクセス制限など)。

当然、そのサーバ上で動いているWebアプリのソースコードを見たことなどないし、中身を把握している人など既に誰もいません。運用屋あるあるです。

とは言え、

  • IPアドレスのパターンは決まっている
  • IPアドレスが書いてあるとしたら、設定ファイルか、プログラム中か、データベース上

ということを考えると、IPアドレスが埋まっていそうなところをgrepでひたすら調べれば、それとなく手掛りは掴めそうな気がします。ということで、やってみました。

実行したgrepコマンド

とりあえず /var/www/html/ 以下の全ファイルを再帰的に検索するとした時、実行するコマンドは下記のようになります。

grep -R '[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}' /var/www/html/*

-R というオプションを指定すると、検索対象にサブディレクトリが含まれていた時、サブディレクトリの中を再帰的に検索対象にしてくれます。

コマンドラインで指定した正規表現ですが、それぞれの要素の意味は下記のようになります。

[[:digit:]]
数字1文字にマッチ。[0-9]と同じ意味です。
{n,m}
直前の文字のn文字以上m文字以下の並びにマッチします。歴史的理由により、”{” と “}” の前には “\” (バックスラッシュ) が必要になります。
\.
正規表現で “.” (ピリオド) は任意の1文字にマッチするのですが、ピリオドそのものにマッチさせたいので、直前に “\” (バックスラッシュ) を付けて特別な意味を無くしています。

IPアドレスのパターンは(IPv4の場合)

(1〜3桁の数値).(1〜3桁の数値).(1〜3桁の数値).(1〜3桁の数値)

となるので、これを正規表現で表すと

[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}

となるわけです。

データベースの中を検索する

hoge_db というデータベースの、全テーブル全カラムを対象にIPアドレスっぽい文字列を検索する時。pg_dumpやmysqldumpでdumpを取り、grepでパターンマッチさせるのが最も手っ取り早いです。

対象データベースが MySQL の場合:

mysqldump hoge_db | grep '[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}'

対象データベースが PostgreSQL の場合:

pg_dump hoge_db | grep '[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}'

何かしらマッチするものがあった場合は、dumpの中身を注意深く精査します。何も出て来なかった場合は、それ以上深追いする必要はなし。

制限事項

例えば、下記のコマンドを実行してみるとわかるのですが、

echo 10.0.12.3456 | grep '[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}'

IPアドレスとしては明らかに間違っているパターン(最後が4桁の数値)であってもマッチしてしまうことがあります。上記の正規表現の場合、「数字1〜3文字」にマッチするわけですが、「数字4文字」の中には当然「数字3文字」が含まれるため、マッチしてしまうのです。

より厳密にマッチされないといけない場合は、例えば最後の「数字1〜3文字」の後に「数字以外の文字」などを置く必要があるのですが、これを始めると「どの文字は許してどの文字は許すべきではないか」を考えなくてはいけなくなり、面倒です。今回は、明らかにおかしいものは人間の目でチェックすれば良かったので、これ以上深追いはしませんでした。

これ以外にも、「8.9.3.1」のようなバージョン文字列にもマッチしてしまうのですが、これは単純なパターンマッチだけでは判定しようがないので、人間の目でチェックして弾くしかないです。

スポンサーリンク
スポンサーリンク:

フォローする