2021年7月6日火曜日

OSSのロードバランサ「ZEVENET Community Edition」にてTCP half-openのカスタムモニターを実装する

OSSのロードバランサである「ZEVENET」では、カスタムモニター (Farmguardian) を作成することができる。この作成方法は以下記事にした通りで、Linuxのncコマンドやnmapコマンドなどを利用したスクリプトを作成することで実装できる。

今回は、ZEVENETにてTCP half-openチェックと呼ばれる方法で負荷分散対象のサーバを監視するカスタムモニターを作成したので、実装方法を記載する。

環境

  • ESXi 6.7 Update 3
  • ZEVENET Community Edition 5.11

TCP half-openチェックとは

そもそも、TCP half-openチェックどのような監視手法かについて説明しよう。

ロードバランサで頻繁に使用されるモニターとして「TCP チェック」がある。TCPチェックでは、以下のTCPの3ウェイ・ハンドシェイクのステップを負荷分散対象のサーバに対して行い、問題なくコネクションの確立ができたのちに、FINパケットを送信してコネクションを切断する。

  1. 送信元→送信先へSYNパケット送信
  2. 送信先→送信元へSYN+ACKパケットを送信
  3. 送信元→送信先へACKパケット送信

しかし、TCPチェックには問題があり、TCPのコネクションを確立した後に切断処理をすることから、サーバ側のログにアクセス記録やエラーログが残ってしまう場合がある。

例えば、以下はPostfixにて構築したメールサーバに対するTCPチェックのログの例となる。ロードバランサ (IPアドレス : 192.168.33.25) からのconnectされたメッセージとdisconnectされたメッセージが確認できる。

Feb 18 06:34:50 64362e23f9d3 postfix/smtpd[158]: connect from unknown[192.168.33.25]
Feb 18 06:34:50 64362e23f9d3 postfix/smtpd[158]: lost connection after CONNECT from unknown[192.168.33.25]
Feb 18 06:34:50 64362e23f9d3 postfix/smtpd[158]: disconnect from unknown[192.168.33.25] commands=0/0
Feb 18 06:35:05 64362e23f9d3 postfix/smtpd[158]: connect from unknown[192.168.33.25]
Feb 18 06:35:05 64362e23f9d3 postfix/smtpd[158]: lost connection after CONNECT from unknown[192.168.33.25]
Feb 18 06:35:05 64362e23f9d3 postfix/smtpd[158]: disconnect from unknown[192.168.33.25] commands=0/0

上記ログは、無視すれば問題ないものであるが、不要なログが出力されることにより、ログの可読性の低下や、容量増加といった問題が発生する。

そこで、サーバ側にログを残さずTCPチェックを実現する方法として、「TCP half-openチェック」のカスタムモニターを実装することにした。TCP half-openチェックの動作について、再度3ウェイ・ハンドシェイクのステップを見ながら説明する。

  1. 送信元→送信先へSYNパケット送信
  2. 送信先→送信元へSYN+ACKパケットを送信
  3. 送信元→送信先へACKパケット送信

TCP half-openチェックでは、上記の2番目ステップのSYN+ACKパケットを受け取った時点でサーバのポートに問題がないものと判断する。3番目のステップでは、ACKパケットを送信するのではなくRSTパケットを送信することで、3ウェイ・ハンドシェイクを中断させ、コネクション確立前に通信を終了させる。

上記のように、送信元からSYN+ACKを受け取った状態 (half-open) で通信を終了させることで、サーバ側に不要なログが残ることを抑止できる。

ZENEVETでTCP half-openのカスタムモニターを作成する

1. カスタムモニター用のスクリプトを作成

TCP half-openチェックはnmap -sSを使うことで簡単に実行できる。以下はRHEL 7でnmapを実行した例となる。正常に接続できればSTATEopenで表示される。

▼接続成功例
# nmap -sS -p 25 192.168.33.23

