月: 2022年12月 Page 1 of 4

2022年のさっくりとしたまとめ。

気がつけば大晦日。今年の個人的な出来事を軽く振り返ってみます。

各月ごとの特記事項

1月

  • 新しいデジタルカメラE-PL7を購入
  • 電子書籍『Redmineで始める異世界人心掌握術』に大いに感銘を受ける

2月

  • redmineの運用を本格的に開始
  • iPad mini新調

3月

  • 検証機のredmineサーバを吹っ飛ばしたことをきっかけに自宅に専用サーバ立ち上げ

4月

  • redmineのバックアップ用などのために自宅サーバをもう1台追加
  • 仕事で苦しかった時期

5月

  • とても久しぶりのボードゲームオフ会
  • 仕事でとても苦しかった時期
  • AWSでredmine立ち上げ

6月

  • Chromebook新調
  • ちょっとした決断をする

7月

  • コロナ罹患、施設療養を体験

8月

  • E-PL7用のマクロレンズを購入
  • スマートフォン新調
  • 自宅サーバ3台目を追加

9月

  • 2年ぶりの旅行
  • 『ライザのアトリエ』コラボをきっかけに『アズールレーン』復帰

10月

  • NextCloud立ち上げ
  • ブロンプトンを修理に出す
  • ジブン手帳との再会

11月

  • メインの万年筆をLAMYに切り替え
  • 修理に出したブロンプトンの改修完了
  • 『アズールレーン』ライザのアトリエコラボ、予想以上の出来に驚愕と歓喜

12月

  • E-PL7用の広角レンズを購入
  • Dropbox→Nextcloudに移行
  • AWSインスタンスをもう一台追加

特に印象的だったこと

redmineの本格運用

これにつきます。元々は正月休みに軽く読んでみた『Redmineで始める異世界人心掌握術』を楽しく読むことができ、仕事でなんとなく使っていたredmineに可能性を見たことでした。

ここから

  1. 自分で実際に立ち上げて
  2. redmineの検証を開始し
  3. 検証DBを吹っ飛ばしたことで冗長化の大切さを学び
  4. 出先でも使いたいためにAWSを立ち上げ
  5. その過程でセキュリティ技術をかじり始める

と、「redmineと戯れた」一年でした。このツール、個人利用だけでもとても使い出があります。後述した療養生活でも体調を記録するために役立ちました。

コロナ感染

こちらもまた特筆すべきことです。検査→陽性確定→療養は気が気でありませんでした。これが徒となって

  • 夏休みの尾道旅行をキャンセル
  • ブロンプトンの改修が4ヶ月先送りになる

憂き目に遭います。軽症で済んだことと、家族や職場のサポートに感謝しました。

願わくば、2023年がよき年であるように。

Fail2Banによるセキュリティ対策。(SSH保護)

概要

AWSはメジャーなサービスのため、ここで使われているIPアドレスは攻撃のリスクがとても高くなります。
ここでSSH権限を乗っ取ろうとする攻撃に備え、Fail2Banを導入しました。

Fail2Banとは

様々なログファイルを読み込み、何度もアクセスを繰り返すようなアクセス元を遮断するプログラムです。

前提

  • AWS Ligthsailで動かしているUbuntu 20.04サーバ/Ubuntu22.04サーバで動作を確認しています。
  • (当然のように)SSHが導入されていることが大前提です。

手順

  • 全て管理者権限で実施しています。
  • パッケージ管理にaptitudeを利用しています。必要に応じてaptに読み替えてください。

参考:
https://www.kkaneko.jp/tools/server/fail2ban.html

https://github.com/mitchellkrogza/Fail2Ban-Blacklist-JAIL-for-Repeat-Offenders-with-Perma-Extended-Banning

Fail2Banのインストール

aptitude update
aptitude install fail2ban

wget https://raw.githubusercontent.com/mitchellkrogza/Fail2Ban-Blacklist-JAIL-for-Repeat-Offenders-with-Perma-Extended-Banning/master/filter.d/blacklist.conf -O /etc/fail2ban/filter.d/blacklist.conf

wget https://raw.githubusercontent.com/mitchellkrogza/Fail2Ban-Blacklist-JAIL-for-Repeat-Offenders-with-Perma-Extended-Banning/master/action.d/blacklist.conf -O /etc/fail2ban/action.d/blacklist.conf

systemctl restart fail2ban
systemctl status fail2ban
# active (running) を確認します

Fail2Banのログローテーション変更

mv /etc/logrotate.d/fail2ban /backup/directory/path/fail2ban.bak
vi /etc/logrotate.d/fail2ban
設定内容
/var/log/fail2ban.log {
                monthly
                rotate 13
                compress
                delaycompress
                missingok
                notifempty
                postrotate
                fail2ban-client flushlogs 1>/dev/null
                endscript
                create 640 root adm
                }

設定反映

