satakesatakeの日記

2016-03-11

Apacheで行う、特定のURLのみを除き、リバースプロキシさせる設定のレシピ

| 14:06

https://example.com/admin

だけはリバースプロキシさせずに、

https://example.com/

とか、それ以外のものはリバースプロキシさせるようなレシピ

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteRule ^/admin - [L]
  RewriteRule ^/(.*) http://example.com:5001/$1 [P,L,QSA]
  ProxyPassReverse /  http://example.com:5001/
</IfModule>

mod_rewriteのPオプションはProxyPassディレクティブと同じ機能を持つ。

…のだが、ProxyPassReverseを直後に書いてやらないとダメらしい。

参考→http://blog.livedoor.jp/techblog/archives/65151527.html

応用

それの応用で、特定のIPアドレス以外はメンテナンス画面を見せるレシピ。RewriteRule の L オプションの活用だ。

#1~3がそれぞれ、if文のブロックのような感覚。

RewriteRule は L オプションを付けると、ルールに合致した際にそこで処理を停める。それ以外は次の行に処理を移す。If文で書ければいいのになあ。

    ErrorDocument 503 /html/maintenance.html

    <IfModule mod_rewrite.c>
      RewriteEngine On

      # 1
      RewriteRule ^/admin - [L]

      # 2
      RewriteCond %{REQUEST_URI} !=/html/maintenance.html
      RewriteCond %{REMOTE_ADDR} !=192.168.0.1
      RewriteRule ^.*$ - [R=503,L]

      # 3
      RewriteRule ^/(.*) http://example.com:5001/$1 [P,L,QSA]
      ProxyPassReverse /  http://example.com:5001/
    </IfModule>

2012-01-05

apacheのerror_logで文字化け

| 10:04

文字化けというよりもセキュリティ上の理由で、UTF8文字列をクォートするらしい。

こいつをperlワンライナーで無理やり表示するぞ。

$ tail -f /var/log/httpd/error_log | perl -nle 's/\?\\([a-f\d]{3})/chr($1)/ieg;s/\\x([a-f\d]{2})/pack("C", hex($1))/ieg;print $_;'

ここからパクリました→http://ucwd.jp/blog/358

$ tail -f /var/log/httpd/error_log | perl -nle 's/\\x(..)/pack("C",hex($1))/eg;print $_'

これもいいなあ→http://kohju.justplayer.com/Tips_unixtool_apache_error_log.html

2010-03-19

SSLの更新

| 15:35

弊社の場合、一年に一度やってくる風物詩だ。

今日はApacheのディレクティブ、SSLCertificateKeyFileの話。SSLCertificateFileとも関連する重要なディレクティブなのだが、これが要らない場合がある。SSLCertificateFileの秘密鍵がSSLCertificateKeyFileにあたるのだが、要らない場合がありえるのだろうか?

実はありえた。

SSLCertificateFileで設定したファイルに秘密鍵が含まれていた場合だ。

つまり、下記のような形になっていた場合に、SSLCertificateKeyFileは省略可能。

-----BEGIN RSA PRIVATE KEY-----
(中略)
-----END RSA PRIVATE KEY-----

-----BEGIN CERTIFICATE-----
(中略)
-----END CERTIFICATE-----

秘密鍵が含まれていないときにはApache再起動時にエラーとなる。

いやーいままで知らなかった。つーか、ちゃんと書いてあるし→http://httpd.apache.org/docs/2.0/ja/mod/mod_ssl.html#sslcertificatekeyfile

ベリサインのヘルプ見ながらやると、指示通りにやっちゃうからしょうがない面もある→https://www.verisign.co.jp/ssl/help/install/iapache_renew.html

2008-05-08

Apacheの再起動のこと

| 11:09

# /etc/init.d/httpd graceful

比較的、メジャーなコマンド。

プロセスは USR1 あるいは graceful シグナルを受け取ると、子プロセスに現在のリクエストの処理の後に終了する (あるいは何もしていなければすぐに終了する) ように助言します。 親プロセスは設定ファイルを再読込して、ログファイルを開き直します。 子プロセスが徐々になくなるに従って、 新しい世代の設定による子プロセスに置き換えていきます。 そして、これらが新たなリクエストに即座に応答し始めます。

