[Ubuntu] ファイアウォール ufw で海外からの接続をブロックする

ALL
スポンサーリンク

Ubuntu でファイアウォール ufw 使用時に、設定している許可/拒否のルールに影響を与えずに、海外からの接続をブロックする設定です。
記事タイトルは「ファイアウォール ufw で海外からの接続をブロックする」ですが、正確には、ufw から、ブロック用のファイアウォールiptablesのルールを実行します。

2022.6.19
記事中のiptablesの場所を /sbin/iptables から iptables へ変更しました

スポンサーリンク

説明

ufw は iptables のラッパーですが、ここでは、海外からの接続ブロック用の iptables のルールを作成し、それを ufw から利用します。

以降の [準備・実行] の手順で説明している drop_except_jp.sh を実行すると、次のような iptables コマンドが実行されます。
x.x.x.x/yy の箇所が IPアドレス(のCIDR表記)で、世界の国別 IPv4 アドレス割り当てリスト を使って、日本国内のIPを列挙しています。

iptables -F DROP_EXCEPT_JP
iptables -A DROP_EXCEPT_JP -p tcp -m multiport --dport $EXCLUDE_PORTS -m state --state NEW -j RETURN
iptables -A DROP_EXCEPT_JP -s x.x.x.x/yy -j RETURN
iptables -A DROP_EXCEPT_JP -s x.x.x.x/yy -j RETURN
      :
iptables -A DROP_EXCEPT_JP -j DROP

以降の [準備・実行] の手順では、ufw のルール評価より前に、この iptables のルールが評価されるように設定します。

この iptables のルールでは、接続元IPが日本国内のIPの場合、RETURN します。
RETURN(=特に許可も拒否もしない)の後、本来の ufw のルール評価がされます。
RETURNされなかったアドレス(=日本以外のアドレス=海外のアドレス)からの接続は、DROP します。

準備・実行

root で次の設定をします。

/etc/ufw/before.rules

COMMIT の前に、次の3行を入れます。

:DROP_EXCEPT_JP - [0:0]
-A DROP_EXCEPT_JP -j ACCEPT
-A ufw-before-input -j DROP_EXCEPT_JP
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT

/etc/ufw/after.init

start、stop の箇所を次のようにします。

start)
    # typically required
    /etc/ufw/after.init.drop_except_jp
    ;;
stop)
    # typically required
    iptables -F DROP_EXCEPT_JP
    ;;

次を実行します。
注:この chmod +x をしないと、after.init は実行されません

chmod +x /etc/ufw/after.init

次のスクリプトを作成します。
場所はどこでもいいですが、スクリプトの箇所に cidr.txt.gz、cidr.txt が作成されます。

drop_except_jp.sh

#!/bin/sh
IPTABLES=iptables
EXCLUDE_PORTS=80,443,25
wget -q -N http://nami.jp/ipv4bycc/cidr.txt.gz
gunzip -q -f -c cidr.txt.gz > cidr.txt
if [ -f cidr.txt ]; then
    echo $IPTABLES -F DROP_EXCEPT_JP
    echo $IPTABLES -A DROP_EXCEPT_JP -p tcp -m multiport --dport $EXCLUDE_PORTS -m state --state NEW -j RETURN
    # 次の行は必要に応じて
    echo $IPTABLES -A DROP_EXCEPT_JP -s 192.168.1.0/24 -j RETURN
    sed -n 's/^JP\t//p' cidr.txt | while read address; do
        echo $IPTABLES -A DROP_EXCEPT_JP -s $address -j RETURN
    done
    echo $IPTABLES -A DROP_EXCEPT_JP -j DROP
fi

なお、「# 次の行は必要に応じて」の後に、接続したい日本のIP以外のアドレスがあれば、
echo $iptables -A DROP_EXCEPT_JP -s 192.168.1.0/24 -j RETURN
のように記述してください。
(localhost(127.0.0.1)からの接続は ufw のデフォルトで許可されているので、ここでの設定は不要です)

また、ブロックしないポート番号があれば、EXCLUDE_PORTS= の行に記載してください。
ここでは、80(HTTP)、443(HTTPS)、25(SMTP)を記載しています。

