標準リポジトリでありそうでなかったのが一定時間が経過したプロセスをkillするプログラムとMySQL、Postgresqlを保護するプログラム。といっても通常運用で長時間居座るプロセスを絶対にぶっ殺したいという場面はそれほど多くないとは思うが、共用サーバなどではしぶとく生き続けるプロセスなどを監視・killしたいという場面は多々出てくると思う。またMySQLやPostgresqlは、設定を複雑にしないとquotaすることができないので作った。
proc_killer
このプログラムの主目的は簡単で、監視対象ユーザを作成して、そのユーザの制限時間を指定してやる。するとそのユーザが立ち上げたプログラムは、ホワイトリストに入っていない限り制限時間経過後にkillされる運命にある。デフォルトでは30秒周回するが、設定変えればもう少し短くできる。
役に立ちそうな場面
上記のとおりで、共用サーバなどでcgroupをかければメモリとCPUなどの使用率は制限できるものの、sleep 999のようなうるさいコマンドを実行されるとうるさい。またApache環境下などで、一定時間が経過したphpプロセスなどを瞬時にkillしたいという需要があるが、標準だと.htaccessのTimeoutディレクティブを変えたりするとすり抜けられてしまう。それを潰す。
ソースコード
Githubに直接公開した。 systemd、rc.dでも動く(はず)。
設定例
基本的に次のようなファイル構成を想定している。
/usr/local/proc_check/bin/proc_killer
/etc/poc_check
├──monitor_users #監視対象ユーザ
├──cmdline_blacklist_regex #正規表現のコマンド規制
├──cmdline_blacklist #禁止コマンド
└──proc_allow_list #無条件で許可するコマンド
/etc/sysconfig/proc_killer.conf #メイン設定ファイルproc_killer.confの例
[main]
# デフォルトの制限時間(秒)
DEFAULT_TIME_LIMIT=300
# ログ出力レベル / kill 動作レベル
# 0 = Dry-run(検知のみ)
# 1 = LOG_DEBUG(検知のみ、killなし)
# 2 = LOG_INFO(SIGTERMのみ)
# 3 = LOG_NOTICE(SIGTERM + SIGKILL)
DEBUG_LEVEL=3
# 外部設定ファイルを include して管理
include=/etc/poc_killer/proc_allow_list
include=/etc/poc_killer/monitor_users
include=/etc/poc_killer/cmdline_blacklist
include=/etc/poc_killer/cmdline_blacklist_regexmonitor_users
[user_limits]
localuser1=60 # 1分kill
noisyuser=300 # 5分超過で kill
tester=600 # 10分超過で killcmdline_blacklist_regex
# Regular expressions matched against process command line.
# Any match → highest priority kill (ignores allow list & user limits).
# Perl sleep bombs
^perl .*sleep
# Fork bombs
.*fork.*
# Netcat misuse
(^| )nc( |$)
# Long-running wget or curl
(^| )wget( |$)
(^| )curl( |$)
# Dangerous shell loops
:(){ :|:& };:cmdline_blacklist
#ここに記載したコードは無条件kill対象になるので注意proc_allow_list
bash
sh
zsh
csh
tcsh
httpd
apache2
php-cgi
php-fpm
perl
python
python3
ruby
proftpd
vsftpd
pure-ftpd
postfix
sendmail
exim
dovecot
courier
imapd
pop3d
sshd
cron
crond
atd
syslogd
rsyslogd
systemd
init
ls
cat
less
more
tail
head
grep
awk
sed
vim
vi
nano
scp
sftp
rsync
wget
curl
tar
gzip
bzip2
xz
zip
unzip
gcc
g++
make
manMySQLのディスク監視
長くなってしまったのでGithubに。README通りで、2デーモンと1プラグインでMySQLを保護する目的で作った。通常、MySQL単体でquotaすることは難しいが、これを入れると指定したユーザのデータベース利用を制限することができる。例えばuser1は500MBまで、user2は1GBまでといった具合。MySQLのパスが平文になってしまうので、必ずchmod 600しないと詰む。
/etc/mysql_monitor/user_limits
#user_name soft_limit_bytes hard_limit_bytes
alice 1000000000 2000000000
bob 5000000000 8000000000
yamagamitetsuya 0 300000000000000000000/etc/storage_guard_users.conf
[users]
alice = 1073741824 , 2147483648
bob = 2147483648 , 3221225472
charlie = 536870912 , 1073741824/etc/storage_guard.conf
[general]
log_level = INFO
check_interval = 30
metrics_file = /var/run/storage_guard.prom
kill_on_hard_limit = yes
user_limits_file = /etc/storage_guard_users.conf
threshold_trigger = 3
use_threads = yes
max_threads = 16
use_connection_pool = yes
connection_pool_size = 10
daemon_user = mysqlmon
daemon_group = mysqlmon
[database]
host = localhost
port = 3306
user = monitor
password_file = /root/etc/mysql_monitor/passwd
type = mysql/etc/mysql_monitor/db_list
# hostname username database monitor_interval sharding_group metrics_enabled
localhost monitor mysql 60 0 1/etc/mysql_monitor/db_config
# hostname username password database port check_interval query_method
localhost monitor secretpw mysql 3306 60 information_schema※db_listとdb_configは必ずroot:root、chmod 600すること。
※事前にmonitorというユーザをMySQLに追加。権限付与すること。
CREATE USER 'monitor_user'@'%' IDENTIFIED BY '{PASSWORD}';
GRANT SELECT ON `information_schema`.* TO 'monitor_user'@'%';
GRANT SELECT ON `mysql`.* TO 'monitor_user'@'%';
GRANT SELECT ON *.* TO 'monitor_user'@'localhost';
GRANT ALTER USER ON *.* TO 'monitor_user'@'localhost';
GRANT PROCESS ON *.* TO 'monitor_user'@'localhost';
GRANT KILL ON *.* TO 'monitor_user'@'localhost';
GRANT PROCESS ON *.* TO 'monitor_user'@'%';
FLUSH PRIVILEGES;制限した容量を使うと勝手にアカウントをロックしてくれる。
Postgresql監視
おまけみたいなコードなのでGithub記載の通り適当に入れてください。動作原理は上と同じ。
Apacheのログファイル問題とホームディレクトリ死ぬと復活できなくなる問題
を解決するためにmod_logdir_improvedとmod_make_homedirを作った。logdirのほうは、ユーザにアクセスログ提供してやっても勝手に消して次の再起動まで復活しない問題を。homedirはユーザがホームディレクトリ消したらgracefulでもrestartでも復旧しなくなる問題を解決する(再起動前にhockして復活させる)もの。README通り、勝手にログディレクトリとホームディレクトリを作ってくれる。
<VirtualHost *:80>
ServerName example.com
DocumentRoot /home/user1/public_html
# Ensure the DocumentRoot exists with secure ownership
MakeHomedirEntries /home/user1/public_html user1 group 0700
MakeHomedirEntries /home/user1/logs user1 group 0750
MakeHomedirEntries /home/user1/tmp user1 group 0700
ErrorLog logs/example.com_error.log
CustomLog logs/example.com_access.log combined
</VirtualHost>

