机の上での参照がしやすくなりました。
メタルスタンドとマグネット

「何かに使えそうだ」と過去に購入していたアイアンメモスタンドが、本来の使われ方をすることになりました。
使い方

単にマグネットで止めるだけです。
このマグネットはマーカーも兼ねていますので、ToDoの記録なんかにももってこい。
また、質量がそれなりにあるので散らばったり机から落ちるということもありません。
机の上での参照がしやすくなりました。

「何かに使えそうだ」と過去に購入していたアイアンメモスタンドが、本来の使われ方をすることになりました。

単にマグネットで止めるだけです。
このマグネットはマーカーも兼ねていますので、ToDoの記録なんかにももってこい。
また、質量がそれなりにあるので散らばったり机から落ちるということもありません。
この記事の続きです。
シェルスクリプトによって、スペースで区切られただけのIPアドレスをリスト化することに成功したので、
192.168.1.2
192.168.1.3
172.28.1.3
172.28.1.5
...
といったIPアドレスのリストを
2, 192.168.1.0/24
2, 172.28.1.0/24
というように、/24で区切ったアドレス帯と件数を表示するスクリプトをchatGPTに作成いただきました。
#!/bin/bash
# ファイルのパスを引数として受け取る
file_path=$1
# ファイルが存在するかを確認する
if [ ! -f "$file_path" ]; then
echo "指定されたファイルが見つかりません。"
exit 1
fi
# ネットワークアドレスごとにIP数をカウントして表示
awk -F. '{print $1"."$2"."$3".0"}' $file_path | sort | uniq -c | while read count address; do
echo "$count, $address/24"
done
あとは実行権を付与します。
./network-address-count.sh /path/to/log/file
# 上述のリンク先でのログファイルを指定します。
2, 71.6.146.0/24
1, 71.6.158.0/24
1, 71.6.199.0/24
11, 71.6.232.0/24
のように、攻撃をしてきたIPアドレスをネットワークアドレスごとにカウントすることができました。
これは、今後の防御手段をしる手段として有効です。
大きな買い物はありませんでしたが、気に入ったものを足していきました。

の両者を融合したような使い勝手の情報カード。使い始めて3週間ほどではありましたけど、100枚のカードが底をついたという感じです。
なので、一気に5束買い足しました。今後、どのぐらい減っていくのかを確かめて適正在庫を見極めます。
このファーストインプレッションの結果は上々。
普段使いにも出先でも使えると判明したので、

もう一セット、買い足しました。


