logrotateでsyslog肥大化防止

もともと小さなDisk容量が圧迫され、一部のサービスがダウンしたのでその対策。
※この方法の欠点:「元ファイルコピー」 ~ 「元ファイルの中身の消去」の間に発生したログは記録されない

ディスク・ドライブの使用量を確認
# df -h

どのフォルダが多いか特定する
# du -h /

ある程度見当がついたら、
# du -h “ディレクトリパス” | sort -n | tail -10
# du -h “ディレクトリパス” | sort -n | more
などで絞り込んでいく。

これで調べるとやはりログ関係のある/var/logが大きそう。

ディレクトリが特定できたら、ファイルを特定していく
(-aオプションでファイルも表示)
# du -ha /var/log | sort -n | more

syslog関係が肥大化している。

一般的には、メールサーバであればmaillog、WEBなど外部公開されているものであれば、不正ログイン失敗を記録するbtmpあたりが、おそらく大きくなってるのではないかと思われる。

# vi /etc/logrotate.d/syslog

/var/log/maillog /var/log/btmp をログローテートさせる場合は以下のように修正
※10MBを超えたらローテートし、4世代分まで残す場合
————————————————————————–
/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron {# sharedscripts
postrotate
/bin/kill -HUP cat /var/run/syslogd.pid 2> /dev/null 2> /dev/null || true
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}

   ↓

/var/log/messages /var/log/secure /var/log/spooler /var/log/boot.log /var/log/cron { sharedscripts
postrotate
/bin/kill -HUP cat /var/run/syslogd.pid 2> /dev/null 2> /dev/null || true
/bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}

/var/log/maillog /var/log/btmp {
rotate 4
size 10M
sharedscripts
postrotate /bin/kill -HUP cat /var/run/syslogd.pid 2> /dev/null 2> /dev/null || true /bin/kill -HUP cat /var/run/rsyslogd.pid 2> /dev/null 2> /dev/null || true
endscript
}
————————————————————————–

テスト実行
# logrotate -d /etc/logrotate.conf

ファイルが指定した世代数や要領でローテートされているのを確認

CRONへの登録確認
/etc/cron.daily内にlogrotateがあればOK
# ls -lat /etc/cron.daily

MySQLのレプリケーション設定

■マスター側

設定ファイル編集
vi /etc/my.cnf

 

MySQL再起動

 

データディレクトリがにバイナリデータが作成されているのを確認

 

MySQLユーザと権限付与

 

データダンプ

※特定のDBのみdumpする場合は–all-databasesを削除しdb名を追加
※MyISAMの場合は、–master-dataによって、自動的に–lock-all-tablesが有効になるので、すべてのテーブルがロックされてしまうので注意
※InnoDBであれば、–single-transactionを付与することで、ロックされることなくdumpを取得できる。

dumpファイルをスレーブ側へ転送しておく

 

■スレーブ側設定

設定ファイル編集

 

再起動

 

マスターDBのダンプの読み込み

 

ダンプした時点の、マスターのバイナリログファイル名(MASTER_LOG_FILE)と開始位置(MASTER_LOG_POS)を確認しておく

 

レプリケーション設定

 

レプリケーションの開始

 

レプリケーションの動作確認

※Slave_IO_Running と Slave_SQL_Running がどちらもYesになっていれば、レプリケーションが正常に動作しています。

参考サイト)

レプリケーションが動かなくなった時

基本は以下のサイトの手順で復旧可能。

MySQLのレプリケーション時エラー対処方法

https://qiita.com/soramugi/items/3c33200b5903007f3ead

 

もしそれでもだめなら、当記事の「データダンプ」のとこからやり直す。

2019/1/28レプリケーションが機能していないと気付いた(「Slave_IO_Running 」が「Yes」にならない)。

その際はダンプからもう一度行うことで復旧した。

ストレージ障害とか、IO系の障害とかあった後は、要注意。

OpenSSLでPKCS12ファイルの解凍

主にSSLサーバ証明書の設置や更新のための1手段。

まず、対象のPKCS12ファイルを、WinSCPなどのFTPクライアントやSSHクライアントを使い、サーバのユーザホームディレクトリ等に転送。

ここでは、
転送したPKCS12ファイルの場所を、
/home/userdir/PKCS12.pfx
サーバ証明書と中間証明書の展開先を、
/etc/httpd/conf/ssl.crt/
秘密鍵の展開先を、
/etc/httpd/conf/ssl.key/
とする。

