f16: xserver vps + ubuntu + 海外アクセス抑止 + 自動更新

.
---

以前の記事
f13: xserver vps + ubuntu + ssh + python
https://qiita.com/cxfgp/items/ce1055522c0ec3c0bceb
の派生メモです

xserver vps + ubuntu + ufw にて
海外からのアクセス抑止設定を行います
また、それらの定期自動更新の設定を行います

---
### **[ 00. メニュー ]**

**01. キッチン**
**02. 海外からの接続ブロック設定・更新**
**03. ufw 再起動**
**04. 自動更新 (crontab) 設定**

---
### **[ 01. キッチン ]**

　**・Xserver VPS / 2GB プラン**
　　**-> Ubuntu 22.04 (64bit)**

　　( root 操作 )
　**・Xserver VPS (VPSパネル) WEB コンソール**
　　**(または ssh + su コマンド)**

　　( 一般ユーザー 操作 (ssh) )
　**・Tera Term Pro version 4.105**

　※ 上記 以前の記事 で、ssh の root ログイン禁止、および、
　　　ssh でのパスワードログイン禁止にしてます

　※ VPSパネル へのログインは 二段階認証 設定をしておいたほうがいいです
　　Xserver VPS 二段階認証について
　　https://vps.xserver.ne.jp/support/manual/man_order_twostepauth.php
　　また、状況・環境により、ssh + su コマンド実行の
　　許可ユーザーの制限も考慮したほうがいいです

---
### **[ 02. 海外からの接続ブロック設定・更新 ]**

海外からの接続ブロック の設定については、
先人の方の以下記事の設定・構造が
非常にわかりやすい + 管理しやすい為、
そのまま利用させていただいております

[Ubuntu] ファイアウォール ufw で海外からの接続をブロックする
https://pcvogel.sarakura.net/2020/09/09/32067

ポイントは、

　・WEB(80、443)、メール(25) ポートは抑止除外していること

　・/etc/ufw/ 関連の設定変更や実行、および、後述する crontab 設定は、
　　sudo ではなく root ユーザーを使用します

　・事前に # select-editor で、お好みのエディタ(nano, vi 等)の
　　番号を入力して Enter を押しておくといいと思います

といったところです

drop_except_jp.sh は、処理ログ追加や
チェック用の if 分岐追加を行いました

```bash:drop_except_jp.sh
#!/bin/sh

# 日付時刻1
date1=`date +"%Y/%m/%d %T"`

# スクリプトパスの取得
s_dir=$(cd $(dirname $0) && pwd)

# 処理ログ設定
lgs1=${s_dir}/ipt-process.log

# iptables 設定
IPTABLES=iptables
EXCLUDE_PORTS=80,443,25

# 更新ファイル設定1
cid1=${s_dir}/cidr.txt.gz
# 更新ファイル設定2
cid2=${s_dir}/cidr.txt

# スクリプトパスへ移動
cd ${s_dir}

# 前回 cidr.txt.gz の削除
if [ -f $cid1 ]; then
    rm -rf $cid1
    echo "$date1 : delete: OK: cidr.txt.gz" >> $lgs1
else
    echo "$date1 : delete: NG: NOT-FOUND cidr.txt.gz" >> $lgs1
fi

# 前回 cidr.txt の削除
if [ -f $cid2 ]; then
    rm -rf $cid2
    echo "$date1 : delete: OK: cidr.txt" >> $lgs1
else
    echo "$date1 : delete: NG: NOT-FOUND cidr.txt" >> $lgs1
fi

# 4秒後、日付時刻2 + cidr.txt.gz ダウンロード
sleep 4s; date2=`date +"%Y/%m/%d %T"`
wget -q -N http://nami.jp/ipv4bycc/cidr.txt.gz

# cidr.txt.gz ファイルチェック
if [ -f $cid1 ]; then
    echo "$date2 : dl: OK: cidr.txt.gz" >> $lgs1
else
    echo "$date2 : dl: NG: NOT-FOUND cidr.txt.gz" >> $lgs1
fi

# 2秒後、.gz 解凍
sleep 2s; gunzip -q -f -c $cid1 > $cid2

# 2秒後、日付時刻3
sleep 2s; date3=`date +"%Y/%m/%d %T"`

# cidr.txt 更新ファイルチェック + 適用
if [ -f $cid2 ]; 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' $cid2 | while read address; do
        echo $IPTABLES -A DROP_EXCEPT_JP -s $address -j RETURN
    done

    echo $IPTABLES -A DROP_EXCEPT_JP -j DROP
    echo "$date3 : OK: updated iptables rule" >> $lgs1

else

    echo "$date3 : NG: not found cidr.txt or not a file" >> $lgs1

fi
```


---
### **[ 03. ufw 再起動 ]**

