!!!概要 DeleGateでクライアント認証付きSSLリバースプロキシサーバ、いわゆるSSL-VPNの一種を構築してみます。 !!!要件 以下のような要件を考えてみます。 +社内ネットワークに設置されているWebベースのグループウェアサーバにインターネットから接続したい。 +インターネット上の通信は暗号化したい。 +接続できるユーザ(PC)を制限したい。 !!!シナリオ 要件1,2はSSLリバースプロキシを用いることで解決できます。想定するネットワークの構成は以下のような感じになります。クライアントPCからSSLリバースプロキシにHTTPSでアクセスすると、リバースプロキシはSSLを復号してHTTPでグループウェアサーバに中継します。 {{ref_image Delegate HTTPS Reverse Proxy.png}} 要件3は少々やっかいです。グループウェアにもユーザ認証機能はありますが、正当なユーザ以外にはグループウェアの認証画面にすら到達できないようにしたいということなのでリバースプロキシ側で何らかの認証を行わなければなりません。 ユーザが自宅や出張先からアクセスすることを想定しているので送信元IPアドレスでの制限は現実的ではありません。リバースプロキシでBASIC認証を行うという手段が考えられますが、リバースプロキシとグループウェアで2回ユーザ名とパスワードを入力することになるのでとても利便性がいいとは言えません。そこで、消去法的にSSLのクライアント認証を用いることにします。運用のコストはBASIC認証とたいして変わりませんが、ユーザからすればクライアント証明書をウェブブラウザにインポートしておくだけになるのでいくらかマシでしょう。 !!!OpenSSLによるCAの構築 OpenSSLによるCA(認証局)の構築・運用手順です。OpenSSLが/usr/local/ssl以下にインストールされているものとして話を進めます。 !!CAの作成 /usr/local/ssl/openssl.cnfを編集し、CAの場所を指定します。 ... [ CA_default ] dir = /usr/local/ssl/demoCA ... 付属のスクリプトでCAを作成します。必要に応じてCA.plを編集して認証局の証明書の有効期限などを変更してください。 # export OPENSSL=/usr/local/ssl/bin/openssl # /usr/local/ssl/misc/CA.pl -newca /usr/local/ssl/demoCA以下にCAが作成されます。 !!サーバ証明書の発行 リバースプロキシ用のサーバ証明書を発行します。 !openssl.cnfの変更 /usr/local/ssl/openssl.cnfを編集し、発行する証明書の種別をサーバ用にします。 ... [ usr_cert ] ... nsCertType = server ... !秘密鍵およびCSRの作成 秘密鍵とCSR(証明書署名要求)を作成します。CN(コモンネーム)はリバースプロキシサーバのFQDNを指定してください。 # openssl req -new -nodes -keyout server-key.pem -out server-req.pem !サーバ証明書の作成 サーバ証明書に署名します。 # openssl ca -out server-cert.pem -infiles server-req.pem !サーバ証明書に秘密鍵を含める 設定が少し簡略になるのでサーバ証明書に秘密鍵を含めておきます # cat server-key.pem >> server-cert.pem !!クライアント証明書の発行 ウェブブラウザにインポートするクライアント証明書を発行します。ルーチンワークになりますのでシェルスクリプトなどにしておくのがよいと思います。私はクライアント証明書の発行・更新・失効・配布、CRLの作成、サーバへのCRLの反映といった一連の流れをシェルスクリプトにして運用しています。 !openssl.cnfの変更 /usr/local/ssl/openssl.cnfを編集し、発行する証明書の種別をクライアント用にします。 ... [ usr_cert ] ... nsCertType = client, email ... !秘密鍵およびCSRの作成 秘密鍵とCSRを作成します。CNはユーザのメールアドレスにするのがよいと思います。 # openssl req -new -nodes -keyout client-key.pem -out client-req.pem !クライアント証明書の作成 クライアント証明書に署名します。 # openssl ca -out client-cert.pem -infiles client-req.pem !pkcs12形式に変換 IEやFirefoxなどのウェブブラウザにインポートできるように秘密鍵と証明書をpkcs12形式に変換します。CAのルート証明書もいっしょにまとめることにします。 PASSWORDはインポート時に尋ねられるパスワードです。秘密鍵のパスワードではありません。 # openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem \ -certfile /usr/local/ssl/demoCA/cacert.pem -out client-cert.p12 \ -password pass:PASSWORD できあがったclient-cert.p12とパスワードをユーザに配布し、ウェブブラウザにインポートしてもらいます。 !!クライアント証明書の失効 クライアント証明書を発行するだけではまだ仕事は半分です。ユーザの退職やPCの紛失などが起こったときにはクライアント証明書を失効させなければなりません。 証明書の失効は以下のコマンドで行います。 # openssl ca -revoke client-cert.pem 発行済みの証明書はdemoCA/newcerts以下に保存されていますのでそちらを指定してもかまいません。 このコマンドによりdemoCA/index.txtに失効の印が付けられます。もちろんこれだけではあいかわらずリバースプロキシにアクセスできてしまいますので、次項のCRL(証明書失効リスト)を使ってサーバに反映する必要があります。 !!CRLの作成 証明書を失効させた後、CRLを作成します。サーバへの反映を忘れないようにしてください。 # openssl ca -gencrl -out crl.pem -crldays 365 !!!DeleGateの設定 DeleGateの設定手順です。DGROOT=/usr/local/delegateであり、delegatedが/usr/local/delegate/binにインストールしてあるとして話を進めます。 !!SSL関連のファイル 上で作成したこれらのファイルを/usr/local/delegate/libに置きます。 *server-cert.pem: サーバ証明書+秘密鍵 *cacert.pem: CAのルート証明書 *crl.pem: CRL ここからがハマりポイントです。サーバの秘密鍵、サーバ証明書、CAのルート証明書はsslwayのオプションで指定できるのですがCRLのファイル名を指定する設定項目はありません。 CRLを読み込ませるには以下のようにハッシュ値をファイル名としたシンボリックリンクを作成しておく必要があります。拡張子も忘れずに付けてください。 ln -s cacert.pem `openssl x509 -in cacert.pem -hash -noout`.0 ln -s crl.pem `oepnssl crl -in crl.pem -hash -noout`.r0 !!設定ファイル /usr/local/delegate/conf/proxyhttps.confとして作成します。 # configuration for HTTPS Reverse Proxy # ポート設定 -P443 # サーバ種別 SERVER=http # SSL関連の設定(実際は1行) STLS='fcl,im20,sslway -cert server-cert.pem \ -CApath /usr/local/delegate/lib -Vrfy -crl_check' # 接続先サーバ MOUNT='/* http://groupwareserver/*' # アクセス許可 PERMIT='http:{groupwareserver:80}:*' # ログ出力設定 LOGDIR="${DGROOT}/log" LOGFILE="${LOGDIR}/${PORT}/log.[date+%d]" PROTOLOG="${LOGDIR}/${PORT}/${PROTO}.[date+%d]:%X %D" ERRORLOG="${LOGDIR}/${PORT}/errors.[date+%d]" TRACELOG="${LOGDIR}/${PORT}/ptrace.[date+%d]" EXPIRELOG="${LOGDIR}/${PORT}/expire.[date+%d]" # キャッシュファイル自動削除 CRON='0 3 * * * -expire 7' -Vrfyはクライアント証明書の提示・認証を強制するオプションで、-crl_checkはCRLを読み込むオプションです。-crl_checkオプションはマニュアルのどこを見ても書いてありませんがちゃんとあります。 !!起動スクリプト 起動スクリプトの例です。 #!/bin/sh # rc script for delegate DGROOT=/usr/local/delegate PROG=$DGROOT/bin/delegated CONF=$DGROOT/conf/proxyhttps.conf OWNER=delegate/delegate case "$1" in start) $PROG OWNER=$OWNER DGROOT=$DGROOT +=$CONF ;; stop) $PROG OWNER=$OWNER DGROOT=$DGROOT +=$CONF -Fkill ;; reload|refresh) $PROG OWNER=$OWNER DGROOT=$DGROOT +=$CONF -Fkill-hup ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 [start|stop|reload|restart]" exit 1 ;; esac exit 0 !!!リンク *[DeleGate Home Page|http://www.delegate.org/delegate/] - DeleGate公式サイト *[Resetting Linux ( and DeleGate + Postfix )|http://i-red.info/] - DeleGateドキュメント和訳 *[OpenSSL|http://www.openssl.org/] - OpenSSL公式サイト