展開時にファイルは上書きされるので、過去のものがあれば念のため各ファイルのバックアップ取得
# cp /etc/httpd/conf/ssl.crt/clcert.crt /etc/httpd/conf/ssl.crt/clcert.crt.bak
# cp /etc/httpd/conf/ssl.crt/cacert.cer /etc/httpd/conf/ssl.crt/cacert.cer.bak
# cp /etc/httpd/conf/ssl.key/privatekey.key /etc/httpd/conf/ssl.key/privatekey.key.bak

#サーバ証明書解凍
# openssl pkcs12 -in /home/userdir/PKCS12.pfx -clcerts -nokeys -out /etc/httpd/conf/ssl.crt/clcert.crt

#中間証明書解凍
# openssl pkcs12 -in /home/userdir/PKCS12.pfx -cacerts -nokeys -out /etc/httpd/conf/ssl.crt/cacert.cer

#秘密鍵解凍
# openssl pkcs12 -in /home/userdir/PKCS12.pfx -nocerts -nodes -out /etc/httpd/conf/ssl.key/privatekey.key

上記各々のコマンドで、解凍パスワードを求められるので入力すると、目的の場所にファイルが展開される。

後は、必要に応じて、ssl.conf内の各ファイルのパスを指定し、WEBサーバのリロードまたは再起動。

# リロードする前に文法チェック
# service httpd configtest

# リロード
# service httpd reload

 

MySQLのクエリログの出力方法

/etc/my.cnfを開く。

[mysqld]ディレクティブにログの種類と出力場所を指定。

代表的なものは下記。

(エラーログ)※これはたぶん最初から書いてある
log_error=”/var/log/mysqld.log”
log_warnings=1

(一般クエリログ)
log=”/var/log/sql.log”

(バイナリログ)
log_bin=”/var/log/mysqlbin.log”
log_bin_index=”/var/log/mysqlbin.list”
max_binlog_size=1M
expire_logs_days=1

(スロークエリログ)
slow_query_log=1
slow_query_log_file=”/var/log/slowquery.log”
log_queries_not_using_indexes
log_slow_admin_statements

設定を書いて保存したら、出力ファイルを作成し、所有者をmysqlに変更しておく。

(一般クエリログの場合)
# touch /var/log/sql.log
# chown mysql:mysql /var/log/sql.log

最後にmysqldを再起動。
# service mysqld restart

一般クエリログの出力例
——————————-
  :
18 Connect ****@localhost on dbname
18 Query set autocommit=1
18 Query SET NAMES utf8
18 Query SELECT * FROM tbl1
18 Query SELECT * FROM tbl2
WHERE id = ‘*****’
18 Query UPDATE tbl2
SET clm1 = UNIX_TIMESTAMP()
WHERE id = ‘*****’
18 Query SELECT * FROM tbl3 WHERE id=’****’
17 Quit
  :
——————————-

ちなみにSQLインジェクション攻撃を受けている場合のログの例
——————————-
  :
1019 Connect ****@localhost on dbname
1019 Query set autocommit=1
1019 Query SET NAMES utf8
1019 Query SELECT * FROM tbl1 WHERE id=’-2353′ OR ORD(MID((SELECT IFNULL(CAST(clm1 AS CHAR),0x20) FROM tbl2 LIMIT 1328,1),12,1))>112#’ AND clm2=’abcdefg’
1019 Query SELECT * FROM tbl3
1019 Quit
  :
——————————-

ちなみに、
# tail -f /var/log/sql.log
とすれば発行クエリがリアルタイムでチェック可能。

DBI使って開発段階で生のSQLをチェックしたい時かあると思いますが、DBIx::QueryLogとか使うよりこっちのほうがアナログで簡単そう。

sqlmapの使い方

いろいろ資料は散見されるが、、、

弊社なりにまとめてみました。

まず、sqlmapをインストールしたディレクトリに移動。

$ cd sqlmap

基本は、

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga”

とやるだけでOK。Getパラメタに対してインジェクションチェックを行ってくれる。

POSTもチェックしたいときは、

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” –data “postparm1=123&postparam2=456”

 

DBMSの種類がすでに分かっているときは、明示的に指定すれば時間の省略になる。

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” –dbms mysql

 