fail2ban-client reload
# OKを確認します

fail2ban-client status sshd

#以下のように表示されました

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list: 

systemctl enable fail2ban
# 自動起動を行います

設定ファイルを作成します

vi /etc/fail2ban/jail.local 
設定内容
[DEFAULT]
port = 0:65535

filter = %(__name__)s
[blacklist]
enabled = true
logpath  = /var/log/fail2ban.*
filter = blacklist
banaction = blacklist
action = %(action_)s
bantime  = 31536000   ; 1 year
findtime = 31536000   ; 1 year
maxretry = 10

追加した設定を反映させます

touch /etc/fail2ban/ip.blacklist
chmod 775 /etc/fail2ban/ip.blacklist
systemctl restart fail2ban
fail2ban-client reload
systemctl restart sshd

systemctl enable fail2ban

導入後に注意する内容

cat /var/log/fail2ban.log
cat /etc/fail2ban/ip.blacklist

AWSで運用しているだけあって、かなりのログが引っかかっています。

AWS LightsailでのUbuntu20.04立ち上げとUbuntu22.04へのアップグレード。

概要

定額でAWSのインスタンスを利用できるLightsail。

Ubuntu系OSを利用できるものの、2022年12月時点ではUbuntu22.04に対応していません。

20.04は選べますので、

  1. Ubuntu20.04で新たなインスタンスを立ち上げる
  2. Ubuntu22.04にアップグレードする

方法を紹介します。

どハマりしたこと

結論を言うと、Ubuntu 22.04にアップグレードするとLigtsailの管理画面から直接SSHすることはできません。
(SSH-1アルゴリズムによるRSA認証が無効化されます)

つまり、 何も設定せずWeb画面のSSH接続で最初にアップグレードをすると、再起動した瞬間にログインできず詰みます。

これに気づかず、アップグレード後に全くログインできずインスタンスを作り直す羽目になりました。以下はメモとして残しておきます。

成功した手順(さっくりした手順)

以下、ある程度の知識がある方ならこの手順を行えば問題ないと思います。

  1. Lightsail上でUbuntu 20.04のインスタンスを立ち上げる。
  2. 静的IPを付与してIPを固定化する。
  3. 必要に応じてDNSレコードに登録する。
  1. Lightsail管理画面から初期ユーザーでログインする。
  2. 初期ユーザー以外のrootに昇格可能なユーザーを作成する。
  3. そのユーザーで強力な暗号による秘密鍵/公開鍵を設定する。
  4. Ubuntu 20.04 → 22.04にアップグレードする。

成功した手順(より詳細な記述)

インスタンスの作成

AWS Lightsailの管理画面にログインします。

https://lightsail.aws.amazon.com/ls/webapp/home/instances

「インスタンスの作成」をクリックします。

インスタンス作成

自分は以下のように選択しました。

  • リージョン:東京
  • インスタンスイメージの選択:Linux (OSのみ)
  • Ubuntu 20.04 LTSを選択。
  • 月次料金:10USD/月
  • インスタンス名:任意のもの
  • そのほかは空白

→設定後、「インスタンスの作成」をクリックします。
 → 作成後、「ネットワーキング」から静的IPを付与します。
  → 必要に応じてDNSを設定し、名前解決できるようにします。

管理画面のWebコンソール(SSH)操作

Web画面からログインし、rootに昇格します。

sudo su -
# この時、パスワードは設定されていないのでそのまま昇格できます。

ここから、ローカルのターミナルクライアントから接続できるようにユーザーを作成し、設定します。

ここではhogeとしていますので、任意のユーザーを指定して下さい。

adduser hoge
# パスワードなどを設定します

usermod -G sudo hoge
# ユーザーhogeを管理者グループに入れます

su - hoge
# ユーザーhogeに変われることを確認します

sudo su -
# パスワード入力後にrootに昇格できることを確認します

exit
# ユーザーhogeに戻ります

whoami
# ユーザーhogeであることを確認します

ssh-keygen -t ed25519
# 鍵の格納場所は初期値でいいので空Enter。(/home/hoge/.ssh/
# パスワードを設定します。

cd .ssh
ls -l
# 以下のファイルを確認します
# └id_ed25519
# └id_ed25519.pub
# ※これらのファイルはscp等で自分のクライアントにコピーします

rm id_ed25519
# sshサーバ上でそのまま鍵を作成したので秘密鍵は*クライアントにコピー後*削除します

mv id_ed25519.pub authorized_keys
chmod 600 authorized_keys
# 公開鍵をauthorized_keysに変更し、パーミッションを厳密にします

この後、ローカルにコピーしたid_ed25519をSSHターミナルクライアントに保存して設定し、接続確認を行います。

接続ができたらいよいよUbuntu 20.04→Ubuntu22.04へのアップグレードです。

ローカルPC(ターミナルクライアント)からの操作