WEBサーバの場合、海外からの接続を遮断すると、google/yahoo/bingなどのクローラのアクセスまでブロックします。
その為、検索にひっかからないようになりますので、WEBへのアクセス(80、443)は海外からも接続できるようにしています。

メールサーバの場合も、25番をブロックすると、メールが届かなくなるので、ここでは接続できるようにしています。

drop_except_jp.sh を作成したら、次を実行します。

sh drop_except_jp.sh > /etc/ufw/after.init.drop_except_jp
chmod +x /etc/ufw/after.init.drop_except_jp

最後に ufw を再起動すると、ここまでの手順で設定した海外からの接続ブロックが動作します。

systemctl restart ufw

運用

どのIPアドレスがどの国にを割り当てられているかは、時々変わりますので、先の手順で作成した、海外からの接続ブロック用の iptables のルールも更新する必要があります。

そこで、時々、先の手順で作成した drop_except_jp.sh を以下のように実行し、ufw を再起動して、更新されたIPアドレスを反映させてください。

sh drop_except_jp.sh > /etc/ufw/after.init.drop_except_jp
systemctl restart ufw

その他

・どのIPアドレスがどの国にを割り当てられているかが変わった場合に、ブロック対象のルールを再適用しやすいように、iptables のルールとして分離させています。

・ufw の起動時に、/etc/ufw/before.init 実行の後、/lib/ufw/ufw-init-functions 内で IPTABLES -F で iptables のルールの初期化がされます。そこで、ブロック用に設定した iptables のルールが初期化されないように、ufw-init-functions の後に実行される after.init で、iptables の設定をしています。

・iptables のルールの初期化がされるので、iptables-persistent で iptables の設定内容の save はできません。

コメント

  1. Nocchi より:

    お世話になります。
    とても素敵な記事を掲載いただきましてありがとうございます!
    海外のIPアドレスに対してアクセスを弾くことができてとても助かりました。
    感謝いたしております。

    ところで、この設定をサーバにしたところ、Gmailへメールが送れなくなりました。
    Gmail does not accept messages from 550-5.7.25 IPs with missing PTR records. となってしまい
    PTRレコードが弾けなくなったからだと思います。
    回避方法ってありますでしょうか?

    あとEXCLUDE_PORTSの書き方ですがポート番号を指定した場合、以下のような書き方で遭っていますか?
    EXCLUDE_PORTS=53/tcp,53/udp,80,443
    この理解でよろしいでしょうか?

  2. パソコン鳥 より:

    53番ポートの設定をしようとされているので、サーバーではDNSも動いてますでしょうか。
    UDP/TCPの53番を通す必要がありますが、EXCLUDE_PORTS の指定はポート番号のみです。
    EXCLUDE_PORTS は、drop_except_jp.sh の
    echo /sbin/iptables -A DROP_EXCEPT_JP -p tcp -m multiport –dport $EXCLUDE_PORTS -m state –state NEW -j RETURN
    で使っていますが、–dport ではポート番号のみ指定可能なためです。また -p tcp の通り、プロトコルはtcpのみです。
    udpを通す場合は、未検証で申し訳ないですが、上記の後に
    echo /sbin/iptables -A DROP_EXCEPT_JP -p udp –dport 53 -j RETURN
    echo /sbin/iptables -A DROP_EXCEPT_JP -p udp –sport 53 -j RETURN
    を追加してみてください。

  3. Nocchi より:

    ご返信ありがとうございます!

    > 53番ポートの設定をしようとされているので、サーバーではDNSも動いてますでしょうか。
    はい。そうなんですね。

    教えて下さった方法で試したところ、順調に逆引きできているようでした。
    ありがとうございました。

    mailqにspamメールがあり得ない勢いでたまってしまっていたのでとても助かりました。
    ありがとうございます。

  4. shers より:

    僕もubuntu20.04でこの方法をやりました。ですが海外からアクセスしてもIPがブロックされません。
    なんででしょうか?

  5. shers より:

    僕もubuntu20.04でこの方法をやりました。ですが海外からアクセスしてもIPがブロックされません。
    なんででしょうか?
    追記:ufwをアクティブにしたらできました。(迷惑をおかけしてすいません。)