ufw 再起動も記事中にある
systemctl restart ufw
を行えばいいだけですが、
自動処理を想定して以下のスクリプトを作成しました


```bash:restart_ufw.sh
#!/bin/sh

# スクリプトパスの取得
s_dir=$(cd $(dirname $0) && pwd)

# 処理ログ設定
lgs1=${s_dir}/ipt-process.log

# ufw ステータス ログ設定
lgs2=${s_dir}/ufw-status.log

# 日付時刻1
dates1=`date +"%Y/%m/%d %T"`
echo "$dates1 : str ufw re-start" >> $lgs1

# ufw 再起動
systemctl restart ufw

# 20秒後、日付時刻2
sleep 20s; dates2=`date +"%Y/%m/%d %T"`
echo "$dates2 : end ufw re-start" >> $lgs1

# ufw ステータス 取得
systemctl status ufw -l> $lgs2

# 2秒後、日付時刻3
sleep 2s; dates3=`date +"%Y/%m/%d %T"`

# ufw status 日付の比較用に システム日付取得
dates4=`date +"%Y-%m-%d"`

# ufw status ログ内の active (exited) 存在チェック
if grep -q "active (exited)" $lgs2; then

   # A) "Active: active (exited) since Sat 2023-07-15 21:32:10 JST; 20s ago"　の 1行 取得
   comp4=`grep "Active:" $lgs2 | { IFS= read -r lines && trimmed_lines=$(echo "$lines" | awk '{$1=$1};1'); echo "$trimmed_lines"; }`

   echo "$dates3 : $comp4" >> $lgs1

   # B) A) の 行から 6つ目のフィールド YYYY-MM-DD の抽出
   rid_date=$(echo "$comp4" | awk '{print $6}')

   # ufw ステータス ログ内に 処理同日の日付があるかチェック
   if [ "$rid_date" = "$dates4" ]; then
     echo "$dates3 : OK: ufw status: active (exited) + $rid_date" >> $lgs1
   else
     echo "$dates3 : NG: ufw status: active (exited) + date NOT-FOUND: $dates4" >> $lgs1
   fi

else

   # C) NG として Active: 行のログ出力
   grep "Active:" $lgs2 | { IFS= read -r lines && trimmed_lines=$(echo "$lines" | awk '{$1=$1};1'); echo "$dates3 : NG: NOT-FOUND active: $trimmed_lines"; } >> $lgs1

fi
```

---
### **[ 04. 自動更新 (crontab) 設定 ]**

以下を実行しますと、

```bash:
# sh /home/userA/ufw-update/drop_except_jp.sh > /etc/ufw/after.init.drop_except_jp
# sh /home/userA/ufw-update/restart_ufw.sh
```
このようにログに出力されます

・ufw ステータス ログ
```bash:
# cat ufw-status.log
● ufw.service - Uncomplicated firewall
     Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sun 2023-07-16 01:27:05 JST; 20s ago
       Docs: man:ufw(8)
    Process: 173451 ExecStart=/lib/ufw/ufw-init start quiet (code=exited, status=0/SUCCESS)
   Main PID: 173451 (code=exited, status=0/SUCCESS)
        CPU: 2.601s

 7月 16 01:27:03 x162-43-7-17 systemd[1]: Starting Uncomplicated firewall.
 7月 16 01:27:05 x162-43-7-17 systemd[1]: Finished Uncomplicated firewall.
```

・処理ログ
```bash:
# cat ipt-process.log
2023/07/16 01:25:27 : delete: OK: cidr.txt.gz
2023/07/16 01:25:27 : delete: OK: cidr.txt
2023/07/16 01:25:31 : dl: OK: cidr.txt.gz
2023/07/16 01:25:35 : OK: update iptables rule
2023/07/16 01:27:02 : str ufw re-start
2023/07/16 01:27:25 : end ufw re-start
2023/07/16 01:27:27 : Active: active (exited) since Sun 2023-07-16 01:27:05 JST; 20s ago
2023/07/16 01:27:27 : OK: ufw status: active (exited) + 2023-07-16
```

プロンプト実行が問題ないようでしたら、以下 自動処理を設定します

※ crontab を使います、crontab -r (確認なし削除) などご注意ください

・設定
例: 毎週 月木(1,4) 05:10am, 05:20am に実行

```bash:
# select-editor
　Select an editor.  To change later, run 'select-editor'.
　1. /bin/nano <---- easiest
　2. /usr/bin/vim.basic
　3. /usr/bin/vim.tiny
　4. /bin/ed

# crontab -u root -e
10 5 * * 1,4 sh /home/userA/ufw-update/drop_except_jp.sh > /etc/ufw/after.init.drop_except_jp
20 5 * * 1,4 sh /home/userA/ufw-update/restart_ufw.sh
```

・設定確認
```bash:
# crontab -l
```

---
.