サーバー設定作業メモ

何をやったか忘れないように、メモメモ記事を残すことにした。これも投稿数稼ぎかなw

ポータルサイト http://www.marochanet.org/ の djangoアップデート作業

ウェブユーザでpython仮想環境に入り、まずはpipのアップデート

(venv0) xxx@jagha:~/html/python$ python -m pip install --upgrade pip

次に仮想環境のアップデート可能なモジュールリストをとる(一部表示)

(venv0) xxx@jagha:~/html/python$ pip list -
Package                Version Latest Type
---------------------- ------- ------ -----
……
Django                 3.0.8   3.2.4  wheel
django-bootstrap4      2.2.0   3.0.1  wheel
django-hitcount        1.3.2   1.3.3  wheel
django-tinymce         3.0.2   3.3.0  wheel
……

他にもリストアップされたモジュールを全てアップデートする

(venv0) xxx@jagha:~/html/python$ pip install -U (module name)

ここで、リストには無いがデータベースエンジンとの接続に必要なmysqlclientのアップデートに失敗。

これに関してはpython側のライブラリが不足していたため下記コマンドをrootで打って、ライブラリをインストールする

apt-get install python3-dev libmysqlclient-dev

無事mysqlclientのアップデートに成功して終了。

メールボックス整理ツール

本サーバーでは個人の興味や勉強を兼ねてメールサーバーを運用している。昔はプロバイダメールはPOPで端末に落としてくるのが主流で、例えば家と職場、携帯電話で同じ受信メールを処理することが難しかったし、Exchangeを始めIMAPも使われ始めたが、サーバー負荷が高いため普通のプロバイダでは利用できない場合が殆どだった。今ならフリーのアカウントなどWEBメールを初めとして受信メールをサーバーを置くタイプが多くなってきた。

私が使用しているプロバイダメールも今はWEBメール対応でサーバーにメール本体を置くことが出来るが、やはりPOPがデフォルトのようだ。そこで、まだPOPしか使えない頃から、外部にサーバーを立ち上げて(一昔流行ったおうちサーバーや、現在の当方のような「さくらVPS」)プロバイダからのメール自動転送(昔はPOP)を受けてIMAPサービスを行っている。

サーバーの引越においてもメールデータの移行も必要であった。引越ついでにサーバー上のユーザーのメールボックス形式をmboxからIMAPとの親和性の高いMaildir形式に移行する。二つの形式には大きな違いがあり、

  • mboxのメールボックスは巨大な1ファイル、Maildirはメール1通1ファイル
  • mboxのメールボックスフォルダ階層はファイルシステムに準ずる、Maildirはフォルダの階層はピリオドで接続した構造で表現され、ファイルシステム的には一階層である
  • mboxの受信トレイは/var/spool階層のユーザー名ファイル、Maildirは各ユーザーディレクトリのMaildir直下に配信される
  • どちらも漢字フォルダ名はutf-7で、端末では普通読めない。

そのあたりの作業を簡単に行えるような行き当りばったりツールをまたpythonで作成した。pythonのmailboxライブラリを使用するとmbox形式やMaildir形式のメールボックスを操作することが出来、相互に移動したりフォルダに振り分けたり出来る。というライブラリお任せで作成したツール「mailboxutil」についてまた追々と解説・覚書きを投稿したいと思う。

このツールをつかってメールボックス移行を行ったのは実際には前のサーバーで約1年前CentOS6からCentOS8にOS変更した時でした。まぁ、話がややこしくなるので、今回やったことにさせてくださいw
ていうか、このタイミングでCentOSサポート終了のお知らせは正直凹みました。。。時間を返せーー!と。
(CentOS同士でもメジャーバージョンを一個飛ばしということもありアップグレードインストールは諦めて、バックアップ→新規インストール→データリストアをやっていたのでした。。。)

gzipモジュール組込み

主にSMTPへの不正アクセスを監視してファイヤーウォールにブラックリストを追加するpythonプログラム(blockset.py)はサーバー引越前より使用していたが、それまでに集計した不正アクセスIPアドレスリストは引越後も使用して対応していた。

リスト自体は5年くらい前からのものでかなり膨らんで来たしもう既に状況は変わっているかも知れないため、サーバーIPアドレスも変わったという機会もあり最初から収集を始めることとし、一度ブロックリストを空にしてみた。2~3日は特におかしなアクセスは無く油断していたら、夕べ辺りに大量にSMTPへログインアタックがいらっしゃいましたので下記に晒します。

