Apache 2.2でTomcatバランシング実験

 article  Comments Off on Apache 2.2でTomcatバランシング実験
Dec 202006
 

Apache 2.2のproxyモジュールを使って複数のTomcatに負荷分散。
HTTPリクエストをReverse Proxyするのではなく、mod_jkを使って接続するわけでもなく、mod_proxy_ajpを使ったAJP13プロトコル接続で負荷分散してみようという試みです。

こんな感じでできるだろうかと、Solaris 10マシンで試してみました。
Apache 2.2とTomcat5はCSWパッケージ版を導入して、もうひとつのTomcat5を公式サイトのバイナリで導入し、ポート番号のみ変更して動かしてます。

ProxyRequests Off

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

<Location /jsp-examples>
  ProxyPass balancer://appservers/jsp-examples stickysession=JSESSIONID nofailover=Off
  Order Deny,Allow
  Allow from all
</Location>

<Proxy balancer://appservers/jsp-examples>
  BalancerMember ajp://127.0.0.1:8009
  BalancerMember ajp://127.0.0.1:8010
</Proxy>

<Location /servlets-examples>
  ProxyPass balancer://appservers/servlets-examples stickysession=JSESSIONID nofailover=Off
  Order Deny,Allow
  Allow from all
</Location>

<Proxy balancer://appservers/servlets-examples>
  BalancerMember ajp://127.0.0.1:8009
  BalancerMember ajp://127.0.0.1:8010
</Proxy>

<Location /balancer-manager>
  SetHandler balancer-manager
  Order Deny,Allow
  Deny  from all
  Allow from ::1 127.0.0.1 192.168.0.0/24
</Location>

とりあえずTomcatについてくるjsp-examplesとservlets-examplesは動作したのですが…

実は最初、

<Location /jsp-examples>
  ProxyPass balancer://appservers stickysession=JSESSIONID nofailover=Off
  Order Deny,Allow
  Allow from all
</Location>

<Proxy balancer://appservers>
  BalancerMember ajp://127.0.0.1:8009
  BalancerMember ajp://127.0.0.1:8010
</Proxy>

という定義を試していました。
ところが/jsp-examplesにアクセスするとTomcatのトップページが表示されてしまうので、前述のやりかたに変更したものの、正しいやりかたなのかよくわかりません。

ちなみに/balancer-managerの状態はこちら。

Apache balancer status

Worker URLのエントリ自体も重複していますし、ステータスがエラーになっているものもあります。やはり何かしらやりかたを間違えているような気がします… 😕

■2006-12-24追記
こんな感じでできました。ProxyPass先にURLパスまで指定する必要があったようです。

<Location /jsp-examples>
  ProxyPass balancer://appservers/jsp-examples stickysession=JSESSIONID nofailover=Off
  Order Deny,Allow
  Allow from all
</Location>

<Proxy balancer://appservers>
  BalancerMember ajp://127.0.0.1:8009
  BalancerMember ajp://127.0.0.1:8010
</Proxy>
Oct 062006
 

