投稿者: manualmaton Page 78 of 275

ChatGPTによるシェルスクリプト。(対話式のUFWブロック)

概要

不正アクセス対策として役立つUFW。これによる不審なIPアドレスの遮断をもっと効率的に行うようにしてみました。

このスクリプトを書い(てもらっ)た背景

攻撃者は複数のIPアドレスから同時に不正アクセスをしてくるパターンが多々あり、

ufw deny from xxx.yyy.1.1
ufw deny from aaa.bbb.0.2

とやるより、

ufw deny from xxx.yyy.1.0/24
ufw deny from aaa.bbb.0.0/16

と、ネットワークアドレスごと遮断した方が効率的だからです。

前提

  • 既にUFWが稼働していること。
  • サービス指定ではなく、あらゆるアクセスを拒絶するという合意が当事者で取れていること。

ChatGPTへの質問と回答

提示した要件

  1. IPアドレスを尋ねる
  2. IPアドレスそのままか、/24ごとブロックするか、/16ごとブロックするかを0~2で質問(空エンターは0)
  3. 実行前に内容を確認する。yなら続行、nなら中止
  4. 1~2に沿ってufw deny処理を行う
  5. 「ルールを付け加えました。他のIPブロックしますか?」の分岐を出す。yなら1に戻る。nなら次の処理
  6. ufw reloadを行う
  7. 現在のブロック状況を出しますか? yならufw status numberedを表示。nなら終了メッセージを出す

出てきたスクリプト

  • ufw_deny.sh
#!/bin/bash

# ユーザーからIPアドレスとブロック範囲を入力してもらい、
# UFWを使用して指定した範囲のIPアドレスをブロックするスクリプトです。

while true; do
    # IPアドレスを尋ねる
    read -p "ブロックしたいIPアドレスを入力してください: " ip_address

    # ブロック範囲を尋ねる
    read -p "IPアドレスをそのままブロックする場合は0、/24ごとにブロックする場合は1、/16ごとにブロックする場合は2を入力してください(空エンターは0): " block_option

    # 入力が空の場合はデフォルトで0(IPアドレスそのまま)とする
    block_option=${block_option:-0}

    # ブロック範囲を計算
    case $block_option in
        1) block_cidr="/24" ;;
        2) block_cidr="/16" ;;
        *) block_cidr="" ;;
    esac

    # ネットワークアドレスに変換
    if [[ -n "$block_cidr" ]]; then
        if [[ $block_option == "1" ]]; then
            # /24で区切る場合
            network_address=$(echo $ip_address | cut -d'.' -f1-3)
            cidr_notation="$network_address.0$block_cidr"
        elif [[ $block_option == "2" ]]; then
            # /16で区切る場合
            network_address=$(echo $ip_address | cut -d'.' -f1-2)
            cidr_notation="$network_address.0.0$block_cidr"
        fi
    else
        cidr_notation="$ip_address"
    fi

    # 設定内容を確認する
    echo "以下の内容でブロックを行います:"
    echo "IPアドレス: $cidr_notation"

    read -p "よろしいですか?(y/n): " confirm

    # ユーザーが処理を続行しない場合、スクリプトを終了する
    if [[ $confirm != "y" && $confirm != "Y" ]]; then
        echo "処理を中止しました。"
        exit 0
    fi

    # ブロックルールをufwに追加
    sudo ufw deny from "$cidr_notation"

    # エラーがあった場合はエラーメッセージを表示して終了
    if [[ $? -ne 0 ]]; then
        echo "ERROR: 不正なソースアドレス"
        exit 1
    fi

    echo "ルールを付け加えました。"

    # 他のIPをブロックするか尋ねる
    read -p "他のIPをブロックしますか?(y/n): " continue_blocking
    if [[ $continue_blocking != "y" && $continue_blocking != "Y" ]]; then
        break
    fi
done

# ufwを再読み込みする
sudo ufw reload

# ブロック状況を確認するか尋ねる
read -p "現在のブロック状況を確認しますか?(y/n): " check_status
if [[ $check_status == "y" || $check_status == "Y" ]]; then
    sudo ufw status numbered
fi

# 終了メッセージを出す
echo "IPブロックを終了しました。"

このスクリプトを

chmod +x ufw_deny.sh

とすれば作成は完了です。

スクリプトの動き

./ufw_deny.sh
ブロックしたいIPアドレスを入力してください:
# IPアドレスを入力します

IPアドレスをそのままブロックする場合は0、/24ごとにブロックする場合は1、/16ごとにブロックする場合は2を入力してください(空エンター
は0): 
# IPアドレスのレンジを
# IPアドレスそのまま:0
# /24(255.255.255.0)で区切る:1
# /16(255.255.0.0)で区切る:2

IPアドレス:
よろしいですか? (y/n):
# 先ほどのIPを表示します。ネットワークアドレスの場合は、/24 /16で区切って表示します。
# 内容を確認します。
# y を入力後、ufwの処理が走ります。一般ユーザーの場合はsudoパスワードが訊かれます。