root@jagha:~# blockset.py -u
use defaule.
New record : 31.210.20.7 (13)
New record : 31.210.20.18 (10)
New record : 31.210.20.23 (11)
New record : 31.210.20.39 (15)
New record : 31.210.20.41 (6)
New record : 31.210.20.54 (7)
New record : 31.210.20.93 (7)
New record : 31.210.20.109 (9)
New record : 31.210.20.111 (14)
New record : 31.210.20.155 (13)
New record : 31.210.20.162 (15)
New record : 31.210.20.173 (11)
New record : 31.210.21.3 (6)
New record : 31.210.21.4 (6)
New record : 31.210.21.9 (6)
New record : 31.210.21.76 (5)
New record : 31.210.21.82 (13)
New record : 31.210.21.96 (12)
New record : 31.210.21.195 (15)
New record : 31.210.21.220 (15)
New record : 31.210.21.235 (6)
New record : 31.210.21.242 (7)
New record : 31.210.21.243 (12)
New record : 45.133.1.22 (15)
New record : 45.133.1.50 (11)
New record : 45.133.1.58 (7)
New record : 45.133.1.73 (13)
New record : 45.133.1.100 (13)
New record : 45.133.1.102 (14)
New record : 45.133.1.109 (14)
New record : 45.133.1.127 (11)
New record : 45.133.1.138 (8)
New record : 45.133.1.192 (15)
New record : 45.133.1.203 (8)
New record : 45.133.1.204 (8)
New record : 45.133.1.206 (13)
New record : 45.133.1.214 (15)
New record : 45.133.1.218 (15)
New record : 45.133.1.239 (15)
New record : 45.133.1.241 (12)
New record : 45.133.1.242 (12)
New record : 45.133.1.247 (8)
New record : 45.144.225.54 (15)
New record : 45.144.225.95 (13)
New record : 45.144.225.204 (9)
New record : 45.144.225.205 (7)
New record : 45.144.225.206 (7)
New record : 136.144.41.70 (7)
New record : 136.144.41.87 (12)
New record : 136.144.41.132 (6)
New record : 136.144.41.162 (8)
New record : 136.144.41.166 (8)
New record : 136.144.41.181 (15)
New record : 136.144.41.209 (8)
New record : 195.133.40.31 (8)
New record : 195.133.40.34 (15)
New record : 195.133.40.41 (7)
New record : 195.133.40.63 (7)
New record : 203.159.80.60 (12)
New record : 203.159.80.61 (15)
New record : 203.159.80.77 (6)
New record : 203.159.80.190 (12)
update ufw before.rules
Firewall reloaded

こちらをネットマスク24ビットでくるめると、意外に同じノードからのご来店が多く、

31.210.20.0/24  <=  31.210.20.0
31.210.21.0/24  <=  31.210.21.0
45.133.1.0/24  <=  45.133.1.0
45.144.225.0/24  <=  45.144.225.0
136.144.41.0/24  <=  136.144.41.0
195.133.40.0/24  <=  195.133.40.0
203.159.80.0/24  <=  203.159.80.0

これだけになったので、この辺りの方々が迷惑なドメインということで一括ブラックリストとした

あと、もう一点、先日のlessコマンドにならってgzip圧縮されたログファイルも普通に解析できるように仕様追加した。cron起動されるlogrotateでまだ解析していないログファイルが圧縮アーカイブされてしまう可能性がある。

pythonのgzipモジュールを使用すると通常ファイルと同じように普通に読み書き出来るファイルハンドルが生成される。with構文を使用してファイル操作を行っている部分を下記にように変更した。

import gzip
import re

・・・・
    with open(args.logfile, 'r', encoding='utf-8') if not re.search('\.gz$', args.logfile) else gzip.open(args.logfile, 'rt') as fh:
        for line in fh:
            ・・・・

with構文の中でインライン条件分岐を行い、末尾が’gz’だった場合はgzipでオープンするという内容。

この方法、他の用途のファイル読み込みでも応用が考えられる。もう一つ分岐を増やして、ファイル名が空白であった場合は標準入力(sys.stdin)とするなども出来そうだ。