脆弱性が発見されたときに、同時にDB一覧の取得を試みる場合。

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” –dbs

 

脆弱性が発見されたときに、同時にテーブル一覧の取得を試みる場合。

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” –tables

 

脆弱性が発見されたときに、特定のテーブルのカラムデータ取得を試みる場合。

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” -T “table name” –colum

※「column」ではなく「columns」と記載されているドキュメントも見かけたが、うちの環境の場合は「column」で通った。

 

脆弱性が発見されたときに、特定のテーブルの中身のダンプ取得を試みる場合。

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” -T “table name” –dump

※実際表示されるとかなりショッキングです。。。。

 

基本は、上記の基本的なコマンドを発行し、デフォルトレベルのチェックで、

[CRITICAL] all tested parameters appear to be not injectable.

と判定されれば、とりあえずは脆弱性は無いということなので、あとは必要に応じてチェックレベルを上げてみてもよいかと思います。

レベルを指定する場合は下記のようにする。(0~5の範囲で指定可能)

$ ./sqlmap.py -u “http://hoge.jp/index.php?id=fuga” –level 3

 

その他、任意のヘッダを指定したりログレベルを調整したり、さまざまな使い方ができる模様。

詳細は下記の参考サイトをどうぞ。

 

参考サイト)

オープンソースの SQL インジェクション脆弱性診断ツールの sqlmap を Kali Linux で使ってみる

 

sqlmapを使うための環境整備

sqlmapとは、オープンソースで開発されている SQL インジェクションの脆弱性診断ツール。

これを使うために、CentOS5.5とかFedora10とか比較的古いlinuxまわりで環境整備しようとしたが、最終的にpythonのバージョンが古くて使えないという壁にぶつかったため、まっさらなCentOS6.2_LAMP_x86_64から入れてみたら動くようになったので、その備忘録。

64bitのサーバなんて初めてだったけど。。。
まずユーザ追加
# useradd sqlmap
# passwd sqlmap

 

■ファイアフォール設定

内部から行ったアクセスに対する外部からの返答アクセスを許可
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

自ホストからのアクセスをすべて許可
iptables -A INPUT -i lo -j ACCEPT

ssh許可
iptables -A INPUT -p tcp –dport 22 -j ACCEPT

その他のアクセス、転送をすべて拒否
iptables -P INPUT DROP
iptables -P FORWARD DROP

確認
# iptables -nL

保存
# /etc/init.d/rc.d/iptables save

■SSH設定
RootでのSSHログイン禁止
# echo “PermitRootLogin no” >> /etc/ssh/sshd_config

再起動
/etc/init.d/rc.d/sshd restart

■リモート接続

SSHクライアントに「未サポートのエスケープシーケンスを見つけました。 ESC [?1034h」と言われたら、ターミナルのエミュレータをxtermからktermに変更してリトライ。

■依存パッケージインストール

yum実行時に「Cannot find a valid baseurl for repo: base」と出てmirrorlist.centos.orgに接続できない時

# vi /etc/yum.repos.d/CentOS-Base.repo

すべてのmirrorlist=の行をコメントアウトし、baseurlにrikenのURLを指定
——————————-
[base]
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra

baseurl=http://ftp.riken.jp/Linux/centos/$releasever/os/$basearch/

[updates]
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra

baseurl=http://ftp.riken.jp/Linux/centos/$releasever/updates/$basearch/

[extras]
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra

baseurl=http://ftp.riken.jp/Linux/centos/$releasever/extras/$basearch/

[centosplus]
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra

baseurl=http://ftp.riken.jp/Linux/centos/$releasever/centosplus/$basearch/

[contrib]
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib&infra=$infra

baseurl=http://ftp.riken.jp/Linux/centos/$releasever/contrib/$basearch/
——————————-

libcurlをインストール

# yum install -y curl-devel
wget が入っていないと思われるのでインストール

# yum install -y wget

■Gitをインストール

# cd /usr/local/src
# wget https://git-core.googlecode.com/files/git-1.9.0.tar.gz
# tar zxvf git-1.9.0.tar.gz
# rm git-1.9.0.tar.gz
# cd git-1.9.0

# ./configure –prefix=/usr/local/

gccがないと言われたらインストール
# yum install -y gcc

# make

「expected specifier-qualifier-list before ‘z_stream」と言われたらzlibインストール
# yum -y install zlib-devel

再度 make

「Can’t locate ExtUtils/MakeMaker.pm in @INC」と言われたら、perl-ExtUtils-MakeMakerをインストール
# yum install -y perl-ExtUtils-MakeMaker

再度 make

「tclsh failed; using unoptimized loading」とでたら、gettextを入れる
# yum install -y gettext

再度 make

今度は通ったっぽい。

# make install

バージョン確認
# git –version
-> git version 1.9.0

OK

ユーザのホームに戻り
$ git clone https://github.com/sqlmapproject/sqlmap.git
$ cd sqlmap

これでひとまず診断の準備完了。

参考サイト)
http://qiita.com/shyamahira/items/9f80d16c3436f9dea753
http://qiita.com/akata/items/57c81ae969255e3c9a70
http://kentai-shiroma.blogspot.jp/2014/10/centos65glibc.html
http://d.hatena.ne.jp/hateka/20110924/1316850271
http://qiita.com/yusukaaay/items/6a39cc2f983cb0319bd1

 