CentOS 3にはwebalizerが標準で含まれていて、インストールすると毎日自動でログ解析がおこなわれるようになってます(http://localhost/usage/でアクセス可能)。
しかしアクセスログをrotatelogsを使った日付つきファイル名に出力するようにしてしまうと、これが実行されなくなってしまいます。

単にwebalizerのcron処理が/var/log/httpd/access_logをファイル名固定で処理対象としているだけなので(/etc/webalizer.confで設定)、毎回前日分のaccess_logを入力するようにすれば解決できます。

CustomLog出力は、access_log.%Y-%m-%d形式で出力するよう、/etc/httpd/conf/httpd.confを変更したとします。

CustomLog "/usr/sbin/rotatelogs /var/log/httpd/access_log.%Y-%m-%d 86400" combined

/etc/cron.daily/00webalizerはログファイル名を引数で与えるように変更します。dateコマンドの–date yesterdayオプションを使って、昨日の日付を計算させています。

# cp -p /etc/cron.daily/00webalizer /etc/cron.daily/00webalizer.rpmorig
# vi /etc/cron.daily/00webalizer
# cat /etc/cron.daily/00webalizer
#!/bin/bash
# update access statistics for the web site

accesslog=/var/log/httpd/access_log.`date --date yesterday '+%Y-%m-%d'`

if [ -s ${accesslog} ] ; then
    /usr/bin/webalizer ${accesslog}
fi

exit 0

/etc/cron.*/配下のファイルは特定サフィックスだと実行対象から除外されますので(/usr/sbin/run-partsスクリプト参照)、.rpmorigというサフィックスでバックアップしてます。

■2006-12-20追記
これだけではwebalizer処理が実行される4:00から9:00頃までのログが抜け落ちることがわかりました。
前述のrotatelogs指定ではUTC(つまり日本時刻の9:00)にログが切り替わってしまうためです。
回避するためには日本時刻の0:00に切り替わるようにUTCオフセットを指定するなどの対応が必要になります。

CustomLog "/usr/sbin/rotatelogs /var/log/httpd/access_log.%Y-%m-%d 86400 540" combined

ログファイルをマスク指定で全件入力させちゃう方法もありますが…

cat /var/log/httpd/access_log.????-??-?? | /usr/bin/webalizer

ログファイル数次第では、とてつもない処理量になる可能性がありますので注意しましょう。

Oct 132005
 

OpenSSLのSSL 2.0実装に関する脆弱性が公表されました。
Potential SSL 2.0 Rollback (CAN-2005-2969)

影響等については発見者である大岩氏のコメントで説明されています。

FirefoxやIEは既にSSLv2を無効にしていたのですが、Apacheは気にかけてなかったので、これを機会に無効にしてみました。

SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:!SSLv2:+EXP
SSLProtocol ALL -SSLv2

SSLCipherSuiteはSSLv2前の!で、SSLProtocolはSSLv2前のの部分で無効にすることになるはずなのですが、どっちが優先なのでしょう…

この状態でopensslコマンドを使いSSLv2で接続してもhandshakeで失敗するようになります。

$ openssl s_client -connect localhost:443 -ssl2
CONNECTED(00000003)
23355:error:1407F0E5:SSL routines:SSL2_WRITE:ssl handshake failure:s2_pkt.c:428:

$

SSLCipherSuiteで!SSLv2しただけだと

2580:error:1406D0B8:SSL routines:GET_SERVER_HELLO:no cipher list:s2_clnt.c:468:

となりましたので、両方書いた場合はSSLProtocol指定の方が優先されるようです。

Sep 012005
 

WordPressでのPermlinks設定は、デフォルトでPost slugをURLに埋め込むようになってます。
/wordpress/2005/08/31/%postname% のような形式です。

Post slugはタイトルがそのまま使われるのですが、日本語記事ではPost slugをasciiで書き直してやらないと、Post slugでのPermlinksが使えません。

ポストする度に書き換えるのが面倒という人は、私もそうなのですけどPost ID(連番ですね)でPermlinksを設定しちゃうと思います。
/wordpress/archives/%post_id%な形式ですね。

Permlinksはmod_rewriteでのURL書き換えによって実現されているのですが、ここで何かできれば日本語のPost slugでも何とかなるのかなぁ、と漠然と考えてました。

そんな中、mod_rewriteで文字コードを変換するパッチがApache 技術者メーリングリストにポストされてました。

もしかしたら、これを使うと日本語Post slugが使えるようになるかも知れないなぁ、とちょっと期待してます。

これを書いているXREAでは残念ながらテストできないので、別に環境を用意して試そうと思います。あ、既に試された方がいたら是非コメントください 😉

mod_auth_ldap

 article  Comments Off on mod_auth_ldap
Aug 282005
 

モジュールの有効化

Apache 2系列であれば、大抵組み込まれていると思います。

LoadModule ldap_module modules/mod_ldap.so
LoadModule auth_ldap_module modules/mod_auth_ldap.so

認証設定

Active DirectoryをLDAPサーバとして使う場合の設定例をいくつか掲載します。

Active Directoryでは、標準的な構成の場合認証前に権限のあるユーザで接続をしなければいけません。 そのユーザ名とパスワードをAuthLDAPBindDN、AuthLDAPBindPasswordで指定します。

  • ここではAdministratorを指定していますが、LDAPサーバとの間で認証情報が垂れ流しになりますので、お勧めしません。
  • Active Directoryに接続だけできるユーザ1を用意するのがよいでしょう。おそらくAuthenticated Usersであればよいと思われますが未確認です。

基本的な設定例

<Location /ldap-status>
  SetHandler ldap-status
  AuthType Basic
  AuthName "Members Only"
  AuthLDAPEnabled on
  AuthLDAPURL "ldap://dc1/CN=Users,DC=example,DC=jp?sAMAccountName?one"
  AuthLDAPBindDN "CN=Administrator,CN=Users,DC=example,dc=jp"
  AuthLDAPBindPassword ****************
  require valid-user
</Location>

認証ダイアログに入力するユーザ名にはsAMAccountname(NetBIOSユーザ名)を使っていますが、cn等のほかの値をを使うことも可能です。

所属グループを制限する例

AuthLDAPURLのフィルタ条件を指定することで、所属グループ(memberOf)でユーザを制限することができます。

AuthLDAPURL "ldap://dc1/CN=Users,DC=example,DC=jp?sAMAccountName?one(memberOf=CN=Sales,CN=Users,DC=example,DC=jp)"

LDAPサーバの複数指定

AuthLDAPURLのldap://~/には空白で区切ってサーバを複数記述できます。

AuthLDAPURL "ldap://dc1 dc2/CN=Users,DC=example,DC=jp?sAMAccountName?one"

mod_auth_kerb

 article  Comments Off on mod_auth_kerb
Aug 282005
 

環境

  • Fedora Core 1
  • Apache 2.0.49 (Fedora Core 1のhttpd-2.0.49-1.1パッケージ)

mod_auth_kerbモジュール導入

モジュールはFecora Core 2用のsrc.rpmをダウンロードしてビルド、インストールしました。

# wget -N ftp://rpmfind.net/linux/fedora/core/development/SRPMS/mod_auth_kerb-5.0-1.src.rpm
# rpmbuild --rebuild mod_auth_kerb-5.0-1.src.rpm
# rpm -Uvh /usr/src/redhat/RPMS/i386/mod_auth_kerb-5.0.1.i386.rpm

Kerberos設定

/etc/krb5.confを設定します。今回は

  • レルムはEXAMPLE.JP
  • KDCはWindows 2000のドメインコントローラで、ホスト名はkdc.example.jp

であると仮定します。

[libdefaults]
 default_realm = EXAMPLE.JP
 default_tkt_enctypes = des-cbc-md5
 default_tgs_enctypes = des-cbc-md5

[realms]
 EXAMPLE.JP = {
  kdc = kdc.example.jp:88
  default_domain = example.jp
 }

[domain_realm]
 .example.jp = EXAMPLE.JP
 example.jp = EXAMPLE.JP

単純なBasic認証

単純にBasic認証をかける場合は、以下の設定ですみます。

AuthType Kerberos
AuthName "Kerberos authentication"
KrbAuthRealms EXAMPLE.JP
KrbVerifyKDC off
require valid-user

この認証をかけたドキュメントにアクセスすると、HTTP Basic認証のダイアログが表示され、入力したIDとパスワードは裏でKDCの認証を受けます。

Active DirectoryでのSSPI認証

更にクライアントPCがActive Directoryのドメイン(今回の例の場合、EXAMPLE.JP)に参加している場合は、「統合Windows認証」というものを使うことができます。 このためにはKDCであるドメインコントローラでKerbeorsのKeytabを作成し、コンピュータアカウントに関連付ける必要があります。

  1. コンピュータアカウントを作成する
  2. 普通に管理ツールを使って、コンピュータアカウントを作成します。今回はwww.example.jpと仮定して、コンピュータアカウントもwwwで作成しておきます。

  3. Support Toolsのktpassコマンドでキーを作成し、コンピュータアカウントと関連付ける
  4. C:\Program Files\Support Tools>ktpass /princ HTTP/www.example.jp@EXAMPLE.JP /mapuser www$ /pass ************ /out www.keytab
    Successfully mapped HTTP/www.example.jp to www$.
    Key created.
    Output keytab to www.keytab:
     
    Keytab version: 0x502
    keysize 70 HTTP/www.example.jp@EXAMPLE.JP ptype 1 (KRB5_NT_PRINCIPAL) vno 1 etype 0x1 (DES-CBC-CRC) keylength 8 (0xfd7c89d0da1a0bb5)
    Account has been set for DES-only encryption.
     
    C:\Program Files\Support Tools>
    

    プリンシパルのサービス名はデフォルトのHTTPとしていますが、これはmod_auth_kerbのKrbServiceNameで変更することができます。

  5. 作成したキーをApacheサーバ上に移し、ディレクティブを設定する
  6. キーを/etc/httpd/conf/www.keytabとして配置し、Apacheのユーザに読み込み許可を与えます(SSLキーと違い、rootに許可するだけではダメでした)。

    AuthType Kerberos
    AuthName "Kerberos authentication"
    KrbAuthRealms EXAMPLE.JP
    KrbVerifyKDC on
    Krb5KeyTab /etc/httpd/conf/www.keytab
    require valid-user
    

これで、「統合Windows認証を使用する」設定になっている(IEデフォルトのようです)Internet Explorerからアクセスすると、認証ダイアログなしにアクセスされるようになります。

Jul 132005
 

あるマシンをリプレースしたところ、Apache 2.0.54のHTTPDプロセスが99%のCPU使用率となる事象に遭遇。
ハードウェアリプレースにともない、HyperThreadingなCPUになったので

にもあるようにHyperThreadingが原因かと思われたのですが、Non SMPなカーネルで起動しても改善しません。

LDAP認証を適用しはじめたこともあるので、

の情報をもとにパッチを適用してみたところ、1つのHTTPDプロセスのCPU使用率は99.9%から40%程度に下がりましたが、まだまだ正常とはいいがたく根本的な解決に至っていません。
さて、次は何を調べましょうか…

Mar 312005
 

ZABBIXを使って監視を始めてみましたが、HTTPポートの稼動監視がうまく動いておらず、”WEB server is down on …”になってしまいます。
監視項目であるnet[listen_80]でgrepしてみると、src/zabbix_agent/sysinfo.cで/proc/net/tcpを読みだしてステータスチェックしていることがわかります。
ステータスに
"0050 00000000:0000 0A"
のような値がが含まれていればいいはずなのですが、目でみても確かにそんな行は確かにありません。
netstatで確認してみると80をListenしているのは:::80のIPv6アドレスだけ!
netstatレベルではIPv4での80をチェックしていることになるので、確かに非稼動扱いでおかしくありません(IPv6での同様の情報は/proc/net/tcp6から取らないといけない)。
試しにApacheの設定で

Listen :::80
Listen 0.0.0.0:80

としてみましたが、これでは起動時に

 * Starting apache2...
(48)Address already in use: make_sock: could not bind to address [::]:80
no listening sockets available, shutting down
Unable to open logs

というエラーになってしまいます。
Apacheのマニュアルによれば上の指定をLinuxでやるにはconfigureオプション変えないといけないらしいです。今まではNetBSDを使うことが多かったので全然気がつきませんでした。

結局ZABBIXでHTTPポート監視をおこなうのはあきらめました。他のプロセス監視やSimple Checkでのポート接続チェックで代用できると思われますので。

Oct 162004
 

LDAPを使った統合認証を目指すべく、まずはIMAPサーバの認証をLDAPに格納したパスワードで実施するようにしてみました。
関連するパッケージはcourier-authldap、courier-imap、slapd (OpenLDAP)になる。

  1. ユーザのuserPassword読み取り用LDAPアカウントを作成する
  2. slapdのACLで(/etc/ldap/slapd.conf)、用意したLDAPアカウントにuserPasswordのread権限を付与する
  3. LDAPアカウント構造にあわせて/etc/courier/authldaprcを設定
    • LDAP_BINDDNとLDAP_BINDPWに、userPassword読み取り用LDAPアカウントを設定
    • LDAP_CLEARPWにuserPasswordを指定(ファイルのコメントにあるとおり、クリアパスワードにすることでCRAM-MD5認証ができるようになる)
  4. 利用ユーザのuserPasswordをクリアテキストで再設定する

これでCourier-IMAP、OpenLDAP連携によるCRAM-MD5認証がおこなえるようになります。
LDAPデータベースにクリアパスワードを格納するのは賛否両論ありそうですが、わたしは

  • SSLやるにはサーバの能力が厳しめなのでCRAM-MD5認証にしたかった
  • でもLDAPへの認証統合化も目指したい

といった動機からクリアパスワード格納を選択しました。

なお、こちらのroughtrade.net / dovecotでは、Dovecot用のCRAM-MD5認証パッチを配布しているようです。
この場合もLDAPにクリアパスワードを格納すれば、LDAPバックエンドでCRAM-MD5認証が可能になるのかな 😕