whoami
#上記、作成したユーザーであることを確認します

sudo su -
# rootに昇格できることを確認します

apt update && apt upgrade && apt autoremove
# パッケージを最新版にして不要パッケージを削除します。途中で不要パッケージを消すかを求められるので[y]で消去します

reboot
# 一度再起動をします
# 再起動後、ログインします

Ubuntu20.04→22.04へのアップグレード

whoami
#上記、作成したユーザーであることを確認します

sudo su -
# rootに昇格できることを確認します

do-release-upgrade
# *ここからの作業は中断せず、一気通貫で行います*
アップグレード中にプロンプトから質問されたこと

以下、主要な質問事項です。コメント(#の後)に概要を書いています。

Reading cache

Checking package manager

Continue running under SSH?

This session appears to be running under ssh. It is not recommended
to perform a upgrade over ssh currently because in case of failure it
is harder to recover.

If you continue, an additional ssh daemon will be started at port
'1022'.
Do you want to continue?

# SSHのポートを追加するか
# → y

Starting additional sshd 

To make recovery in case of failure easier, an additional sshd will 
be started on port '1022'. If anything goes wrong with the running 
ssh you can still connect to the additional one. 
If you run a firewall, you may need to temporarily open this port. As 
this is potentially dangerous it's not done automatically. You can 
open the port with e.g.: 
'iptables -I INPUT -p tcp --dport 1022 -j ACCEPT' 

To continue please press [ENTER]

# 設定を変更するか
# → Enter

Do you want to start the upgrade?


4 packages are going to be removed. 85 new packages are going to be
installed. 555 packages are going to be upgraded.

You have to download a total of 247 M. This download will take about
49 seconds with a 40Mbit connection and about 6 minutes with a 5Mbit
connection.

Fetching and installing the upgrade can take several hours. Once the
download has finished, the process cannot be canceled.

 Continue [yN]  Details [d]

# アップグレード前の最終確認
# → y

There are services installed on your system which need to be restarted when certain libraries, such as libpam, libc, and libssl, are upgraded. Since these restarts may cause interruptions of service for the system, you will     x
   x normally be prompted on each upgrade for the list of services you wish to restart.  You can choose this option to avoid being prompted; instead, all necessary restarts will be done for you automatically so you can avoid being   x
   x asked questions on each library upgrade.                                                                                                                                                                                            x
   x                                                                                                                                                                                                                                     x
   x Restart services during package upgrades without asking?

# アップグレード時、各種サービスを再起動前にプロンプトでy/nを確認するか
# → 質問されるのがめんどいので yes

# この間、SSH等の設定変更を行うか訊いてきます。プロンプトの選択を変えずに先に進みました
# keep the local version currently installed

Remove obsolete packages? 

# 不要パッケージの削除
# → Yes

System upgrade is complete.

Restart required

To finish the upgrade, a restart is required.
If you select 'y' the system will be restarted.

Continue [yN]

# アップグレード完了後にリブートするか
# → y

こうして、再起動後、無事にアップグレードが完了です。

cat /etc/lsb-release

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"

アップグレード後の操作

以下、速やかに行います。

管理者に昇格できることを確認します。

sudo su -

rootのパスワードを設定します。

passwd root

初期ユーザー(ubuntu)が物理的にログインできないようにします。

cd /home/ubuntu/.ssh

rm authorized_keys

Let’s Encryptワイルドカード証明書によるredmineのSSL化対応。

先だって、AWS Lightsail上で2つめのredmineを構築する手順について触れました。

こちらをLet's Encryptで常時SSL化します。

前提

  • Ubuntu 20.04、Apache2での記録です。
  • 以下、sample.comで証明書を発行するための記録です。ドメインはお持ちのものを使ってください。(自環境で実施する際は必ず書き換えてください)
  • certbotで定期的に更新を行うのではなく、多目的に用いるために手動でワイルドカード証明書を発行する手順です。
  • 既にcertbotはインストールされていることと、DNSの更新権限を持っていることが前提です。

また、管理者権限で実施します。

ワイルドカード証明書発行

sudo certbot certonly --manual \
    --preferred-challenges dns-01 \
    --server https://acme-v02.api.letsencrypt.org/directory \
    -m メールアドレス \
    -d *.sample.com
TXTレコード登録
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
# IPは記録される旨を訊かれるので了承のためY

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.sample.com with the following value:

「文字列」

# 上記文字列をDNSのテキストレコードに登録します
# 登録後、
# nslookup -type=TXT _acme-challenge.sample.comを入力し、「文字列」が返ってくるまで少し待ちます

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

# TXTレコードが返ってくるのを確認したらEnter
発行完了
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/sample.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/sample.com/privkey.pem
   Your cert will expire on 2023-03-24. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

発行確認

cd /SSL一時格納ディレクトリ

cp -pi /etc/letsencrypt/live/sample.com/fullchain.pem ./sample.com.crt.$(date +%Y%m)
cp -pi /etc/letsencrypt/live/sample.com/privkey.pem ./sample.com.key.$(date +%Y%m)
# 一時格納ディレクトリにコピーします


openssl x509 -noout -dates -subject -in ./sample.com.crt.$(date +%Y%m)
# 証明書の発行期限を確認します

openssl x509 -in sample.com.crt.$(date +%Y%m) -noout -modulus | md5sum
openssl rsa -in sample.com.key.$(date +%Y%m) -noout -modulus | md5sum
# 証明書と秘密鍵のハッシュがそれぞれ一致していることを確認します

openssl x509 -issuer_hash -noout -in sample.com.crt.$(date +%Y%m)
sed -n -e'1d' -e'/BEGIN/,$p' sample.com.crt.$(date +%Y%m) | openssl x509 -subject_hash -noout
# 証明書と中間証明書のハッシュがそれぞれ一致していることを確認します

SSL格納、リンク貼り替え

mkdir /etc/certs
cp -pi sample.com.crt.$(date +%Y%m) /etc/certs
# 証明書ディレクトリ

cd /etc/certs
ln -sf sample.com.crt.$(date +%Y%m) sample.com.crt
# Let's Encryptは有効期限が3ヶ月と短いため、メンテナンスしやすいようにリンクを貼り替えるだけで更新できるようにします
ll
# シンボリックリンクが張られていることを確認します

mkdir /etc/private
cp -pi sample.com.key.$(date +%Y%m) /etc/private
# 秘密鍵ディレクトリ

cd /etc/private
ln -sf sample.com.key.$(date +%Y%m) sample.com.key
# Let's Encryptは有効期限が3ヶ月と短いため、メンテナンスしやすいようにリンクを貼り替えるだけで更新できるようにします
ll
# シンボリックリンクが張られていることを確認します
リリースファイル

cd /etc/sites-available/redmine2.conf

<VirtualHost *:80>
servername redmine2.sample.com
# 常時SSL化の設定
 RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost *:443>
  ServerName redmine2.sample.com
  ErrorLog /var/log/apache2/atlier/redmine2.sample.com_error.log
  CustomLog /var/log/apache2/atlier/redmine2.sample.com_access.log combined

Alias /redmine2 /var/lib/redmine2/public
<Location /redmine2>
PassengerBaseURI /redmine2
PassengerAppRoot /var/lib/redmine2
Require all granted
</Location>


#SSL対応
  SSLEngine on
    Protocols h2 http/1.1
    Header always set Strict-Transport-Security "max-age=63072000"

# 先に指定したLet's Encryptの格納先
SSLCertificateFile /etc/certs/sample.com.crt
SSLCertificateKeyFile /etc/private/sample.com.key

        # redmine2.sample.comでアクセスしてきた場合、強制的に/redmine2サブディレクトリに遷移します
        RewriteEngine On
        RewriteCond %{HTTP_HOST} ^redmine2\.sample\.com
        RewriteRule ^/$ https://redmine2.sample.com/redmine2/ [R]

</VirtualHost>

SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE6-GCM-SHA384
SSLHonorCipherOrder     off
SSLSessionTickets       off

SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

動作確認

http://redmine2.sample.com (自分が設定したドメイン名)にアクセスして

  • redmineの画面が表示されること
  • SSl通信に置き換わること

を確認します。また、こちらの設定は可能な限りSSLの強度を高めています。

https://www.ssllabs.com/ssltest/analyze.html

こちらの暗号化強度チェックで

A+となっています。(2022年12月現在

同一サーバ上で2つめのredmineを構築。

redmineはプロジェクトごとに機能の増減やアクセス権を増やせるものの、諸般の事情で「全く別のドメインで新たにredmineを構築する」必要がありました。

以下の手順でうまくいったので、メモとして残します。

環境

  • Ubunut 20.04 (AWS Lightsailインスタンス上)
  • 既に以下のredmineを立ち上げ済み
    • redmine 4.2
    • ruby 2.7
    • mysql 8.0.31

rubyのバージョンの関係で4.2系をインストールすることにします。また、既に動いている環境なのでapacheやmysqlの初期設定は行っていません。

立ち上げ手順

前提

  1. 新たなドメインを取得しているものとします。
  2. mysqlは同一サーバ上にあり、管理者権限を持っているものとします。
  3. この段階ではhttpsを行わないので、グローバル環境で実施する際は早急にSSL化を行ってください。
  4. また、筆者が使いたいプラグインの関係上、4.2をインストールします。

さっくりとした概要

次の内容を実施します。

  1. 新たなredmine用のデータベースを新規で作る。
  2. 現行とは別のディレクトリ上にredmineのプログラムを展開する。
  3. apacheのバーチャルホスト機能で新規redmineの機能を

注意事項

  • 現行のredmineをredmine.sample.com/redmine
  • 新しいredmineをredmine2.sample.com/redmine2

で稼働させます。

現行稼働している時に新しいものを立ち上げる場合は、現行環境のバックアップを取るなどの施策を行ってください。

以下、管理者権限で行います。

redmine用DB/ユーザ作成

mysql -uroot -p
CREATE DATABASE redmine2 character set utf8mb4;
CREATE USER 'redmine2'@'localhost' IDENTIFIED BY 'パスワード';
GRANT ALL ON redmine2.* TO 'redmine2'@'localhost';
flush privileges;
exit

redmine取得

ソースダウンロード

mkdir /var/lib/redmine2
chown -R www-data:www-data /var/lib/redmine2
sudo -u www-data svn co https://svn.redmine.org/redmine/branches/4.2-stable /var/lib/redmine2

configファイル編集

cp -pi /var/lib/redmine2/config/database.yml.example /var/lib/redmine2/config/database.yml
vi /var/lib/redmine2/config/database.yml
編集ファイル内容

productionの部分を以下のように変更します。

production:
  adapter: mysql2
  database: redmine2
  host: localhost
  username: redmine2
  password: "パスワード"
  encoding: utf8mb4

redmineインストール

cd /var/lib/redmine2
sudo -u www-data bundle install --without development test --path vendor/bundle
sudo -u www-data bundle exec rake generate_secret_token
sudo -u www-data RAILS_ENV=production bundle exec rake db:migrate
sudo -u www-data RAILS_ENV=production REDMINE_LANG=ja bundle exec rake redmine:load_default_data

設定ファイル編集

vi /etc/apache2/sites-available/redmine2.conf
設定ファイル内容
<VirtualHost *:80>
  ServerName redmine2.sample.com

Alias /redmine2 /var/lib/redmine2/public
<Location /redmine2>
PassengerBaseURI /redmine2
PassengerAppRoot /var/lib/redmine2
Require all granted
</Location>

  ErrorLog /var/log/apache2/redmine2.sample.com_error.log
  CustomLog /var/log/apache2/redmine2.sample.com_access.log combined
</VirtualHost>

リダイレクトなどで軽くハマり、この設定に落ち着きました。この後、SSL化の手順を実施します。

設定ファイル有効化

a2ensite redmine2.conf
apache2ctl configtest
# Syntax OKを確認します。
systemctl  reload apache2.service

アクセス確認

http://redmine2.sample.com/redmine2

でログインします。

Mod_SecurityのIPアドレス調査。(Cronによる自動実行)

2022年12月現在、「Mod_Securityが検知したIPアドレスネガティブリストに放り込む」は達成しました。

  • これら検知したIPはどこの国からか?
  • 日々、どのぐらいの数、不審なアクセスが来ているのか?

を把握するため、シェルスクリプトを書きました。(今回で一端終了です)

やりたいこと

  1. Mod_securityが検知したエラーログからIPアドレスのみを抜き出す
  2. 検出したIPアドレスがどこの国からアクセスしたかを調査してcsvファイルに出力する
  3. 同じIPアドレスごとに件数を数え、降順で並べ替える
  4. cronで定期実行する

本項でやること

  1. cronで定期実行

前提

  • エラーログからIPアドレスを抜き出しアクセス元の国を抜き出すスクリプト
  • そのIPアドレスをカウントして降順に表示するスクリプト

が用意されていること。(前回前々回で提示)

また、

  • apacheのログが日ごとにローテーションされていること
  • redmineの稼働サーバに導入しているので、ログ表示プラグインで閲覧できる

も想定しています。

スクリプト作成

cron用に一部手を加えます。

エラーログからIPアドレスを抜き出してアクセス元の国を付与

ip_check.sh

スクリプト内容

#!/bin/bash

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# ログの格納場所に移動
cd /var/lib/redmine/log

# error.logからIPアドレスだけを抜き出します
cat ./error.log | awk 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) { print  substr($0, RSTART, RLENGTH) }' | sort > ip.`date +%Y%m%d`.csv

listfile="./ip.`date +%Y%m%d`.csv"
# ip.YYYYMMDD.csvファイルがない場合にエラーを返します
if [ ! -f $listfile ]; then
        echo "ファイル $listfile が存在しないので終了します。"
        exit 1
fi

country_list="./country_list.csv"
# 国コード,国の名前が書かれたcountry_list.csvがない場合にエラーを返します
# このCSVファイルはログの格納場所に配置します
if [ ! -f $country_list ]; then
        echo "ファイル $country_list が存在しないので終了します。"
        exit 1
fi

# IPアドレスに国名を付与したファイルを定義します。(ip_list.YYYYMMDD.csv)
result_file="./ip_list.`date +%Y%m%d`.csv"
cat /dev/null > $result_file

cat ${listfile} | while read line
do
                # IPアドレスを逆順に並び替えます。(例: 1.2.3.4 → 4.3.2.1
                ip_revers=`echo ${line}|awk -F'.' '{print $4,".",$3,".",$2,".",$1}'|sed -e 's/ //g'`
                # 並び替えたIPアドレスをcc.wariate.jpに並び替えて、国コードを抜き出します。(JP,CH,ESなど
                country_code=`nslookup -type=TXT ${ip_revers}.cc.wariate.jp | grep '"'|awk -F'"' '{print $2}' `
                # 国コードをcountry_list.csvから参照して国名を抜き出します。
                country_name=`cat ${country_list} | grep ${country_code} | cut -d"," -f 2`

                # 次の行は標準出力に返す処理を行います。cron処理する場合は#をつけて作動しないようにします。
                # echo "${line},${country_name}"
                # IPアドレス,国名の形式にして同ディレクトリのip_list.YYYYMMDD.csvに保存します
                echo "${line},${country_name}" >> $result_file
        sleep 1
done

chown www-data:www-data ip.`date +%Y%m%d`.csv
chown www-data:www-data ip_list.`date +%Y%m%d`.csv

exit

アクセス元の国を付与したリストを集計するスクリプト

ip_count.sh

スクリプト内容

#!/bin/bash

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

cd /var/lib/redmine/log

# ip_list.csv.YYYYMMDDを読み込んで、IPアドレスをキー、国を値とする連想配列を作成します
declare -A countries
while read -r line; do
  # CSVの1列目をIPアドレス、2列目を国とします
  ip=$(echo $line | cut -d',' -f1)
  country=$(echo $line | cut -d',' -f2)
  # 連想配列に格納します
  countries[$ip]=$country
done < ip_list.`date +%Y%m%d`.csv

# 結果を格納するための変数を定義します
result=""

# 連想配列を反復処理します
for ip in "${!countries[@]}"; do
  # 各IPアドレスの件数を数えます
  count=$(grep -c $ip ip_list.`date +%Y%m%d`.csv)
  # 件数、IPアドレス、国をカンマ区切りで結合します
  line="$count,$ip,${countries[$ip]}"
  # 結果に追加します
  result="$result\n$line"
done

# カウントした結果をcounted_ip.YYYYMMDD.csvに出力します
echo -e $result > counted_ip.`date +%Y%m%d`.csv

### ↑ここまでchatGPTが作成したスクリプト↑ ###

# 最終結果をsorted_ip.`date +%Y%m%d`.csvに出力します
# LC_ALL=Cを設定しないと日本語で書かれた国名の並べ替えがうまくいきませんでした
cat counted_ip.`date +%Y%m%d`.csv |LC_ALL=C sort -n -r > sorted_ip.`date +%Y%m%d`.csv

# 最終結果以外のログファイルを削除します
# 必要に応じて無効化してください
rm ip.`date +%Y%m%d`.csv
rm ip_list.`date +%Y%m%d`.csv
rm counted_ip.`date +%Y%m%d`.csv

chown www-data:www-data sorted_ip.`date +%Y%m%d`.csv

exit

Cron配置

sudo crontab -e -u root

定期実行

0 7 * * * /スクリプト配置パス/ip_check.sh && /スクリプト配置パス/ip_count.sh

これで、指定した時刻に

  1. IPアドレスの抜き出し
  2. IPアドレスの集計

を行うようにしてくれます。

Mod_SecurityのIPアドレス調査。(IPアドレスごとのカウント)

2022年12月現在、「Mod_Securityが検知したIPアドレスネガティブリストに放り込む」は達成しました。

  • これら検知したIPはどこの国からか?
  • 日々、どのぐらいの数、不審なアクセスが来ているのか?

を把握するため、シェルスクリプトを書きました。(前回はこちらです)

やりたいこと

  1. Mod_securityが検知したエラーログからIPアドレスのみを抜き出す
  2. 検出したIPアドレスがどこの国からアクセスしたかを調査してcsvファイルに出力する
  3. 同じIPアドレスごとに件数を数え、降順で並べ替える
  4. cronで定期実行する

本項でやること

  1. 同じIPアドレスごとに件数を数え、降順で並べ替える

前提と準備

以下の環境です。

  • Ubuntu 20.04とCentOS 7以降で動作を確認しました。

前回の「エラーログからIPアドレスのみを抽出し、アクセス元の国を付与する」スクリプトが導入されていることが条件です。

スクリプト生成

参考

chatGPTの力を借りました。何度か質問を変え、動作確認しつつコマンドを足しています。

1. スクリプトを作成します。

vi ip_count.sh
スクリプト内容
#!/bin/bash

# ip_list.csv.YYYYMMDDを読み込んで、IPアドレスをキー、国を値とする連想配列を作成します
declare -A countries
while read -r line; do
  # CSVの1列目をIPアドレス、2列目を国とします
  ip=$(echo $line | cut -d',' -f1)
  country=$(echo $line | cut -d',' -f2)
  # 連想配列に格納します
  countries[$ip]=$country
done < ip_list.`date +%Y%m%d`.csv

# 結果を格納するための変数を定義します
result=""

# 連想配列を反復処理します
for ip in "${!countries[@]}"; do
  # 各IPアドレスの件数を数えます
  count=$(grep -c $ip ip_list.`date +%Y%m%d`.csv)
  # 件数、IPアドレス、国をカンマ区切りで結合します
  line="$count,$ip,${countries[$ip]}"
  # 結果に追加します
  result="$result\n$line"
done

# カウントした結果をcounted_ip.YYYYMMDD.csvに出力します
echo -e $result > counted_ip.`date +%Y%m%d`.csv

### ↑ここまでchatGPTが作成したスクリプト↑ ###

# 最終結果をsorted_ip.`date +%Y%m%d`.csvに出力します
# LC_ALL=Cを設定しないと日本語で書かれた国名の並べ替えがうまくいきませんでした
cat counted_ip.`date +%Y%m%d`.csv |LC_ALL=C sort -n -r > sorted_ip.`date +%Y%m%d`.csv

# 最終結果以外のログファイルを削除します
# 必要に応じて無効化してください
rm ip.`date +%Y%m%d`.csv
rm ip_list.`date +%Y%m%d`.csv
rm counted_ip.`date +%Y%m%d`.csv

exit 

スクリプトに実行権限を付与します。

chmod +x ip_count.sh

動作確認

任意のディレクトリに以下のファイルがあることを確認します。

  • ip_check.sh スクリプトが生成したログip_list.YYYYMMDD.csv
  • ip_count.sh スクリプト

スクリプト実行

./ip_count.sh

スクリプト実行結果

出力先(上記例ではスクリプトを配置したディレクトリ)に以下のファイルが出力されます。

  • sorted_ip.YYYYMMDD.csv (以下の様に、アクセスごとの件数とIPアドレスとアクセス元の国を記述し、アクセス数の降順で並べ替えたファイル)
100, AAA.BBB.CCC.DDD,シンガポール
30, AAA.BBB.CCC.DDD,ベトナム
20,AAA.BBB.CCC.DDD,中国
  • 同時に、以下のファイルが消去されます。
  • ip.YYYYMMDD.csv (エラーログからIPアドレスのみを抜き出したファイル)
  • ip_list.YYYYMMDD.csv (IPアドレスにアクセス元を追記したファイル)
  • counted_ip.YYYYMMDD.csv (IPアドレスごとのカウントを行ったファイル)

合間に余計なファイルが含まれるので、ここはもっとスマートに書きたいです。

次にやること

  1. cronによる定期実行化
  2. redmineのプラグインredmine_logsで閲覧できるように設定

Mod_SecurityのIPアドレス調査。(アクセス元の国を抜き出す)

2022年12月現在、「Mod_Securityが検知したIPアドレスネガティブリストに放り込む」は達成しました。

  • これら検知したIPはどこの国からか?
  • 日々、どのぐらいの数、不審なアクセスが来ているのか?

を把握するため、シェルスクリプトを書きました。

やりたいこと

  1. Mod_securityが検知したエラーログからIPアドレスのみを抜き出す
  2. 検出したIPアドレスがどこの国からアクセスしたかを調査してcsvファイルに出力する
  3. 同じIPアドレスごとに件数を数え、降順で並べ替える
  4. cronで定期実行する

本項でやること

  1. Mod_securityが検知したエラーログからIPアドレスのみを抜き出す
  2. 検出したIPアドレスがどこの国からアクセスしたかを調査してcsvファイルに出力する

前提と準備

以下の環境です。

  • Ubuntu 20.04とCentOS 7以降で動作を確認しました。

nslookupコマンドが実装されていること

which nslookup
# パスがあれば実装されています。
nslookupがない場合のインストール
sudo apt-get install dnsutils

スクリプト生成

参考

以下のスクリプトをベースにしています。

https://raintrees.net/news/11

本スクリプトの作成者様と、IPアドレスと国の対応を結びつけるサービスの作成者様にこの場を借りて御礼申し上げます。

1. 国コードとアドレスを対応させたCSVを作成します。

以下のようなCSVを作成します。

vi country_list.csv
ファイル内容
AC,アセンション島
AD,アンドラ
AE,アラブ首長国連邦
AF,アフガニスタン
AG,アンティグア・バーブーダ
AI,アンギラ
AL,アルバニア
etc...

作成に当たっての参照先:

https://memorva.jp/memo/website/domain_cctld_country_code.php

スクリプトを作成します。

vi ip_check.sh
スクリプト内容
#!/bin/sh

# error.logのディレクトリを指定する場合は指定して下さい
# error.logからIPアドレスだけを抜き出して同ディレクトリのip.YYYYMMDD.csvに保存します
cat ./error.log | awk 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) { print  substr($0, RSTART, RLENGTH) }' | sort > ip.`date +%Y%m%d`.csv

