2020年7月アーカイブ

タイトルだけ見たら、なんのこっちゃ?という感じかもですが、

こんな感じのWebページを作りたいってことです・・・・あれ?やっぱり分からない。(を

つまり、BOOTHなんかで同人誌の電子ファイルを買うわけですよ。すると、同人誌のデータがPDFで手に入ります。当然ファイルサーバとか NAS とかに保存するんですが、何冊も買ってるとどんどんファイルが増えていく。だけど、PDF って Windows Exproler とかで表紙一覧ができない。ファイル名だけズラズラ並んでても、「ん?これ、どんなんだっけ??」ってなるわけです。困りますね。

なんで、Web 使ってサムネイル化できないか?というのが要求なわけです。

サムネイルつきのリスト画面って、何が面倒かちうと、コンテンツ(この場合はPDF ファイル)と、その表紙になる JPEG が両方必要になって、ファイルの管理がごちゃっとしちゃうのが嫌なんですね。

じゃあ、どーするか?サムネイルはデータベースに突っ込んじゃえば?なんなら、コンテンツそのものもデータベースに突っ込んじゃえば??というお話です。

なお、貼り付けたイメージは、BOOTHでエフ屋さんという同人サークルさんの作品です。気になる方はどうぞ


データをDBに入力する

さて本題、まずデータをデータベースに取り込まないと話にならんので、取り込みます。

取り込むべきサムネイル画像を作りましょう。

# convert Futanari_Elf_chan__sub_quest__DL__Lsize.pdf\[0\] -resize 600x600 ./title.jpg

ImageMagick で PDF の最初のページ、つまり表紙を JPEG 化します。

本当は JPEG ファイルを生成せず、そのままデータベースに送り込みたいんですが、どーも ImageMagick は STDOUT に処理結果を出したりできないっぽく、しょうがないのでファイルにしてます。

んで、生成したファイルをデータベースに送り込みます。

#! /usr/local/bin/python3.7
# -*- coding:utf-8 -*-

import io
import os
import sys
import subprocess
import psycopg2

args = sys.argv

filename = os.path.basename(args[1])
titlepage = open('title.jpg' , 'rb').read()

conn = psycopg2.connect("dbname=book host=******** user=pgsql")
cur = conn.cursor()
sql = "INSERT INTO book (title_page , filename) values (%s , %s)"
btitlepage = psycopg2.Binary(titlepage)
cur.execute(sql , (btitlepage , filename))
conn.commit()
cur.close()
conn.close()

Python のスクリプトです。本当は psql コマンドで INSERT したいんですが、psql コマンドで bytea データを INSERTしようと思ったら、PostgreSQL のデータディレクトリに対象ファイル置いておかないと駄目とか、なんだかなぁな仕様があるようで、仕方ないからこんな Python スクリプトを使ってます。


CGIでデータを取り出す

んでまって、データベースに格納した bytea データを JPEG として取り出す CGI。これがこの記事の本体だったりします。

いやね、そんなん、大したことないやろ?ちょっと調べたら出てくるやろ?って思うやん?

出てこないのよ、これが。Python 2 を使った記事は見つかるけど、Python 3 の実装例がまるでみつからん。ちうわけで、この記事です。

#! /usr/local/bin/python3.7
# -*- coding:utf-8 -*-

import cgi
import io
import sys
import psycopg2

args = sys.argv

conn = psycopg2.connect("dbname=book host=******* user=pgsql")
cur = conn.cursor()

print("Content-Type: image/jpeg")
print()

form = cgi.FieldStorage()
id = form["id"].value

cur.execute("SELECT title_page FROM book WHERE id = (%s)" , (id))
res = cur.fetchone()

sys.stdout.flush()
sys.stdout.buffer.write(res[0])

以上、実装例でした。

いや、これだけじゃ分からんですよね。

ポイントは、sys.stdout を使うというところです。ちうか、それだけです。

Python2 を使った実装だと、SQL から取り出した res[0] を print するだけでいいらしいのですが、Python3 はそれでは動きません。Python 2 と 3 の大きな違いはデータ型が厳密になったことで、バイナリを print できないようになったということなんでしょう。

意図的にバイナリデータを、標準出力に送りだす。という実装をしないといけない。っていうことでした。

Graylog なるツールがあります。ログ解析を唄うツールです。ログ解析ができます!

っていうと、なーんも考えずにインストールすればできるぜ、いえーい!って思っちゃうでしょうけど、そんな甘いものではありません。

というか世の中に統合ログ解析ツールを唄うツールが結構ありますが、どれもお気楽なものがないんですよね。結局はログメッセージを人間が見て、どうやって分割して集計しようか?って考えて、正規表現とかをゴリゴリ書いてよーやく解析できるようになります。

IT 系の展示会とかセミナーとか行くと、嫌というほど「誰でも簡単にログ解析できてセキュリティ向上できます!」って言われるんですが、話聞いてみると、「嘘つけ!」って言いたくなるのばっかりで(とボヤいてもしょうがない)

とまぁ、製品買ってもアレなものばっかりなら、OSSでやりましょ!

Graylog は日本語の情報が少なくて、どーやって使うんだ??と悩むんですが、DesigNet なる SIer さんが日本語マニュアルを公開されてますんで、これが参考になります。

さて、動かしてみたスクリーンショットがこんな感じ。インターネット接続をになってる Fortigate のログのうち、deny されたトラフィックを集計してみました。Netherlandsってオランダのことなんですね。なんでオランダからこんなにアタック着てるんだ??

graylog.png


インストール

さて、まずはインストールしましょ。

私が構築するんだから、とーぜん FreeBSD です。Ports から必要なものをインストールします

  • sysutils/graylog
  • databases/mongodb36
  • textproc/elasticsearch5
  • sysutils/pwgen

けっこーデカイものばっかりなんで、24時間以上かかるかも?なお、pwgen は一回実行して結果を設定ファイルに書くだけなんで、別マシンで動いててもいいです。

Elasticsearch とか MongoDB なんていう NOSQL ツール郡を使います。Graylog 本体も Java で動いてたりします。つまり、リソース食いです。2vCPU、4GB 与えないと起動に失敗したりするくらいに。

プロセス起動

設定ファイルを設定して、プロセスを起動しましょう。

設定ファイルの書き方は他に説明してくれてるサイトがあるので、そちらを参照で。参考1 / 参考2 / 参考3

MogoDB は設定不要でした。

Elasticsearch はクラスターの設定が必要です。設定ファイルは /usr/local/etc/elasticsearch/elasticsearch.yml

cluster.name: graylog

この一行があれば大丈夫みたいです。

Graylog の設定。こっちはわりと面倒です。設定ファイルは /usr/local/etc/graylog/graylog.conf

is_master = true
node_id_file = /usr/local/etc/graylog/node-id
password_secret = ****
root_password_sha2 = ****
http_bind_address = 0.0.0.0:9000

ここで pwgen を使います。password_secret のところに、pwgen -N 1 -s 96 を実行した結果を書きます。

root_password_sha2 には、echo -n PASSWORD | shasum -a 256 を実行した結果を書きます。

あとは /etc/rc.conf に追記しましょ。

elasticsearch_enable="YES"
mongod_enable="YES"
graylog_enable="YES"

メンドクサイから、これで OS を再起動しちゃえー

Input モジュールを作る

SyslogUDP の Input モジュールを作ります

ここはまぁ、作ればいいので、作ってくださいませ

graylog-input.png解析パターンの作成

さぁ、いよいよ本題。ログメッセージを解析するための設定だなんだをつくります。ここからは、あくまでFortigate のログを解析するための話なんで、Fortigate が出すログメッセージに特化した内容です。

メニューから [System]-[Grok Patterns]を選択してマッチングパターンを登録します。

とりあえずこの三つ。他にも作るべきものはあると思うんですが、いったんこれで。コピペしたい人用に、テキストも置いておきます。

FG_APPNAME [A-Za-z.]+
FG_CUNTORYNAME [A-Za-z\s]+
FG_SERVICE [A-Za-z0-9\/\-.]+

つぎに、Input モジュールにパターンを登録します。Input モジュール設定画面にある、[Manage extractors] ボタンを押します。最終的に作る extractors はこんな感じ。

extractors.pngで、一個のextractorの書き方はこんな感じ。

extractor.png設定内容を文字列でも書き出しておきましょう。

SrcIP srcip=%{IPV4:SRC}
Src-cuntry srccountry="%{FG_CUNTORYNAME:SRC_CUNTORY}"
Service service="%{FG_SERVICE:SERVICE}"

実際のログファイルと見比べて解釈してください。たとえば、ログ本文中に service="Local-Proxy" という文字列が含まれていたとすると、3個目のルールにマッチして、「Local-Proxy」という文字列が、SERVICE という項目として抽出されます。

そのまま使ってみたいというキトクな方用に、Export したファイルを置いておきます。とーーーぜんですけど、無保証でよろしく。extractors.json

解析結果の表示

最後に解析結果を表示します。

[Search]メニューを選択して、ログの検索画面をだし、

Fields.pngこの画面のような操作をして [Show top values] メニューを選択してみてください。この場合であれば、SERVICE の集計表が表示されます。

このアーカイブについて

このページには、2020年7月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2019年12月です。

次のアーカイブは2020年9月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。