以前からVPSのようなグローバルIPで直接監視をするようなサーバに対してZabbixを使うときには、Stoneで暗号化をしてきた。
Stoneでzabbix途中経路を暗号化
でも、長期運用をしていると必ずと言って・・・とある問題があった。
stoneを通しての通信が停止したり、到達できないというエラーで監視ができなくなってしまう。
これは、Server側のstoneとAgent側を再起動すると解決はするのだが、一回では再起動が完了せず、落とすまでにも時間がかかるし、立ち上げるのもひどいときには5,6回起動コマンドが必要になる。もしかしたら、メモリ解放ができていなくて、このような現象になっているのかもしれないけれど。(pgpool-IIでも同様の現象があったので、マッチングテーブルが解放できないとかなのかなぁ)
というわけで、Zabbix Agentの通信経路暗号化に他のプロダクトを使うことにした記録。1年ぐらい前に実装して今のところ運用実績は1年程度。
プロダクト候補
■1.stuunel
参考にしたのは上記のサイト。以前から安定性とかも問題なさそうだったので、採用してみたいと思っていた。
■2.SSH のポートフォワード
切断、接続が手動しかないのでは再起動するまでのデータ抜けが発生したり、運用手順が煩雑になったりするので敬遠される。
でも、今回試したのはSSHのポートフォワード。なぜ?と思われるかもしれないけれど、iptablesでポートを開ける必要が無いっていうのとスクリプトで何とかなるんじゃないか?と思ったから。stuunelのほうが実装例が多いみたいなので、挑戦するならこっちのほうかなと思ってのこと。
■参考サイト・フォーラムのURL
ZABBIX-JPフォーラム:トンネリングのポートを使用しての監視
いわずもがなと思いますが、日本のZABBIXコミュニティのフォーラム。エージェントアクティブを使った監視には2つのポートをトンネリングしないとだめっていう事が書いてある。
ZABBIXをSSH越しで使う。の巻
autosshっていうのは知らなかった。機会あったら使いたいかも。
お名前.com の VPS を Zabbix でリモート監視
iptablesのnatテーブルにルールを書いて、相手先への接続を自分自身のポートに変更している。LVSでも勉強したけれど、iptablesの応用力には驚かされる。
■作ってみたSSHトンネルを作成するスクリプト
準備するもの
・トンネル専用ユーザーと公開鍵が仕込んである監視対象サーバ。
・監視対象サーバ上のZabbixエージェントの設定ではlocalhostの10050portでListenして、localhostの10051portにサーバがある設定。
・監視対象サーバ上のSSHポートは22から12022等に変更済み。
#!/bin/sh KEY=/usr/local/zabbix/bin/for_tunnel_dsa KNOWN_HOSTS=/usr/local/zabbix/bin/for_tunnel_known_hosts SSH_OPTIONS="-t -t -i ${KEY} -o UserKnownHostsFile=${KNOWN_HOSTS}" # debug echo $@ # 接続 function start() { /usr/bin/ssh ${SSH_OPTIONS} ${AGENT_USER}@${AGENT_HOST} -n -p ${SSH_PORT} -L ${TUNNEL_PORT}:127.0.0.1:10050 & /usr/bin/ssh ${SSH_OPTIONS} ${AGENT_USER}@${AGENT_HOST} -n -p ${SSH_PORT} -R 10051:127.0.0.1:10051 & } # 切断 function stop() { pgrep -l -f "${AGENT_USER}@${AGENT_HOST} -n -p ${SSH_PORT} " pkill -f "${AGENT_USER}@${AGENT_HOST} -n -p ${SSH_PORT} " echo "${AGENT_USER}@${AGENT_HOST} -n -p ${SSH_PORT} " echo 'stop ssh for tunnel' } if [ $# -ne 5 ];then echo $"Usage: $0 {start|stop|restart} Destination_server Login_user Localport Destination_ssh_port" exit 1 fi AGENT_HOST=${2} AGENT_USER=${3} TUNNEL_PORT=${4} SSH_PORT=${5} case "$1" in start) start ;; stop) stop ;; restart) stop sleep 1 start ;; *) echo $"Usage: $0 {start|stop|restart}" exit 1 esac |
スクリプトをキックするためのZabbix設定
またこれが厄介な話なのだが、引数に接続ユーザーやZabbixサーバからエージェントを指定するときのポートをスクリプトに渡さなくてはならないのに、Zabbix1.8のリモートコマンドに引き渡せる情報は、HOSTNAMEだけだった。そこで、苦肉の策としてプロファイルに書き込んだ情報を引き渡している。
リモートコマンドに記述した内容
「ZABBIXサーバの名前」:/usr/local/zabbix/bin/zabbix_ssh_tunnel.sh start {HOSTNAME} {PROFILE.TAG1} >> /tmp/zabbix_ssh_tunnel.log 2>&1 |
ホストのプロファイルのタグに書き込んだ内容
zabbix_tunnel 20054 12022 |
今後、Zabbix2.2に移行するにあたって拡張したいことや修正必要箇所
https://www.zabbix.com/documentation/2.2/manual/appendix/macros/supported_by_location
これを見ると、PORTが「Trigger-based notifications and commands」でサポートされたので、引数には{HOST.NAME} {HOST.PORT} {PROFILE.TAG1}(=zabbix_tunnel 12022)となりそう。※{PROFILE.TAG1}は{INVENTORY.TAG<1-9>}と名前が変わった模様
あと、「DB monitoring additional parameters, SSH and Telnet scripts」が{$MACRO}を使えるらしいので、どんなものなのか?を確かめてみたい。
これは、SSHの接続をチェックするタイプだった。
https://www.zabbix.com/documentation/2.2/manual/config/items/itemtypes/ssh_checks
そういえば、これも合わせてテンプレートに入れておいて、回復したことをトリガーにトンネルスクリプトを流しても良いかもしれない。