listfile="./ip.`date +%Y%m%d`.csv"
# ip.YYYYMMDD.csvファイルがない場合にエラーを返します
if [ ! -f $listfile ]; then
        echo "ファイル $listfile が存在しないので終了します。"
        exit 1
fi

country_list="./country_list.csv"
# 国コード,国の名前が書かれたcountry_list.csvがない場合にエラーを返します
if [ ! -f $country_list ]; then
        echo "ファイル $country_list が存在しないので終了します。"
        exit 1
fi

# IPアドレスに国名を付与したファイルを定義します。(ip_list.YYYYMMDD.csv)
result_file="./ip_list.`date +%Y%m%d`.csv"
cat /dev/null > $result_file

cat ${listfile} | while read line
do
                # IPアドレスを逆順に並び替えます。(例: 1.2.3.4 → 4.3.2.1
                ip_revers=`echo ${line}|awk -F'.' '{print $4,".",$3,".",$2,".",$1}'|sed -e 's/ //g'`
                # 並び替えたIPアドレスをcc.wariate.jpに並び替えて、国コードを抜き出します。(JP,CH,ESなど
                country_code=`nslookup -type=TXT ${ip_revers}.cc.wariate.jp | grep '"'|awk -F'"' '{print $2}' `
                # 国コードをcountry_list.csvから参照して国名を抜き出します。
                country_name=`cat ${country_list} | grep ${country_code} | cut -d"," -f 2`

                # 次の行は標準出力に返す処理を行います。cron処理する場合は#をつけて作動しないようにします。
                 echo "${line},${country_name}"
                # IPアドレス,国名の形式にして同ディレクトリのip_list.YYYYMMDD.csvに保存します
                echo "${line},${country_name}" >> $result_file
        sleep 1