lessコマンドの覚え書き

CentOSからUbuntuにサーバー引越して、いろいろ違いがあった場合その都度対策している。今回は特に困っているわけでは無いが、コマンドラインツールのlessについて、lessはテキストファイルの内容をページ送りで閲覧することが出来るビュアーで間違って編集してしまわない安心感とお手軽さで昔から常用しているツールだ。

大昔は無かったと思うが、CentOSで運用しているとき。ファイル名の代わりに間違ってディレクトリ名を渡してしまった時。エラーでなく、そのディレクトリのファイル名一覧(ls -la の結果)が表示されるようになっていた。これが以外に便利で、ファイルがメチャメチャ入っているディレクトリとかザーッと眺めるのに丁度良い機能だった。

とは言ってもそんなに使う事もないので、忘れたまま先日のサーバー引越&OS変更(CentOS→Ubuntu)を行なった後に、lessを使うとディレクトリ一覧機能が無くなっていた。CentOSのマシンもまだ生きているので改めて試してみるとこちらは引数にディレクトリを与えることで、ファイルの一覧が出来ていた。ディストリビューションごとの機能の違いなようだがlessなんていうレガシーがツールに今更機能の差があるのは考えにくいので、設定関係で調査してみた。

どうやら、lessには前処理を行なうlesspipe(.sh)というシェルスクリプトがあり、ここで圧縮ファイルの展開などを行なっていたようだ。

/usr/bin/lesspipe(.sh)

CentOSとUbuntuでこれらのファイルを比較したところ、CentOSの方には下記のような引数がディレクトリだった場合の処理が入っている。

if [ -d "$1" ] ; then
        ls -alF -- "$1"
        exit $?
fi

これをUbuntuの方にも記載することで、無事ディレクトリリストを閲覧することが出来るようになった。