Starting Nmap 6.40 ( http://nmap.org ) at 2021-02-20 10:28 JST
Nmap scan report for t3023cent.intrat.local (192.168.33.23)
Host is up (0.00036s latency).
PORT   STATE SERVICE
25/tcp open  smtp

接続に失敗する場合は、STATEclosedであったりfilteredになる。

▼接続失敗例
# nmap -sS -p 123 192.168.33.23

Starting Nmap 6.40 ( http://nmap.org ) at 2021-02-20 10:29 JST
Nmap scan report for t3023cent.intrat.local (192.168.33.23)
Host is up (0.00035s latency).
PORT    STATE  SERVICE
123/tcp closed ntp

Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

ZEVENETにおいてもnmapコマンドは使用できるのだが、単独ポートでスキャンを実行するとfilteredになるという不具合が存在する。

# nmap -sS -p 25 192.168.33.23
Starting Nmap 7.70 ( https://nmap.org ) at 2021-02-20 10:34 JST
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 192.168.33.23
Host is up (-0.20s latency).

PORT   STATE    SERVICE
25/tcp filtered smtp
MAC Address: 00:0C:29:1F:E0:DE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.44 seconds

スキャン対象のポートを単独ではなく、範囲指定を行うとなぜか成功し、openステータスとなる。

# nmap -sS -p 25-26 192.168.33.23
Starting Nmap 7.70 ( https://nmap.org ) at 2021-02-20 10:34 JST
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 192.168.33.23
Host is up (-0.15s latency).

PORT   STATE  SERVICE
25/tcp open   smtp
26/tcp closed rsftp
MAC Address: 00:0C:29:1F:E0:DE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.44 seconds

上記をふまえ、あまり綺麗な回避策とはいえないが、nmapを監視対象と監視対象ポート+1のポート範囲を指定して実行するようカスタムモニタースクリプトを作成することにする。

結果、カスタムモニタースクリプトcheck_tcp_half_openは以下内容となった。本スクリプトは/usr/lib/nagios/pluginsのディレクトリに配置しておく。

# cat /usr/lib/nagios/plugins/check_tcp_half_open
------------------------------
#!/bin/bash

HOST=$1
PORT=$2
NextPORT=$((${PORT}+1))

nmap -n -sS -p ${PORT}-${NextPORT} ${HOST} | grep open | grep ${PORT}
------------------------------

最後にスクリプトに実行権限を付けておく。

# chmod +x /usr/lib/nagios/plugins/check_tcp_half_open

2. モニター (Farmguardians) を作成

管理GUIにログインし、「Monitoring」→「Farmguardians」にて「CREATE FARMGUARDIAN」を選択する。

Farmguardianの設定は以下の通りとする。Commandの「HOST」はチェック対象のホストのIPアドレス (またはホスト名)、「PORT」はチェック対象のポート番号を示す変数となる。Intervalは負荷分散対象にチェックを行う間隔となるので、要件に応じて設定すればよい。

設定項目 設定値 (TCP half-openチェック)
Name check_tcp_half_open
Command check_tcp_half_open HOST PORT
Interval 15 seconds

3. Farmの設定を修正

「LSLB」→「Farms」で修正対象のFarmの「Edit」ボタンを選択する。

「Health Checks for backend」を先ほど作成したモニターに設定変更する。なお、ZEVENETではなぜか本設定を変更すると「Submit」ボタンを押すことなく即座に設定反映されてしまうので、設定時は注意が必要となる (反映された旨が、自動的に右下にメッセージとして表示される)。

4. 動作確認

設定変更後、「Monitoring」→「Farm Stats」を確認し、負荷分散対象がUpステータスになっていることを確認する。

また、負荷分散対象のサーバのログを確認し、負荷分散装置からのモニターによるアクセスログが出力されていないことを確認する。

▼Postfixのログの例

15秒間隔で出力された接続・切断のログが表示されなくなった。

Feb 21 06:44:05 64362e23f9d3 postfix/smtpd[203]: connect from unknown[192.168.33.25]
Feb 21 06:44:05 64362e23f9d3 postfix/smtpd[203]: lost connection after CONNECT from unknown[192.168.33.25]
Feb 21 06:44:05 64362e23f9d3 postfix/smtpd[203]: disconnect from unknown[192.168.33.25] commands=0/0
Feb 21 06:44:20 64362e23f9d3 postfix/smtpd[203]: connect from unknown[192.168.33.25]
Feb 21 06:44:20 64362e23f9d3 postfix/smtpd[203]: lost connection after CONNECT from unknown[192.168.33.25]
Feb 21 06:44:20 64362e23f9d3 postfix/smtpd[203]: disconnect from unknown[192.168.33.25] commands=0/0

▼Squidのログの例

15秒間隔で出力されたerror:transaction-end-before-headersのログが表示されなくなった。

1613857802.748      0 192.168.33.25 NONE/000 0 NONE error:transaction-end-before-headers - HIER_NONE/- -
1613857817.752      0 192.168.33.25 NONE/000 0 NONE error:transaction-end-before-headers - HIER_NONE/- -
1613857832.756      0 192.168.33.25 NONE/000 0 NONE error:transaction-end-before-headers - HIER_NONE/- -

参考

0 件のコメント:

コメントを投稿

人気の投稿