done

exit

スクリプトに実行権限を付与します。

chmod +x ip_check.sh

動作確認

任意のディレクトリに以下のファイルがあることを確認します。

  • error.log (またはスクリプトにログのパスを記載)
  • ip_check.sh スクリプト
  • country_list.csv

スクリプト実行

./ip_check.sh

スクリプト実行結果

出力先(上記例ではスクリプトを配置したディレクトリ)に以下のファイルが出力されます。

  • ip.YYYYMMDD.csv (エラーログからIPアドレスのみを抜き出したファイル)
  • ip_list.YYYYMMDD.csv (以下の様に、IPアドレスとアクセス元の国を記述したファイル)
AAA.BBB.CCC.DDD,シンガポール
AAA.BBB.CCC.DDD,ベトナム
AAA.BBB.CCC.DDD,中国

次にやること

  1. このスクリプトの実行結果を元に件数ごとにまとめて並べ替えるスクリプトの作成
  2. cronによる定期実行化

絞りと背景。

今日は簡単な検証です。

発端は11月に撮影したこの、LAMYとfigmaライザを併せた絵をもう一度撮りたい、でした。

そこで適当にペンケースやら背景を並べていき、

撮影した1st takeがこちら。以前よりもペンやらをより強調したいのですがボケがやや強め。

