🕸

geoipフィルタのiptables+xtable-addons+geoipでなんとかしてみた話(2020年秋)

2020/10/11に公開

クラウド(雑)で、特定のエリアからのアクセスフィルタをサーバ上に入れようとして、いつもfail2banかiptables+xtable-addons+geoip[1]にしようか迷うんだけど、今回も慣れているiptables+xtable-addons+geoipにしようとしてうまくいかなかったので、ワークアラウンドを含めて残しておく。

準備

  • Ubuntu 20.04(GCEではminimalでインストール)

サーバーの起動が完了したら、必要なものいるものインストール。

$ sudo apt install xtables-addons-common libtext-csv-xs-perl

進め方

インストール後は以下のように進めます

  • geoipの取得
  • geoipモジュールのbuild
  • iptablesの定義

で、弾けるようになるのですが、初手のgeoipの取得処理からうまくいかない。マジで。

geoipの取得失敗とxt_geoip_dlの修正

geoipの取得は以下のように進めます。…が前述の通りうまくいきません。

$ sudo mkdir /usr/share/xt_geoip
$ cd /usr/share/xt_geoip

# geoipの取得
$ sudo /usr/lib/xtables-addons/xt_geoip_dl

geoipのソース取得は/usr/lib/xtables-addons/xt_geoip_dlで処理していますが、ここには2つ問題があって、

  1. wgetでmaxmindからGeoLiteの国別リストをダウンロードしてるけどもうできない
  2. dbip-country-liteがその後のxt_geoip_buildで必要だけど、これもダウンロードしてない

1.についてはMaxMind GeoLite2 のライセンスと取得方法が変わったので対応する。を読んだほうが話は早いでしょう。要は『MaxMindでアカウントつくってライセンス発行しないとダウンロードさせないよ』になりました。なので、素直にMaxMindでアカウントをつくってライセンスキーを発行する作業が必要です[2]

2.については、dbip-country-lite.csv.gzが取得できてなくてその後のgeoipモジュールのビルドが失敗しているようです。これはダウンロードして展開するだけでよさそう。

というわけで、/usr/lib/xtables-addons/xt_geoip_dlを修正するのですが、現在ソースは以下のようになっています。

#!/bin/sh

rm -rf GeoLite2-Country-CSV_*

wget -q http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip
unzip -q GeoLite2-Country-CSV.zip
rm -f GeoLite2-Country-CSV.zip

このあたりを以下のように書き換えてみます。"LICENSE_KEY"は先程MaxMindで取得したライセンスキーを設定します。

#!/bin/sh

#rm -rf GeoLite2-Country-CSV_*
#ファイル名が変わっているので以下に修正
rm -rf GeoLite2-Country-*

# ↓maxmindからgeoipリストを取得のため追加。LICENSE_KEYは自分が取得したライセンスキーを入れてね
wget -q -O GeoLite2-Country-CSV.zip  "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=LICENSE_KEY&suffix=zip"
# ↓はコメントアウト
#wget -q http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip  ←コメントアウト
# ↓dbip-country-lite.csv.gzを取得。本ファイルはdbip-country-lite-yyyy-mm.csv.gzのフォーマットでファイルになっているので、こんな感じでダウンロード
wget -O dbip-country-lite.csv.gz "https://download.db-ip.com/free/dbip-country-lite-$(date +'%Y-%m').csv.gz"

# dbip-country-lite.csv.gzをgunzipで展開のため追加
gunzip -f dbip-country-lite.csv.gz
# これで展開するとディレクトリができてしまうのでコメントアウト
#unzip -q GeoLite2-Country-CSV.zip
# オプションを-qojにしてgeoipデータベースを展開
unzip -qoj GeoLite2-Country-CSV.zip
rm -f GeoLite2-Country-CSV.zip

これで、geoipのダウンロードができるようになります。もう一度実行してみましょう。

$ sudo /usr/lib/xtables-addons/xt_geoip_dl

エラーがでなければgeoipモジュールをビルドできるようになります。

geoipモジュールのbuild

では、geoipモジュールをビルドしましょう。これはすんなり終わるでしょう。

$ sudo /usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv

これでiptablesでgeoipモジュールを組み込むことができます。cronに組み込む場合は、geoipデータベースのダウンロードとgeoipモジュールのビルドを月に1回程度行えばいいでしょう。

iptablesの設定

クラウドシステムなどで、Ubuntuをminimalでインストールしている場合、iptablesは入ってないと思うのでiptablesをインストールします。

$ sudo apt install iptables

iptablesには、アクセス元となるIPの地域を指定してDROPを指定します。指定する内容はISO 3166ベースです。このあたりが参考になるでしょう。

$ sudo iptables -A INPUT -m geoip --src-cc CN,AU -j DROP

で、落としたい国をgeoip経由みてもらってDROPするイメージになります。iptablesは再起動後に消えてしまうので永続化できるようにiptables-persistentをインストールします。インストール中に「ipv4の設定を保存する?」とか「ipv6の設定を保存する?」と確認されます。先程の設定を引き継ぎたいのですべてyesとします。

$ sudo apt install iptables-persistent

再起動して、iptablesを確認して残っていれば、設定自体はこれで完了です。

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             -m geoip --source-country CN,AU

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

DROPの結果をログに書き込む

動いているかを確認したい時にみたいことがありますよね。iptablesからログに出力することができるので、ちょっとやってみましょう。

まず、先程投入した、DROPの設定を削除します。まずはiptables -L --line-numbersで、削除対象の番号を確認。

$ sudo iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       all  --  anywhere             anywhere             -m geoip --source-country CN,AU 

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination  

INPUT Chainの1番を削除したいので、以下のコマンドを入力すればルールを削除できます。

$ sudo iptables -D INPUT 1

新規にGEOIPDROPChainをiptablesコマンドから設定し、INPUT Chainの条件にかかったパケットをログ出力して、DROPするというルールを書きます。

$ sudo iptables -N GEOIPDROP
$ sudo iptables -A GEOIPDROP -j LOG --log-prefix "GEOIPDROP:" --log-level 6
$ sudo iptables -A GEOIPDROP -j DROP
$ sudo iptables -A INPUT -m geoip --src-cc CN,AU -j GEOIPDROP  

再度、sudo iptables -Lで確認すると、以下のようになっているでしょう。

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
GEOIPDROP  all  --  anywhere             anywhere             -m geoip --source-country CN,AU

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain GEOIPDROP (1 references)
target     prot opt source               destination
LOG        all  --  anywhere             anywhere             LOG level info prefix "GEOIPDROP:"
DROP       all  --  anywhere             anywhere

DROP対象になっている国から、アクセスすると以下のようにログが出力され、パケットはDROPされるでしょう。

Oct 11 06:43:02 ubuntu2004lts kernel: [ 1649.714461] GEOIPDROP:IN=ens4 OUT= MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX SRC=(DROPしている国のIPアドレス) DST=xxx.xxx.xxx.xxx LEN=60 TOS=0x00 PREC=0x00 TTL=38 ID=18724 DF PROTO=TCP SPT=44690 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0 

ところで、なんでこれ書いたの?

筆者が構築の度に忘れるからだよ!

脚注
  1. 前者、後者でメリットデメリットはあるんですけどね ↩︎

  2. 登録はちょっと…の場合は諦めるしかないですね…ライセンスキーの発行についてはここでは触れません。 ↩︎

Discussion