ルールを追加しました
ルールを付け加えました。
# ufw deny from (入力したIP/NWアドレス)を実行します。

他のIPをブロックしますか?(y/n): 
# 続行するかを訊きます。yの場合はIPアドレスから始まります。

ファイアウォールを再読込しました
現在のブロック状況を確認しますか?(y/n):
# yの場合は sudo ufw status numberedを実行します。

と、

  • IPアドレス→ネットワークアドレスへの変換
  • UFW DENYに追加
  • UFWルールの読込
  • 設定後のルール表示

まで一元管理してくれます。

ボードゲーム『アグリコラ』ソロプレイを兼ねてのコンデジ検証。

こちらの7年前に購入したコンパクトデジカメ、ちょっとした記録にちょうどいいということで更に検証してみました。

そこで、室内で撮影機会の多いボードゲーム記録です。

『アグリコラ』ソロプレイ

『アグリコラ』プレイ開始

まずは、外観を撮影。特に設定をしなくても隅々まで写してくれる描写は記録にピッタリです。

プレイ後

アグリコラ自体の記録は以下の通り。割と堅実に得点を重ねられました。

得点合計

57

得点詳細

項目得点
54
33
94
野菜44
未開拓地00
家畜:羊84
家畜:猪74
家畜:牛53
柵内の厩22
木の部屋00
レンガの部屋00
石の部屋48
家族515
カード66
ボーナス00

プレイした後の盤面撮影

分割

この盤面撮影における分割機能はやっぱり便利。しかも、頭をフルに使った後でも特に気を遣わず、ダイヤル操作だけでこれが撮影できるのはありがたいです。

フィルター撮影

ミラーレス譲りのフィルター撮影もビルトイン。

総じて

  • テーブルをフルに使うゲームも外観を撮影できて
  • 分割により細かい状況を捉えることができて
  • ビルトインのフィルターも楽しい

と、ボードゲームの撮影時にも使えるカメラと判明です。

ボードゲーム『チューリングマシーン』開封とセットアップ。

前に入手していたのを、今のタイミングで開封です。

外観

『チューリングマシーン』外箱外観

中箱寄りの箱。パンチカードをテーマにしているということもあって、外箱に穴が空いているのが特徴です。

コンポーネント一覧

カードが多めでボール紙は少なめ
  • カード(判定カードと要件カード)
  • 検証機/パンチカードホルダー
  • パンチカード
  • ついたて
  • スコアシート
  • ホワイトボードマーカー

で、比較的シンプル目でした。

要件カードはユーロサイズ。判定カードはマーカーに書き込むという特性があるためにスリーブは入れにくいです。

収納

ある程度キチッと納められる内箱

収納についてはほぼいじるところがありませんでした。内側の仕切りで区切られているのが好印象です。

セットアップ

カードを同心円状に並べます

セットアップはお題に沿って行う必要があるため、やや大変。(特に判定カードは番号を並べていく必要があります)

ただ、ゲームシステムは比較的単純。

単純なのに論理力が問われる凄いゲームというのが第一印象。

ゲーム内容に関しては改めてレビューします。

百均グッズによる情報カードスタンド。

机の上での参照がしやすくなりました。

メタルスタンドとマグネット

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

使い方

単にマグネットで止めるだけです。

このマグネットはマーカーも兼ねていますので、ToDoの記録なんかにももってこい。

また、質量がそれなりにあるので散らばったり机から落ちるということもありません。

統率者&ボードゲーム(2023年10月)

4人で統率者&ボードゲーム会がありました。

統率者

  • グレムリンの神童、ジンバル
  • 工匠の主任、ウルザ
  • 高名な者、ミシュラ

それぞれ使いましたがいずれも敗北。相手の統率者ダメージで一撃死という敗北もありました。

最初に展開しすぎて一掃されたというヘイトコントロールも課題となりました。

ボードゲーム

サラダマスター

拮抗したゲームでした。後一手及ばず敗北です。

グラスロード

前から気になっていた中量級ゲームをインスト兼ねて回す機会に恵まれました。

  • リソース管理
  • カードのバッティング
  • バリアブルフェイズオーダー

が絶妙に組み合わさっていて、これは自分でも欲しいと思ったほどです。

タイガー&ドラゴン

最後の最後で「1」上がりによる勝利が決まったので満足です。

ここのところ、諸々煮詰まっていたので、とてもよい気分転換になりました。

WordPress改修。(プラグインの見直し)

自分のWordpressを見直すことにしました。

やったこと

  • JetPackからの脱却
  • よく読まれている記事セクションの追加
  • 自動TOC作成の改善
  • 問い合わせフォームの追加

JetPackからの脱却