の思惑があった次第。
不審なアクセスを弾いているfail2ban。
sudo fail2ban-client status sshd
と実行することでBANしたIPのリストが出てきます。
ただ、それは
aaa.bbb.ccc.ddd AAA.BBB.CCC.DDD
のようにスペース区切りとなっていて読むのが大変。
そこで、IPアドレスを一覧表示して可読性を高めるようにします。
(抜粋)
[sshd]
enabled=true
filter=sshd
mode=normal
port=22
protocol=tcp
logpath=/var/log/auth.log
maxretry=3
bantime=-1
# ログインが3回失敗したIPアドレスを猶予期間無しに永久追放します
ignoreip = 127.0.0.0/8 ::1 #その他、除外IPを必要に応じて
enabled=true filter=sshd mode=normal port=22 protocol=tcp logpath=/var/log/auth.log maxretry=3 bantime=-1 # ログインが3回失敗したIPアドレスを猶予期間無しに永久追放します ignoreip = 127.0.0.0/8 ::1 #その他、除外IPを必要に応じて
※教義・信仰に沿ったエディタで作成してください。※
#!/bin/bash
# ログの格納場所を指定
log_directory="/path/to/log/directory"
# fail2ban-client status sshdを実行し、IPアドレスを取得
ip_addresses=$(fail2ban-client status sshd | awk 'BEGIN {RS="[ \\t]+"} {if ($1 ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $1}')
# IPアドレスを一行ずつ表示してソートし、csvファイルに出力
echo "$ip_addresses" | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 > "$log_directory/sorted_ips.csv"
chmod +x fail2ban-ssh-sort.sh
sudo mkdir /var/log/fail2ban-ips
# 上記のスクリプトで指定したディレクトリを指定します。
sudo bash fail2ban-ssh-sort.sh
cat /var/log/fail2ban-ips/sorted_ips.csv
# IPアドレスの出力がされていれば成功です。
sudo crontab -e -u root
0 3 * * * /path/to/directory/fail2ban-ssh-sort.sh
# スクリプトを格納したディレクトリを絶対パスで指定します
# この例では毎日午前3時に実行します
※管理者権限で、教義・信仰に沿ったエディタで作成してください。※
/var/log/fail2ban-ips/sorted_ips.csv {
# スクリプトで指定したログ格納ディレクトリ/ログファイルを指定
daily
rotate 3
compress
missingok
notifempty
}
sudo logrotate -d /etc/logrotate.d/fail2ban-ssh-sort
エラーがなければ成功です。
これで、加工しやすいCSVファイルで不審なログインのアクセス元を確認することが可能になりました。
昨日の「SSL証明書の有効期限確認を確認するスクリプト」は、確認するURLをスクリプト内にべた書きしているため、利便性に欠けます。
そこで、もっと使いやすく改良してもらいました。
の2点。
require 'openssl'
require 'socket'
require 'date'
require 'uri'
require 'timeout'
# ユーザーからURLを対話的に受け取る
def get_user_input
print "チェックしたいサイトのURLを入力してください(https://example.comのような形式): "
gets.chomp
end
# 変数で指定したURLに接続して証明書の有効期限を取得するメソッド
def get_certificate_expiry_date(url)
uri = URI.parse(url)
hostname = uri.host
ssl_socket = nil
tcp_client = nil
begin
# タイムアウトを5秒に設定してSSL接続を確立
Timeout.timeout(5) do
tcp_client = TCPSocket.new(hostname, 443)
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_client, ssl_context)
ssl_socket.hostname = hostname
ssl_socket.connect
# 証明書の有効期限を取得
cert = ssl_socket.peer_cert
expiration_date = DateTime.parse(cert.not_after.to_s)
days_remaining = (expiration_date - DateTime.now).to_i
return expiration_date, days_remaining
end
rescue Timeout::Error
return nil, "サーバーへの接続がタイムアウトしました。"
rescue => e
return nil, e.to_s
ensure
ssl_socket&.close
tcp_client&.close
end
end
# メイン処理
def main
url = get_user_input
expiration_date, days_remaining = get_certificate_expiry_date(url)
if expiration_date
formatted_date = expiration_date.strftime("%Y/%m/%d")
puts "サイト #{url} の有効期限は #{formatted_date} です。残り #{days_remaining} 日です。"
else
puts "証明書の取得に失敗しました: #{days_remaining}"
end
end
# メイン処理を呼び出し
main
bash qa_ssl_checker.rb
チェックしたいサイトのURLを入力してください(https://example.comのような形式): https://news.bbc.co.uk
サイト https://news.bbc.co.uk の有効期限は 2024/03/04 です。残り 139 日です。
これによって、ブラウザのマウス操作より確実にSSL証明書の有効期限を確認することができるようになりました。
2023年10月現在、自分のサイトの証明書はLet's Encryptのワイルドカード証明書を利用しています。
性質上、有効期限が90日のため「いつ頃が有効期限か」を確認するためのスクリプトをChatGPTに書いてもらいました。
require 'openssl'
require 'socket'
require 'date'
require 'uri' # URIモジュールを追加
# 変数で指定したURL
url = "https://hoge.example.com"
# 変数で指定したURLに接続して証明書の有効期限を取得するメソッド
def get_certificate_expiry_date(url)
uri = URI.parse(url)
hostname = uri.host
begin
# SSL接続を確立
tcp_client = TCPSocket.new(hostname, 443)
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_client, ssl_context)
ssl_socket.hostname = hostname
ssl_socket.connect
# 証明書の有効期限を取得
cert = ssl_socket.peer_cert
expiration_date = DateTime.parse(cert.not_after.to_s)
days_remaining = (expiration_date - DateTime.now).to_i
return expiration_date, days_remaining
rescue => e
return nil, e.to_s
ensure
ssl_socket&.close
tcp_client&.close
end
end
# メイン処理
def main(url)
expiration_date, days_remaining = get_certificate_expiry_date(url)
if expiration_date
formatted_date = expiration_date.strftime("%Y/%m/%d")
puts "サイト #{url} の有効期限は #{formatted_date} です。残り #{days_remaining} 日です。"
else
puts "証明書の取得に失敗しました: #{days_remaining}"
end
end
# メイン処理を呼び出し
main(url)
ruby ssl_checker.rb
サイト https://hoge.example.com の有効期限は 2024/01/12 です。残り 88 日です。
これはサーバ管理の度に確認したいので、motdに以下のスクリプトを管理者権限で配置します。
/etc/update-motd.d/99-custom-motd
#!/bin/bash
ruby /path/to/directory/ssl_cecker.rb
sudo chmod +x /etc/update-motd.d/99-custom-motd
任意のターミナルクライアントでSSH接続後、
サイト https://hoge.example.com の有効期限は 2024/01/12 です。残り 88 日です。
と表示されればうまくいっています。
第一印象は「サイズが多くて手に余る」思っていたB6サイズの情報カード(いわゆる京大式カード)。
その別の使い方をちょっと試します。
フィギュア撮影の際、ふとした弾みで「また撮りたい構図」が出て来ます。
それらをデジタルのフォトアルバムでお気に入り登録するのはしているものの、割と手に余ります。
また、構図は組み合わせて参考にしたいため、物理的に出力してアルバムに収納するのも出し入れが面倒です。
そこで、情報カードに貼り付けてみることにしました。

