Home

技術系のメモと日々の雑感

sshguard の使用感

ssh のログイン失敗が続いたときに、接続元をブロックするルールを iptables に自動で追加してくれる sshguard というツールがあるそうな。
後学のために家のマシンで試してみた。
CentOS 用のパッケージは見当たらなかったので、ソースをダウンロードしてインストールする。

# tar jxvf sshguard-1.4.tar.bz2
# cd sshguard-1.4
# ./configure --prefix=/usr/local --with-firewall=iptables --with-iptables=/sbin/iptables

--with-firewall は指定しないとエラーになった。

# make
# make install

実行ファイル sshguard は /usr/local/sbin の下に置かれる。
一緒にインストールされる man ページが詳しいのは助かるね。
続いて、iptables に必要な設定を追加する。
以下、sshguard の動作を見るのに必要な設定だけ。

# iptables -N sshguard
# iptables -A INPUT -p tcp --dport 22 -j sshguard

これで準備ができたので起動しよう。

# tail -n0 -F /var/log/secure | /usr/local/sbin/sshguard &

試しに、テスト用のホスト 192.168.0.100 から接続して、わざとログインに失敗してみると

# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
sshguard   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22

※省略

Chain sshguard (1 references)
target     prot opt source               destination
DROP       all  --  192.168.0.100        0.0.0.0/0        ← 追加された

よしよし、ちゃんと締め出してくれたね。
ただ、しばらく動きを見ていると、ブロックしたホストを解放するタイミングになってもルールが残ってしまったり、同じルールが複数追加されてしまうことがあった。
あと、これは設定の問題かもしれないけど、本家のドキュメントのページにある、syslog からパイプでログを渡す設定はうまくいかなかった。
クリティカルなサーバで使うにはあと一歩というところかな。

MySQL の configure で unrecognized options

MySQL 5.1.36 をソースから入れたときの話。
InnoDB を使うので、過去に作った手順に従って configure で --with-innodb を指定したら

configure: WARNING: unrecognized options: --with-innodb

と怒られた。
実は以前、このワーニングに気づかずにそのままコンパイルしてしまったことがあるんだけど、InnoDB は問題なく使えていた。
--with-innodb を指定しないでコンパイルしたら、当然ながら InnoDB は使えなかったから、とりあえずこのオプションは効いているってことだね。
とはいえ、ワーニングを放置しておくわけにもいかない。
暇を見つけて configure --help を眺めてみると、InnoDB を有効にするオプションの指定方法が変更されていた。
以下、関係があるところだけ。

--with-plugins=PLUGIN[[[,PLUGIN..]]]
Plugins to include in mysqld. (default is: none)
Must be a configuration name or a comma separated list of plugins.
Available configurations are: none max max-no-ndb all.
Available plugins are: partition daemon_example ftexample archive blackhole
csv example federated heap ibmdb2i innobase myisam myisammrg ndbcluster.

=== InnoDB Storage Engine ===
Plugin Name:      innobase
Description:      Transactional Tables using InnoDB
Supports build:   static and dynamic
Configurations:   max, max-no-ndb

ということで、今後は --with-plugins=innobase と指定しよう。

パスワードが書かれたスクリプトを読めなくする

MySQL のスレーブのステータスをチェックするスクリプトを書いているときに思ったんだけど、パスワードをスクリプトの中に書いてしまうのってちょっと抵抗があるね。
これって mysql コマンドに限らず、passwd --stdin とか、いろんなパターンで絡んでくる話だし。
とはいえ、gpg とかでパスワードを暗号化してしまうと実行時に毎回入力しなければいけなくなるから、それも本末転倒だ。
完全な解決策は簡単には見つかりそうにないなぁ。
まぁ、とりあえずスクリプトを開いたときにそのままでは読めないようになってればいいから・・・、今回は gzexe で逃げておこう。
知ってる人なら圧縮された後のファイルを見ただけで気づくだろうけど、近頃はディスクの容量不足に悩まされることがなくなったせいか、このコマンドの知名度も下がっていってる気がするしね。
-d オプションで元のファイルに復元できるけど、gzexe 自体がシェルスクリプトだから処理を削るのは難しくない。
ちなみに、常用してる CentOS 5.3 でこのオプションを試してみたら、どうもバグがあるらしくエラーが出て復元できなかった。
かえって好都合だ。
もちろん、こんなの単なる圧縮だからセキュリティ的にはぜんぜんお勧めはできない。
やるなら At Your Own Risk で。

NFS と TCP Wrapper (Part2)

CentOS 5.3 でサーバ全体のレスポンスが極端に悪くなることがあった。
Domain-U に作った環境だったので最初は Xen を疑ったけど、結局は NFS の設定が不完全なのが原因だった。
現象が出たとき NFS サーバ側の dmesg には次のようなメッセージが出ていた。

lockd: server XXX.XXX.XXX.XXX not responding, timed out

表示されている IP アドレスは NFS クライアントのもの。
同様に NFS クライアント側の dmesg にも

statd: server localhost not responding, timed out
lockd: cannot monitor XXX.XXX.XXX.XXX
lockd: failed to monitor XXX.XXX.XXX.XXX

というメッセージが出ていた。
こっちに表示されている IP アドレスは NFS サーバのものだ。
これを見て nfslock サービスの問題だと気づいたんだけど、前に設定したときは nfs と portmap しか気にしてなかったはず。
不思議だ。
サーバとクライアントの両方で nfslock を無効にしていたら関係ないのかなぁ。
原因が分かったとはいえ、TCP Wrapper で制限をかけているので、ここからさらに試行錯誤が必要だった。
結果をまとめておくと、NFS サーバ側は portmapnfsnfslock を有効にして、/etc/hosts.allow には

portmap:[NFSクライアントのIP]
mountd:[NFSクライアントのIP]

と書く。
NFS クライアント側は portmapnfslock を有効にして、/etc/hosts.allow に

portmap:[NFSサーバのIP]

と書けばよかった。
ちなみに、iptables ではサーバとクライアント間は IP アドレスだけで制限して、ポートは NFS に限らずすべて許可している。
iptables で NFS(v3) のポートをきっちり制限するのは難しいので、現時点では TCP Wrapper と組み合わせるのがベストかと。
そういえば nfs と nfslock のサービスが分けられているのがちょっとした疑問だったんだけど、これってクライアント側でも nfslock を使うからなんだね。
今頃気づいてる自分って・・・。

MySQL のスレーブのステータスを定期的にチェック

MySQL でレプリケーションを組んだ後、スレーブのステータスを定期的にチェックする方法を考えていた。
以前、Ver 5.0 で一度レプリケーションの構成を組んだときに、load data infile とか auto increment といったステートメントベースが非対応の SQL 文を使ってしまってレプリケーションが止まったことがあるので、それ以来ちょっとだけ気をつけるようにしている。
調べてみたら、mysql コマンドは標準入力から SQL 文を読み込んで実行できるので、今回はこれでいくことにした。
次のような簡単なスクリプトを cron で実行させるだけだ。

#!/bin/sh
echo 'show slave status¥G' | ¥
/usr/local/bin/mysql -u root -pXXXXXX | ¥
mail -s 'slave tatus' hoge@example.com

Last_Errno とかを見てエラーのときだけメールしてもいいんだけど、スクリプトで何かミスして実際にエラーになったときにメールが飛んでこなかったら大変なので今回はやめておこう。
こういうクリティカルなところはシンプルに限る。