apacheのSNI対応を行った場合のメリット・デメリットとapacheからのサーバ証明書切り替え処理

apache2.2.12以降で利用できるようになったSNI。

弊社サービスでも採用すれば、標準提供のワイルドカードSSL証明書と、オプションによる顧客個別のSSLサーバ証明書がうまく共存できるのではないかと考えた。

つまり、標準用とオプション用のサーバ証明書と秘密鍵を設定しておき、名前ベースのアクセスのみでサーバ証明書を切り替えられれば、標準SSL←→オプションSSLをいちいち証明書を切り替えてapacheをリロードする必要が無い。

しかし、いかんせんSNIはほぼすべてのフィーチャーフォンに未対応である。

2015年12月現在、スマホ時代が到来してフィーチャーフォンのシェアはもっぱら減少傾向にある。

運用上単純にフィーチャーフォンを排除もしくはフィーチャーフォン専用のホストを用意する場合は問題ないが、弊社のサービスはメールであり、かつ1顧客1ホストである。

特にフォームからの読者登録などの処理について、フィーチャーフォンの前提をまだ排除するわけにはいかない。

SNIを採用した場合、フィーチャーフォンのアクセス時に自動的に平文通信に切り替えてくれればまだいいのだが、SSLネゴシエーションをする段階での問題なので、無理である。

従って、フィーチャーフォンでアクセスした場合は、SNIの仕様として、デフォルトの証明書であるワイルドカードSSLの証明書が採用される。つまりフィーチャーフォンはワイルドカードにも対応していないので、結果として認証不可警告画面が出る。

これらの問題点ならびに、現在のプラットフォームはCentOS5.5+apache2.2.3なので、これらやOpenSSLをリビルドしてSNIに対応させなければならないことのリスクを考えれば、やはり標準SSL←→オプションSSLは証明書を切り替えてapacheをリロードするのが現実的であると考えた。

実現するにあたって、特に難しいことは無いが、既存のホストへのパッチ処理は最低限必要になる。

具体的には下記のような感じ。

1.ワイルドカード用のサーバ証明書・秘密鍵・ルート証明書をSCPなどで転送してapacheの設定ディレクトリ配下にコピー。

2.上記の証明書を利用するように設定したコンフィグファイル(例:ssl_wc.conf)を作成。

3.既存のssl.confをリネームして無効にする。

4.CGIが実行できる場所に、証明書の切り替えやapacheのリロードを実行するための処理を書いたshellスクリプトを追加

5.sudoユーザ設定ファイルにおいて、apacheに上記shellスクリプト(コマンド)の実行を許可する

ここまで準備を行ったら、アプリ側に、shellファイルを起動する処理を書き、GUIでサーバ証明書の切り替えを行えるようにコーディングし、これらが有効になるようにシステムファイルをバージョンアップしてもらう。

※当たり前だが、くれぐれも任意のパラメタをコマンドとして実行できてしまうような危険なshellにはしないこと。

またフォームの入力画面は、オプションSSLなしの場合は原則平文で出力し、formのaction属性(POST先)を動的に出力する。

フィーチャーフォン以外からのアクセスであれば https://+”ワイルドカードSSL用のドメイン”を出力し、フィーチャーフォンからのアクセスであれば http://+”デフォルトのドメイン”を出力する。