の特徴あり。

収納は、既存の情報カード収納ボックスにそのまま入れるだけ。インデックスもあるので分類は非常に簡単です。
一番の利点は
「他の情報カードと組み合わせられる」こと。
おかげで、メモとメモのつながりが見えるようになってきます。
検証の続き。
まで完了したので、Playbookを書いてみます。
単純に、Webサーバ(apache2)を再起動するためのymlを書きます。
---
- name: Restart Apache2 Service
hosts: clients
become: yes
tasks:
- name: Restart Apache2
service:
name: apache2
state: restarted
ansible-playbook WebRestart.yml
fatal: [IP]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"setup": {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "failed": true, "module_stderr": "Shared connection to IP closed.\r\n", "module_stdout": "sudo: パスワードが必要です\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1, "warnings": ["Platform linux on host IP is using the discovered Python interpreter at /us
ため、この結果となりました。
の2つはセキュリティ的によろしくありません。
は、暗号化→複合化の手間を伴います。そこで、単純に
ansible-playbook --ask-become-pass WebRestart.yml
とすることで、Playbook実行時にリモートホストのSudoパスワードを尋ねられるようになり、上記Playbookも正常に実行できました。
効率化を図るとはいえ、Playbook実行時に
ansible-playbook --ask-become-pass
とオプションをつけるのは面倒です。更に回避策を考えます。
alias ansible-playbook='ansible-playbook --ask-become-pass'
を作業前に実行。これで、
ansible-playbook
と実行するだけで
ansible-playbook --ask-become-pass
が得られます。この方法は一回限り有効な手段。サーバの設定を余り変えたくないときに有効な手段です。
echo "alias ansible-playbook='ansible-playbook --ask-become-pass'" | tee -a ~/.bashrc
source ~/.bashrc
Case1を永続的に付与する手法です。運用者での合意が取られているなら、メンテナンス的にも楽だと言うことでこの方法を採ります。
複数のサーバー管理を効率化するため、Ansibleサーバをインストールします。
今回は検証のため、単純構成。
の2台構成であり、両方とも同じネットワークに属しています。
また、OSは共にUbuntu20.04です。
本項では、「Ansibleのホストサーバ」の設定を行います。
sudo aptitude update
sudo aptitude install ansible
# 筆者はapitudeの方が好みです。必要に応じてaptを利用してください。
Ansibleホスト~クライアント間はSSHで通信を行うので、鍵のペアを作成します。また、ローカルネットワークのためパスワードは省きます。
ssh-keygen -t ecdsa -b 521
# 後続のプロンプトは全て空Enterにします。
ssh-copy-id [Ansibleホストのユーザ名]@[AnsibleクライアントのIPアドレス]
# Ansibleホストのユーザ名のパスワードを入力して鍵を登録します。
ssh [Ansibleホストのユーザ名]@[AnsibleクライアントのIPアドレス]
# SSHログインを確認します。
exit
# ログアウトします。
sudo cp -pi /etc/ansible/ansible.cfg /path/to/backup/directory/ansible.cfg.$(date +%Y%m%d)
# 任意のバックアップディレクトリを指定します。
diff -u /etc/ansible/ansible.cfg /path/to/backup/directory/ansible.cfg.$(date +%Y%m%d)
# 差分がないことでバックアップを確認します。
以下のファイルを、教義・信仰に沿ったエディタで編集します。
/etc/ansible/ansible.cfg
[defaults]
inventory = /etc/ansible/hosts
remote_user = your_username
private_key_file = /home/your_username/.ssh/id_ecdsa
# 上述した鍵ペアの「秘密鍵」の方を指定します。your_usernameはそれを作成したユーザ名です。
sudo cp -pi /etc/ansible/hosts /path/to/backup/directory/ansible_host.$(date +%Y%m%d)
# 任意のバックアップディレクトリを指定します。
diff -u /etc/ansible/hosts /path/to/backup/directory/ansible_host.$(date +%Y%m%d)
# 差分がないことでバックアップを確認します。
以下のファイルを、教義・信仰に沿ったエディタで編集します。
/etc/ansible/hosts
[clients]
[クライアントのIPアドレス] ansible_ssh_user=[ホストのユーザ名]
以下のコマンドを実行します。
ansible clients -m ping
次の結果が返ってくれば成功です。
(クライアントのIP) | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
※以下のようなメッセージは今のところ無視して大丈夫です。
discovered Python interpreter at /usr/bin/python3, but future
installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
これで、Ansibleサーバの簡単な検証が行えました。
クライアント側の設定やplaybookの作成は今後、実施していきます。
足繁く通っていた頃よりも増えた習慣/趣味。それらが今回のサイクリングでどのように作用したかを軽く触れてみます。
など、様々なアナログツールで書く習慣が大いに役立ちました。これによって、細かな気づきや思ったことを即座に書いて、その場は忘れることができました。
その後、こうして思い起こすことができるようになったのです。
特に、情報カードはマスターピースと言うべきもの。
と、当初は「こんなに大きいのか」と不安だったのですが、そこはやはり先人の知恵でした。
予想通りというか、予想以上の活躍でした。
をつぶさに記録。「この道をどのぐらいの速度で走ることができた」は特に収穫。もう一度その道を走るときの参考になります。
逆に、足かせとなりました。理由は単純。ある程度の平滑部を走る都内と異なり、アップダウンとあれた道がある所でカメラを持ち運ぶだけでも大変です。
衝撃に備えてカメラバッグに入れていましたが、そうなると水筒や食料のスペースを阻害します。
また、体を使った後、「カメラを構えて集中して撮影する」ための集中力を使い切るパターンがあったので、これは再考の余地ありです。
というよりも、もっと気軽に撮れてある程度の撮影が担保されるコンパクトデジカメでいいのではと本気で検討しました。
サイクリングの途上の栄養補給的なものだったので、レストランには立ち寄らず。

道の駅で惣菜パンを戴きました。
これが疲れた体に染み渡る味。折しも秋風が心地よく、絶好のロケーションで食べることができたわけで。
ってところです。
Powered by WordPress & Theme by Anders Norén