さくらのクラウド「シンプル監視」でVPCルータ配下のhttp/httpsを無料で監視する

さくらのクラウドで提供されている「[シンプル監視](http://cloud-news.sakura.ad.jp/simplemonitor/)」は

|料金|説明|
|----|----|
|無料|監視対象がIPv4アドレスかつ、弊社サービス(さくらのVPS、さくらの専用サーバ等)で提供するグローバルIPアドレスの場合|
|有料|・監視対象がFQDNの場合<br>・弊社提供以外のグローバルIPアドレスの場合|

ということで、IPv4でさくらインターネットのグローバルIPアドレスであれば無料で監視できます。
有料でも21円/月(2016年4月28日現在)なので、有料でも良い気はするのですが、 **さくらインターネットで借りているサーバ** なのに **有料** になっちゃうのは悲しかったので、無料で使える方法。

今回の構成は、[VPCルータ](http://cloud-news.sakura.ad.jp/vpc-router/)を利用して

* グローバルIPは1つ
* 配下にプロダクションサーバ、ステージングサーバの2台
* プロダクションサーバはVirtualHostで運用していてFQDNでリクエストする必要がある
* グローバルIPの80ポートおよび443ポートはプロダクションサーバに転送(VPCルータのNAT機能利用)
* Webサーバは[Apache HTTP Server](https://httpd.apache.org/)の2.4系

という構成になります。

# 目的

VPCルータ配下のプロダクションおよびステージングサーバのhttp/httpsの応答監視をしたい

# 越えなければならないハードル

有料でOKなら、越えるべきハードルは月額21円×監視項目数。

無料にしたいなら

* FQDNは有料になるのでIPv4でしか監視できない
* IPv4にするとVirtualHostが反応しない

をどうにか越えなければならない。

# そうだ！Proxyを使おう

というわけで、早速解決編。
mod_headersとmod_proxy、mod_sslが使える前提になりますが、以下の方法で監視できました。

```apache
<VirtualHost *>
	ServerName dummy.example.net
	DocumentRoot /var/www/html

	SetEnvIf Request_URI "^/_monitor/prod/" REQUEST_MONITOR_PROD=1
	SetEnvIf Request_URI "^/_monitor/stg/" REQUEST_MONITOR_STG=1

	RequestHeader set Host www.example.net env=REQUEST_MONITOR_PROD
	RequestHeader set Host stg.example.net env=REQUEST_MONITOR_STG

	ProxyRequests Off
	ProxyPreserveHost On

	SSLProxyEngine On
	#SSLProxyVerify none
	SSLProxyCheckPeerCN off
	SSLProxyCheckPeerName off
	#SSLProxyCheckPeerExpire off

	<Proxy *>
		Order deny,allow
		Deny from all
		Allow from 27.133.139.32/28
	</Proxy>

	ProxyPass /_monitor/prod/http/  http://192.0.2.32/
	ProxyPass /_monitor/prod/https/ https://192.0.2.32/
	ProxyPass /_monitor/stg/http/   http://192.0.2.33/
</VirtualHost>
```

この設定で、

|名称|監視用URL|
|----|--------|
|プロダクションサーバのHTTP|http\://(VPCルータのIPv4アドレス)/_monitor/prod/http/|
|プロダクションサーバのHTTPS|http\://(VPCルータのIPv4アドレス)/_monitor/prod/https/|
|ステージングサーバのHTTP|http\://(VPCルータのIPv4アドレス)/_monitor/stg/http/|

を監視できます。

# 上から順に設定の解説

## VirtualHost宣言
```apache
<VirtualHost *>
	ServerName dummy.example.net
	DocumentRoot /var/www/html
```

ここで登場する &lt;VirtualHost *&gt; は httpd.conf から設定ファイルをたどって最初に登場する &lt;VirtualHost&gt; にします。
ApacheはIPアドレスでアクセスされた場合など該当するVirtualHostが無い場合、一番最初に定義されているVirtualHostにアクセスします。

## SetEnvIfで条件によって環境変数を宣言
```apache
	SetEnvIf Request_URI "^/_monitor/prod/" REQUEST_MONITOR_PROD=1
	SetEnvIf Request_URI "^/_monitor/stg/" REQUEST_MONITOR_STG=1
```
Request_URI の値を使ってどのサーバを確認したいのかを判断します。

|conf|内容|
|----|----|
|SetEnvIf Request_URI "^/\_monitor/prod/" REQUEST_MONITOR_PROD=1|/\_monitor/prod/ で始まるリクエストURIの場合、REQUEST_MONITOR_PROD環境変数を作成して1を代入|
|SetEnvIf Request_URI "^/\_monitor/stg/" REQUEST_MONITOR_STG=1|/\_monitor/stg/ で始まるリクエストURIの場合REQUEST_MONITOR_STG環境変数を作成して1を代入|

## RequestHeaderでHostを指定
```apache
	RequestHeader set Host www.example.net env=REQUEST_MONITOR_PROD
	RequestHeader set Host stg.example.net env=REQUEST_MONITOR_STG
```
proxyでアクセスする際にVPCルータ配下のIPアドレスを直接指定してアクセスするため、環境変数が宣言されているかによってリクエストヘッダーの Host 値を設定します。

# Proxyの挙動を設定
```apache
	ProxyRequests Off
	ProxyPreserveHost On
```

ProxyRequest Off は、フォワードプロキシではなくリバースプロキシにするためOFFにします。
ProxyPreserveHost On は、RequestHeaderで設定したHostを引き継ぐためにONにします。

# Proxyをする際のSSL通信について設定
```apache
	SSLProxyEngine On
	#SSLProxyVerify none
	SSLProxyCheckPeerCN off
	SSLProxyCheckPeerName off
	#SSLProxyCheckPeerExpire off
```
ここ案外肝です。

SSLProxyEngine On が無いと
> AH01961: SSL Proxy requested for dummy.domain.tld:80 but not enabled [Hint: SSLProxyEngine]
AH00961: HTTPS: failed to enable ssl support for 192.0.2.32:443 (192.0.2.32)

と言う感じでエラーになります。

次に SSLProxyCheckPeerCN 、 SSLProxyCheckPeerName が無いと…
> (502)Unknown error 502: [client 203.0.113.1:63153] AH01084: pass request body failed to 192.0.2.32:443 (192.0.2.32)
[client 203.0.113.1:63153] AH00898: Error during SSL Handshake with remote server returned by /_monitor/https/
[client 203.0.113.1:63153] AH01097: pass request body failed to 192.0.2.32:443 (192.0.2.32) from 203.0.113.1 ()

というエラーになります。
理由はproxyでアクセスしているのはIPアドレスになるため証明書の検証でCommon Name(CN)が一致しないやSubject Alternative Name(SANs)でも一致しないというのをチェックしないようにします。

コメントアウトしている SSLProxyVerify と SSLProxyCheckPeerExpire は自己署名証明書(オレオレ証明書)の場合に付けると証明書自体の検証と有効期限切れのチェックを行わなくなります。
(今回は証明書の期限切れとか証明書そのものがおかしいというのも監視できるようになるのでコメントアウト)

# Proxyへの外部からのアクセスについて設定
```apache
	<Proxy *>
		Order deny,allow
		Deny from all
		Allow from 27.133.139.32/28
	</Proxy>
```
proxyすることができる接続元IPをシンプル監視のIPに限定します。

## Proxy接続先
```apache
	ProxyPass /_monitor/prod/http/  http://192.0.2.32/
	ProxyPass /_monitor/prod/https/ https://192.0.2.32/
	ProxyPass /_monitor/stg/http/   http://192.0.2.33/
```
各リクエストURLでのプロキシ先を定義します。

## VirtualHost設定終了
```apache
</VirtualHost>
```
設定終了です。

# 最後に・・・

これを使うと、Proxyを経由してさくらインターネット以外のIPも監視できちゃう気がしますが、やめておきましょう。

* サービス提供元のさくらインターネットに対して、なんか失礼である(今回はVPCルータ配下と言うことで見逃して…NGなら記事下げます m(_ _)m )
* 監視先の実際のサーバは何事も無くてもVPCルータまたはProxyを設定したサーバが落ちた場合、障害が検知される(→夜中不用意に起こされる危険が増える)

ということで、さくらインターネットのサービスに対して快く無料提供があるので、さくらのクラウドのリソースなどさくらインターネットのサービスだけで使いましょう。