geoipフィルタのiptables+xtable-addons+geoipでなんとかしてみた話(2020年秋)
クラウド(雑)で、特定のエリアからのアクセスフィルタをサーバ上に入れようとして、いつも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つ問題があって、
- wgetでmaxmindからGeoLiteの国別リストをダウンロードしてるけどもうできない
- 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
新規にGEOIPDROP
Chainを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
ところで、なんでこれ書いたの?
筆者が構築の度に忘れるからだよ!
Discussion