/usr/bin/lesspipeを直接編集してしまったので、今後アップデートで元に戻ってしまった時のことを考えての覚え書き・・・・とφ(`д´)メモメモ…

SVGファイルの件

スケーラブルベクターグラフィックス形式といって中身はjavascriptの画像形式で、テキストの入ったような資料を貼付けるのに適していると思う。ブログへの貼付けも通常の画像と同様に貼り付けが可能で、図形拡大による劣化がないのが有難い。今後当サイトでも色々使えそうなので調査してみた。

テキストファイルなのでその気があればテキストエディタで作成・編集が可能だが、基本的にはInkscapeの様な画像ソフトで作成する。Inkscapeの使い方を一からおぼえるのも大変なので、他に手段を考えてみる。Inkscapeでは様々なベクタフォーマットをインポート出来るので、慣れたソフトで作成して変換するのもアリでしょう。

使えそうなフォーマットは*.emf(拡張メタファイル)。これはOffice系からも吐き出せるので便利そう。あとフリーの回路図エディタ水魚堂のBschも*.emfファイルを書き出せるので、回路図を貼付けるの良いかもしれない。ということで早速Bsch付属のサンプル回路図を*.emf出力→InkscapeでSVGに変換してみた。

水魚堂Bschのサンプル回路図

良い感じ。

あと*.wmf(ウィンドウズメタファイル)も対応しているため、簡単な図ならOffice系のDrawで作成して、インポートすれば楽勝じゃん!と思ってPowerPointdeサンプル作って実験してみたところ、インポート時にInkscapeが落ちてしまった。。。

何度やってもダメなため、ネットで調べたが同様の症状は見当たらず、まぁWMF使う人は少ないのかなとでも思っておくことにした。

Officeインポート作戦はあきらめて別の方法を調べていたら、なんと!PowerPointから直接SVGファイルが作成出来るじゃないかー。Office系Drawはある程度使い慣れているので、この方が良いかもしれないが、PowerPointはプレゼンソフトなのでキャンバスサイズがスライドサイズとなり、簡単な図形をそのまま保存すると余白が気になることになる。その場合は保存したい図形を選択した状態でシフトを押しながら右クリックすると「図として保存」という項目があり、そこで出力形式をSVGにすると良い。

作成環境:PowerPoint (Office365) 2021/06/11現在

ちなみに、WordpressでSVGファイルを貼付けられるが、メディアファイルにリンクを設定しても画像ポップアップは出来ないようなので、リンクは無しで貼り付けとする

SVGはソースファイルっぽいので右クリックで保存されないようした方が良さそうだけど、、なんとなく。いや、へんな著作権を主張するんじゃなくて、訪問者の安全性を考えて。。一応javascriptみたいなモンだからねー。

ブロックリスト自動生成(番外)

前回のPythonプログラムの補足説明というか、WEBページで図を使って説明するための練習の様な投稿になります。WEBで表示出来るオブジェクトとしては通常段落と画像が主なものになりますが、画像はビットマップ形式が多く説明用の図には向かないかなと思っていたが、よくよく調べるとHTML5からベクタ図形の表示が出来るようになってるんですね。ほうほう。

ということで、SVGについて少し勉強してみることにした。中身はjavascriptのようで、WEBに貼付けるときは普通に画像扱いで良いとか。作成用のツールはInkscapeというフリーソフトがあるので早速インストールして使用してみた。

illustratorとかと同じように使えそうなスグレモノだけど、あいにく自分はillustrator系は使い慣れていないので、一から勉強するよりは、既存のドローソフトで簡単に描いたものをSVGに変換して貰うだけでも便利そうだ。

簡単なものならWMF(ウィンドウズメタファイル)、EMF(拡張メタファイル)も読み込めるのでBschとかで描いた回路図も変換出来そう。

ということで前回のPythonネタの続き

msks = list(map(lambda n: int('1'*n+'0'*(8-n), 2), [8 if (mask - i*8) >= 8 else (mask - i*8) if (mask - i*8) > 0 else 0 for i in range(4)]))

これは、整数値のネットマスク幅を、IPアドレスリストと同じ形式のマスクビット配列に変換する1文となる。(例えば23 → 11111111.11111111.11111110.00000000

[8 if (mask - i*8) >= 8 else (mask - i*8) if (mask - i*8) > 0 else 0 for i in range(4)]

これが1から32までの数字mskに対して、8ビットずつ4分割し、足りない分は余りと、ゼロとする構文。mskを8で割って、配列の上から「商」の数だけ8として、次に「余り」残りをゼロとする。

map(lambda n: int('1'*n+'0'*(8-n), 2), LIST)

上記配列の要素に対し上位を1で埋めたビット表記に変換して、2進数で数値化

例)7 → 11111110 → 0xFE

これを図で説明すると下図の様になる

なんか余計に分かりにくくなったような。まぁ今回は自分で思い出せれば良いか~くらいのつもりでまとめておきます。今後のツール活用に期待で。

Youtube貼付けに謎の空白が!

別にYoutuberになるわけではないが、Yutubeチャンネルを開設このブログサイトの右上の動画アイコンリンクも自分のチャンネルに変更。

開設理由はたいしたことではなく、過去に投稿した動画ページについて、容量が余裕だったので、自サイトのメディアライブラリにアップして配信を行ってみたが、たった一人しか見ていないのに関わらず転送が間に合わず動画がカクカクになる問題となっていた。やっぱりセオリー通りというか一旦Youtubeなど動画配信専門サイトにアップしてリンクした方が良いという結論になった。そこでの開設と相成ったという感じ。

チャンネル自体は昔から作ってあったけど、身内専用限定公開の為のものだったが、折角なので今回から特に差し障りがない限り公開で行くことにした。

YouTubeにアップした後、自サイトに貼付けること自体は容易な作業で、Wprdpressブロックエディタ(Gutenberg)のブロック挿入コマンドで動画、もしくはYoutubeアイコンを選択し、URL貼り付けとしてYoutubeからの共有URLを貼付けるだけ。編集画面で上手く行っていたので、実際にプレビューしてみたところここで問題発生。

なんだこの空白は!って感じで動画フレームと直前の段落の間に謎の空白が出来てしまっている。

ブラウザの開発者ツールでHTMLのソースを見てみたら特に空白が設定されているわけでもなく、何らかのスタイルシートの影響だろうということまでは想像できた。

ネットで情報収集すると「Wordpress Youtube 空白」で色々出てきて、皆さん苦労しているのが伺える。皆さん各自で対策しているようなので(症状、原因もマチマチな感じ)こちらも独自調査で行くこととする。

埋め込んだブロックをHTML編集することとし、部分的にソース表示すると埋込み用のfigureタグの中にもう一つdivでスタイル指定をしている。

  • <div class=”wp-block-embed wrapper”>

こいつが悪さしているのでは、と、class指定文を削除。Gtenbergは「なんか変だぞ?」とエラーを出してくるが無視してHTMLとして保存。

以上の作業で編集状態では動画のプレビューが出来なくなるが、このままプレビューを行った所、無事、謎の空白が削除されていることが確認できた。

スタイル指定文を削除することで弊害が出るかどうか手持ちの機器でアクセスして確認したところ、特にこれと言って問題は無さそうなので、当サイトではこの方法で貼付けることとした。

当サイトの確認条件

  • WordPress 5.7.2
  • 使用テーマ:Catch Base
続きを読む…

WordPress環境ごたごた

内容はともかく、最近日課としてブログを書くようにしているが、記事が貯まってくると、レイアウトとかいじりたくなり、何となくカスタマイズもしたくなり、と、色々設定をいじっていたら元のレイアウトに戻すことが出来なくなってしまった。具体的には

こんななってしまった

  • 使用していたテーマはCatch Responsiveで、トップページは最新の投稿から順に全文表示していたのだが、数行のダイジェスト表示のリストになってしまった。最近の流行のレイアウトなのだろうか、トップページに固定ページを置き、その下の最新記事をダイジェストする様な形でした。一応テーマ設定で全文表示変更出来るのだが、更新すると元に戻ってしまう。
  • トップページのスライダ画像も設定が消えて、デモ画像になってしまったので、再設定してみたが、これも更新すると元に戻ってしまう。

そこでやったことは、

  • テーマの再インストール ー 効果無し
  • サーバー引越前のバックアップデータがあったので、データベース以外のファイル群をリストアした
    ー テーマ設定情報がデータベース側にあるのか効果はなかった。
  • あきらめて似たようなテーマを探してインストール
    ー 他のテーマであれば設定が反映され正常動作することは確認できた。

結局、元のテーマの不具合の理由は分からないまま、昔の設定のまま長く使っていたのと、サーバーの引越でデータベースの内容がおかしくなったのだろうと結論づけて、似たようなテーマに変更することとした。

選定したテーマはCatch Base(フリー版)で同じ所のもののようで、設定項目も似たような感じでした。違いはデフォルトでは3カラムで両脇サイドバーのレイアウトだったくらいで、トップのスライド画像も前回同様のものを設定可能であった。一応またテーマを変えてしまうかも知れないので、現在のSSを貼付けておきます。

まぁ、ほぼほぼ前回と同じレイアウトに戻せてメデタシメデタシであったが、一つだけ気になる点があった。

続きを読む…

ブロックリスト自動生成その3(素人のサーバー管理)

自動生成プログラムの機能はオプション‘-h’を付けると確認することが出来る。この辺は普通のコマンドラインプログラムっぽく作ってみました。

root@xxx:~# blockset.py -h
usage: blockset.py [-h] [-n] [-f] [-d] [-u] [-o MASK,COUNT] [-c COUNT] [-a ADDRESS] [logfile]

blockset.py collection of unauthorized access list and restart firewall(ufw)

positional arguments:
  logfile               input log file default:/var/log/mail.log

optional arguments:
  -h, --help            show this help message and exit
  -n, --none            Check only mode.
  -f, --force           bloclist force update, unless new record.
  -d, --debug           debug print mode
  -u, --update          blocklist update and restart firewall(ufw)
  -o MASK,COUNT, --orderck MASK,COUNT
                        ipset order ckeck
  -c COUNT, --count COUNT
                        abuse count
  -a ADDRESS, --address ADDRESS
                        individually address entry to blacklist
root@xxx:~#

  • -h(–help)
    ヘルプの表示、引数やコマンドラインオプション説明
  • -n(–none)
    ログファイルの検査のみで何もしない
  • -f(–foce)
    ログの検査で不正アクセスが無かった場合でも、ファイヤーウォール設定ファイルへのブロックリスト追加を続行する(ネットマスクによるリスト整理時に使用する)
  • -u(–upadte)
    ファイヤーウォール設定ファイルの更新とプロセスリスタートを行う
  • -o MASK,COUNT (–oderck MASK,COUNT)
    ブロックリストを再検査し、指定したマスクビットにてグループ化して、一定数以上のものをリストアップする。-fオプションで該当アドレスをマスクビットでまとめてファイヤーウォール設定ファイルを更新する、ファイヤーウォールの再起動には-uオプションを併用する
  • -c N(–count N)
    検査対象ログにて不正アクセスがN回以上あった場合にリストアップする
  • -a ADDRESS(–address ADDRESS)
    IPアドレスを直接指定して登録する、ログ検査と併用する仕様上、便宜的に100回不正アクセスがあったことにしている
続きを読む…

ブロックリスト自動生成その2(素人のサーバー管理)

手動起動によるメンテナンス機能をまとめると(順不同)

  1. 指定した(規定の)ログファイルを検索して不正アクセスのパターンにマッチしたIPアドレスを収集する
  2. 規定回数(例:5回)以上の不正アクセスが確認できたIPアドレスをリスト化
  3. 現行ブロックリスト(ufwの場合:/etc/ufw/before.rules)より現行のブロックリストを読み出し、新しく検出したIPアドレスリストを重複しないようにマージ(基本的には重複しないはず)
  4. オプション機能としてブロックリストの整理ーアクセスの多いIPアドレスのノードを指定幅ネットマスクでまとめる
  5. 新しいブロックリストを更新し、ファイヤーウォールを再起動 ー オプション:基本的には確認のみ

ipv4adrsetクラス

1のIPアドレスのパターンマッチは普通に正規表現と比較だけですむが、ブロックリストにはネットマスクでグループ化した形式(xxx.yyy.zzz.0/24)などに指定アドレスが含まれるかどうかの判定も必要になる。おそらく便利なライブラリがあるとは思うが、ここは勉強を兼ねてクラスを作成した

class ipv4adrset:
    def __init__(self):
        self.ips = []
        self.msk = 32
    def __init__(self, line = None):
        self.set_line(line)

    def set_line(self, line):
        if line is None:
            self.ips = []
            self.msk = 32
        else:
            res = re.match('^([0-9\.]+)\/([0-9]+)$', line)
            (ip, msk0) = (res.group(1), res.group(2)) if res else (line, 32)
            self.ips = list(map(lambda n: int(n), ip.split('.')))
            self.msk = int(msk0)

    def set_mask(self, mask):
        if self.msk < mask:
            return self
        msks = list(map(lambda n: int('1'*n+'0'*(8-n), 2), [8 if (mask - i*8) >= 8 else (mask - i*8) if (mask - i*8) > 0 else 0 for i in range(4)]))
        rip = list(np.array(self.ips) & np.array(msks))
        ret = ipv4adrset()
        ret.ips = rip
        ret.msk = mask
        return ret

    def __eq__(self, other):
        smsks = list(map(lambda n: int('1'*n+'0'*(8-n), 2), [ 8 if (self.msk - i*8) >= 8 else (self.msk - i*8) if (self.msk - i*8) > 0 else 0 for i in range(4)]))
        omsks = list(map(lambda n: int('1'*n+'0'*(8-n), 2), [ 8 if (other.msk - i*8) >= 8 else (other.msk - i*8) if (other.msk - i*8) > 0 else 0 for i in range(4)]))
        sip = list(np.array(self.ips) & np.array(smsks) & np.array(omsks))
        oip = list(np.array(other.ips) & np.array(smsks) & np.array(omsks))
        return sip == oip

    def __str__(self):
        return '.'.join(map(lambda i: str(i), self.ips)) + ('/' + str(self.msk) if self.msk < 32 else '')

  • メンバ変数self.ipsは4要素整数の配列でアドレスを示しており、self.mskはネットマスクピット数でデフォルトは全マスクで32
  • メゾッドset_lineはIPアドレスのマスク有り無しの文字列を読み込みオブジェクトの値をセットする
  • メゾッドset_maskはマスクピット幅をセットする。マスク外のビットはゼロにする
  • メゾッド__eq__は比較関数だが、ネットマスク幅の短い方で比較する。指定したアドレスがあるネットマスクに含まれるかどうかを判別出来る
  • メゾッド__str__は文字列変換関数

改めて見てみるとリスト内包表記で無理に一行で書こうとしている感じで可読性が非常に悪いですね。。。

とくに1文メチャクチャ長いリスト内包表記があるので、覚書きついでに解説

続きを読む…