強力な機能であることには間違いないのですが、以下の理由により脱却です。

  • X(Twitter)と連携されなくなった
    • 割と重めのウェイトです。2023年のゴタゴタで更新時に反映されなくなったので、使う理由がほぼなくなりました。
  • アクセス解析がうまくいっている
    • Web解析システムMatomoの導入により、JetPackの解析機能は代替できると判断です。

脱却の手順

先人の知恵に頼りました。

https://iyusuke.net/jetpack-goodbye/

  1. 脱JetPack
  2. SiteGuardプラグインによるセキュリティ強化

を同時に行いました。

よく読まれている記事セクションの追加

これは1ヶ月ほど前から導入。

こちらを入れました。

サイトの右ペインに、人気記事が自動的に表示されるようになりました。

自動TOC作成の改善

記事冒頭に作られる目次作成、前は別のプラグインを使っていたものの、Wordpress自体のバージョンと合わなくなったのかうまく機能しなくなりました。

そこで、こちらに差し替え。今のところうまくいっています。

問い合わせフォームの追加

先ほどの脱JetPackの記事にあったものをそのまま利用。各種設定を行いました。

改修によって

かなり動作が軽くなりました。「ちょっともっさりしているかな?」思っていたWordpressもまだまだチューニングできると思った次第です。

IPアドレスをネットワークアドレスにした上での洗い出し。

この記事の続きです。

シェルスクリプトによって、スペースで区切られただけの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に作成いただきました。

スクリプト内容

  • network-address-count.sh
#!/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アドレスをネットワークアドレスごとにカウントすることができました。

これは、今後の防御手段をしる手段として有効です。

買い足し、追加。(2023年プライムデーの収穫)

大きな買い物はありませんでしたが、気に入ったものを足していきました。

情報カード

  • メモ帳
  • ノート

の両者を融合したような使い勝手の情報カード。使い始めて3週間ほどではありましたけど、100枚のカードが底をついたという感じです。

なので、一気に5束買い足しました。今後、どのぐらい減っていくのかを確かめて適正在庫を見極めます。

茶こしつきマグボトル

このファーストインプレッションの結果は上々。

普段使いにも出先でも使えると判明したので、

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

  • 1本では足りないときがあった。
  • ローテーションするときにも便利
  • この手の商品はすぐに終売になるので在庫を抑えたい

の思惑があった次第。

Fail2banが弾いたIPアドレスの洗い出し。

はじめに

不審なアクセスを弾いているfail2ban。

sudo fail2ban-client status sshd

と実行することでBANしたIPのリストが出てきます。

ただ、それは

aaa.bbb.ccc.ddd AAA.BBB.CCC.DDD

のようにスペース区切りとなっていて読むのが大変。

そこで、IPアドレスを一覧表示して可読性を高めるようにします。

前提

環境

  • Ubuntu 20.0.4
  • fail2ban 0.11.1

sshdの設定

  • /etc/fail2ban/jail.local
(抜粋)
[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を必要に応じて

さっくりとした手順

  1. fail2banが弾いているIPをログファイルに出力するためのスクリプトを作成します。
  2. 出力したファイルのディレクトリを作成します。
  3. 動作を確認します。
  4. cronで自動実行されるようにします。
  5. 出力したログファイルをローテーションする設定を追加します。

スクリプト作成

※教義・信仰に沿ったエディタで作成してください。※

  • fail2ban-ssh-sort.sh
#!/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アドレスの出力がされていれば成功です。

cron自動実行

  • cron編集
sudo crontab -e -u root
  • 編集内容
0 3 * * * /path/to/directory/fail2ban-ssh-sort.sh
# スクリプトを格納したディレクトリを絶対パスで指定します
# この例では毎日午前3時に実行します

ログローテーション設定

※管理者権限で、教義・信仰に沿ったエディタで作成してください。※

  • /etc/logrotate.d/fail2ban-ssh-sort
/var/log/fail2ban-ips/sorted_ips.csv {
# スクリプトで指定したログ格納ディレクトリ/ログファイルを指定
    daily
    rotate 3
    compress
    missingok
    notifempty
}

ローテーション設定確認

sudo logrotate -d /etc/logrotate.d/fail2ban-ssh-sort

エラーがなければ成功です。

これで、加工しやすいCSVファイルで不審なログインのアクセス元を確認することが可能になりました。

ChatGPTによるRubyスクリプト(対話型のSSL証明書の有効期限確認)

概要

昨日の「SSL証明書の有効期限確認を確認するスクリプト」は、確認するURLをスクリプト内にべた書きしているため、利便性に欠けます。

そこで、もっと使いやすく改良してもらいました。

ChatGPTに実装してもらった内容

  • URLを対話型で入力する
  • 存在しないURLやアクセスできないサイト(ローカルNW内など)を入力した場合はタイムアウトする

の2点。

スクリプト内容

  • qa_ssl_checker.rb
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証明書の有効期限を確認することができるようになりました。

Page 78 of 275

Powered by WordPress & Theme by Anders Norén