停止と再起動 - Apache HTTP サーバ: 緩やかな再起動

gracefulは、VeriSignなどで認証された証明書を設定し、Apache再起動時にSSLパスワードが要求されるシステムにも効果的だ。パスワードを要求せずに緩やかに設定の再読み込みをしてくれる。

  • 2010.3.19 追記
    • ただし、証明書を更新した際にgracefulを行うと、再起動に失敗するようだ。その場合は潔く、restartとパスワードを入力!

2008-05-07

Pleskの悪夢。~またもやバッドノウハウ

| 15:14

Pleskの管理画面上で、サブドメインの設定などして、景気よく、けってーい、とかすると、

/var/www/vhosts/example.com/conf/httpd.include

を書き換えてくれる。※example.comはあくまでも例。各々のドメインに読みかえるべし。

こまっちゃうのが、手動でけっこう重要な設定をhttpd.includeに書き、ウェブサーバを稼動させていたときだ。重要な設定が上書きされ、亡きものとなる。

対策としては、上書きされるhttpd.includeに重要な設定を書かず、設定ファイルを外出ししておくこと。

四苦八苦して、思い出し、設定を再現するのだが、perlCGIがうまく動かないことがある。なぜだか、Internal Server Errorが出るようになったりするのだ。

再現した設定はこのような感じ。

<VirtualHost 192.168.0.1:443>
        ServerName   example.com:443
        ServerAlias  www.example.com
        UseCanonicalName Off
        SuexecUserGroup example psacln
        ServerAdmin  "root@example.com"
        DocumentRoot /var/www/vhosts/example.com/httpsdocs
        CustomLog  /var/www/vhosts/example.com/statistics/logs/access_log plesklog
        ErrorLog   /var/www/vhosts/example.com/statistics/logs/error_log
        ScriptAlias /cgi-bin/ "/var/www/vhosts/example.com/httpsdocs/cgi-bin/"
        AddHandler cgi-script .cgi

        <IfModule mod_ssl.c>
            SSLEngine on
            SSLVerifyClient none
            SSLCertificateFile "/var/www/vhosts/example.com/pem/cert.pem"
            SSLCertificateKeyFile "/var/www/vhosts/example.com/pem/key.pem"
            SSLCACertificateFile "/var/www/vhosts/example.com/pem/inca.pem"
        </IfModule>

        <Directory /var/www/vhosts/example.com/httpsdocs>
            SSLRequireSSL
            AllowOverride None
            Options ExecCGI
            Order allow,deny
            Allow from all
        </Directory>

        Alias /frontage/ "/usr/local/example.com/perl/2008/www/"
        <Directory "/usr/local/example.com/perl/2008/www/">
            SSLRequireSSL
            AllowOverride None
            Options ExecCGI
            Order allow,deny
            Allow from all
            AddHandler cgi-script .cgi
        </Directory>
</VirtualHost>

ちなみに、apacheのerror.logにはこのような形でエラーが記録が残されていた。

[Wed May 07 14:50:38 2008] [error] [client 192.168.0.2] Premature end of script headers: index.cgi

改行コードがLFでない場合にこのエラーが発生することが多いが、問題はそうでないときだ。Premature end of script headersは、あいまいなエラーで原因特定が難しい。そんなときに疑ってみるべきなのがSUEXECのエラーだ。

suexec_logにはこの様な記録が残されていた。

[2008-05-07 14:50:38]: uid: (10001/example) gid: (10001/10001) cmd: index.cgi
[2008-05-07 14:50:38]: command not in docroot (/usr/local/example.com/index.cgi)

これによれば、docrootでないため、CGIが起動できないとされている。

先の再現した設定のどこが問題なのだろうか。結論を先に言ってしまうと、下記設定が悪さをしている。正確には「悪さ」ではなく、SUEXECの使い方の問題だ。

        SuexecUserGroup example psacln

SuexecUserGroupを設定すると、Apacheはユーザをexample、グループをpsaclnにて、CGIをSUEXECを使用して動作させようとする。SUEXECをOFFにしたい場合、このSuexecUserGroupの行を削除(もしくはコメントアウト)してしまえばオッケーだ。

たったの一行で、動作がガラリと変わる。あなおそろしや。