そこで、カメラを絞り優先にして明かりも足して2nd take。

近づいてきたので、表情を変えての3rd takeです。

これによって、ペンもフィギュアも両方ともある程度ピントが合った状態で撮影できたという次第。

Nextcloudのリリース判定。

そもそも、このNextcloudを導入しようと思っていたきっかけは「Dropboxの代わりにならないか」でした。

なので、それを判定です。

スマートフォンの画像をアップロードできるか

→ 問題なし。出先からアップロード出来ないという問題がありますが、逆に無線Wi-Fiルータの帯域を消費せずに住みます。

表示速度などは大丈夫か

→ やはり問題なし。むしろローカル環境なので(インターネット回線に左右されないので)回線速度は良好。プレビューが少しもたつくかなぐらいですが誤差の範囲内です。

システムリソースに負荷がかからないか

→ アップロードした画像にタグ付けや顔認識をする「recognize」のせいで、ロードアベレージが常時10を超える事態が導入直後から1週間以上続きました。

ですが、その処理が無事に終わったあとは収束を見せています。

データの冗長化はどうなっているか

→ こちらも、lsyncによるデータのリアルタイム動機により解決。

結論

10年以上用いていたDropboxを解約するに至りました。(というよりも、並行期間中、Dropboxが使えないことに不便は感じていません)

あと、やることがあるとするならこのサーバ自体のスペックアップとデータストレージの増強ぐらいかなと。

Nextcloudが稼働している小型PC[Chuwi Herobox pro]

Page 1 of 4

Powered by WordPress & Theme by Anders Norén