なお、shellの例。
————————————————————-
#!/bin/bash

# Subroutines

use_ssl_origin() {

# Checking config files…

local chg_ssl=’1′
local chg_ssl_wc=’1′

if [ ! -f “$SSL_CONF_DIR/ssl.conf.bak” ]; then
if [ ! -f “$SSL_CONF_DIR/ssl.conf” ]; then
retval=”Both ssl.conf.bak and ssl.conf are not exsist.”
return 1
else
chg_ssl=’0′
fi
fi
if [ ! -f “$SSL_CONF_DIR/ssl_wc.conf” ]; then
if [ ! -f “$SSL_CONF_DIR/ssl_wc.conf.bak” ]; then
$retval=”Both ssl_wc.conf and ssl_wc.conf.bak are not exsist.”
return 1
else
chg_ssl_wc=’0′
fi
fi
if [ $chg_ssl -eq 1 ]; then
# Updating config file…(ssl.conf.bak -> ssl.conf)
mv $SSL_CONF_DIR/ssl.conf.bak $SSL_CONF_DIR/ssl.conf || { retval=”Rename failed.(ssl.conf.bak -> ssl.conf)”; return 1; }
fi
if [ $chg_ssl_wc -eq 1 ]; then
# Updating config file…(ssl_wc.conf -> ssl_wc.conf.bak)
mv $SSL_CONF_DIR/ssl_wc.conf $SSL_CONF_DIR/ssl_wc.conf.bak || { retval=”Rename failed.(ssl_wc.conf -> ssl_wc.conf.bak)”; return 1; }
fi

# On bash, Success statsu -> 0
return 0
}

use_ssl_wc() {

# Checking config files…

local chg_ssl=’1′
local chg_ssl_wc=’1′

if [ ! -f “$SSL_CONF_DIR/ssl.conf” ]; then
if [ ! -f “$SSL_CONF_DIR/ssl.conf.bak” ]; then
retval=”Both ssl.conf and ssl.conf.bak are not exsists”
return 1
else
chg_ssl=’0′
fi
fi
if [ ! -f “$SSL_CONF_DIR/ssl_wc.conf.bak” ]; then
if [ ! -f “$SSL_CONF_DIR/ssl_wc.conf” ]; then
retval=”Both ssl_wc.conf.bak and ssl_wc.conf are not exsist.”
return 1
else
chg_ssl_wc=’0′
fi
fi
if [ $chg_ssl -eq 1 ]; then
# Updating config files…(ssl.conf -> ssl.conf.bak)
mv $SSL_CONF_DIR/ssl.conf $SSL_CONF_DIR/ssl.conf.bak || { retval=”Rename failed.(ssl.conf -> ssl.conf.bak)”; return 1; }
fi
if [ $chg_ssl_wc -eq 1 ]; then
# Updating config files…(ssl_wc.conf.bak -> ssl_wc.conf)
mv $SSL_CONF_DIR/ssl_wc.conf.bak $SSL_CONF_DIR/ssl_wc.conf || { retval=”Rename failed.(ssl.conf.bak -> ssl.conf)”; return 1; }
fi

# On bash, Success statsu -> 0
return 0
}

httpd_reload() {

/etc/rc.d/init.d/httpd reload

}

# Define values
SSL_CONF_DIR=’/etc/httpd/conf.d’

# Main
retval=”0″
if   [ “$1” = “use_ssl_origin”  ]; then
use_ssl_origin || { echo $retval; exit 1; }
elif [ “$1” = “use_ssl_wc” ];      then
use_ssl_wc     || { echo $retval; exit 1; }
elif [ “$1” = “httpd_reload” ];     then
httpd_reload
fi

exit
————————————————————-

参考リンク)
http://builder.japan.zdnet.com/etc/20402262/
http://hoge001.exblog.jp/13982612
http://another.rocomotion.jp/14140508324311.html
http://blogs.yahoo.co.jp/xkrdy982/12244910.html
http://okwave.jp/qa/q8172686.html
http://webcache.googleusercontent.com/search?q=cache:eKZwQAKc3pAJ:www.hutcraft.jp/%3FD%252F2013-08-03+&cd=3&hl=ja&ct=clnk&gl=jp
http://centos.it-study.info/web/apache2225.html
http://www.atmarkit.co.jp/ait/articles/1108/05/news122.html