SSLとは、公開鍵方式(PKI)を利用した暗号化通信を指す。主にWEBなどで不特定多数の人との安全な通信をする場合に便利な仕組みである。(httpsと最後にsが付いているページは、このSSLが利用されてるページとなる)
PKI方式とは、暗号化する鍵と復号化する鍵が違うものであり、さらに言えば暗号化する鍵で復号化できない!のが特徴である。よって、暗号化鍵を持っている人だけが暗号化できることを生かしてWEBなどでセキュリティを確保する。
分かり易く言えば、AさんとBさんが暗号通信をする場合、AさんがBさんに暗号鍵を渡す。Bさんはその暗号鍵を使って、暗号化した文章をAさんに送る。ここでもし他の盗聴者が、最初の暗号鍵を盗聴し、さらにBさんの暗号化した文章を盗聴できても、Aさんが持つ復号鍵がないので暗号化された文章を解読できない。(逆にいえば、Bさんも一度暗号化した文章は一生見れないものになる)
その後、Aさんだけが自分で持っている復号鍵を使って復号できる。
ちなみに、暗号についての強度の解説はここを参照すると分かり易い。
SSLをWEBサーバで利用するには、OpenSSLを利用するのが一番適切である。そのためSSLを利用するにあたり、OpenSSLの導入を行う。またWEBサーバ導入に当たっては、IPA、安全なWEBサイトの作り方を一読してほしい。
1.0.2系統は2019年12月末にサポート終了したため、現在は1.1.1系統を利用すること。
# wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz # tar zxvf openssl-1.1.1d.tar.gz # cd openssl-1.1.1d # ./config shared ※OSの日付間違えてるとエラーになる。 # make # make install
1.1.0 以前では、これらのコマンドによって、/usr/local/ssl/bin にopensslなどのインストールが完了するが現在は /usr/local/bin にインストールされるようだ。そのため、PATHを/usr/local/ssl/bin 等に通していない場合を考慮し、opensslをコピーする。(下記のフォルダには旧バージョンの openssl コマンドがある場合があるので注意する)参考に初期値のインストール先を列記する。(主要なもののみ)
/usr/local/bin/openssl /usr/local/bin/c_rehash /usr/local/lib64/libcrypto.so.1.1 /usr/local/lib64/libcrypto.so <-- 上のlink /usr/local/lib64/libssl.so.1.1 /usr/local/lib64/libssl.so <--上のlink /usr/local/lib64/libcrypto.a /usr/local/lib64/libssl.a /usr/local/lib64/engines-1.1/capi.so /usr/local/lib64/engines-1.1/padlock.so /usr/local/ssl/misc/CA.pl /usr/local/ssl/misc/tsget.pl /usr/local/include/openssl/*.h <-- header files
# rm /usr/bin/openssl # ln -s /usr/local/bin/openssl /usr/bin/openssl
正しくインストールされたかバージョンを確認する。
# openssl version
# echo /usr/local/lib64 > /etc/ld.so.conf.d/ssl.conf # ldconfig
通常SSLを行うにあたり、サーバ証明書というものが必要になる。これはこのサーバがブラウザメーカーが保証する、証明書発行機関(VeriSign社等)から発行してもらう。法人や個人でもセキュリティを第三者に保証したい場合には、これら発行機関に費用を払って発行してもらう。
しかし、多数の第三者に対してサーバーの証明を行う必要がなく、アクセスする1人1人に、ブラウザに登録するための承認された証明書を登録させられる環境にある、のであれば、CA局(証明書発行機関)を自分で立ち上げて証明書を作成することもできる。
ここでは、発行機関に発注する環境にある人は、発行機関の人に聞けばよいので自分で証明局を立ち上げ、証明書の発行を行いたい人を対象とする。
注意!VirtualHostを利用している場合、サーバーのキーファイルをVirtualHost指定後しに、複数指定しても最初の指定だけが採用される。(記述は定義エラーとならない)これは、暗号化通信することによって、ドメイン名も暗号化されるため、apacheが通信を分類することができず、443などのポート番号か、IP番号でのみの識別しか出来ないためである。よって、複数のセキュアドなドメインをドメイン名で分類管理することは出来ない!
ここでは、/usr/local/ssl に、OpenSSLが導入されていることを前提とする。
補足:yum で、openssl をインストールしていると、CA操作の初期フォルダが、/etc/pki/CA に固定されるので注意。
# touch demoCA/index.txt <- 証明書作成の履歴保存用 # echo '1000' > demoCA/serial <- 証明書発行にあたって、連番の初期値を設定 # echo 'unique_subject = yes' > demoCA/index.txt.attr <- 発行シリアル番号の重複を許可しない。
OpenSSLコマンド用のコンフィグファイルを修正して自分の環境に合わせる。(修正すべき行だけ記載している)
# vi /usr/local/openssl.cnf [ CA_default ] default_days=3650 <- 元は 365 [ req ] default_bits = 2048 <- 元は1024 [ req_distinguished_name ] countryName_default = JP <- 自分の国コードを入力 stateOrProvinceName_default = Tokyo-to <- 自分の都道府県を入力 localityName_default = Taito-ku <- 自分の市町村区を入力 0.organizationName_default = My Company <- 自分の会社名を入力 [ usr_cert ] basicConstraints = CA:FALSE nsCertType = server [ policy_match ] countryName = supplied stateOrProvinceName = supplied organizationName = supplied
このコマンドは、バックスペースやDELキーが使えない!パンチミスには気をつけること
# cd /usr/local/ssl # /usr/local/ssl/misc/CA.sh -newca ... CA certificate filename (or enter to create) <- ここでは、return だけ押す。(新規の為) ... writing new private key to './demoCA/private/./cakey.pem' Enter PEM pass phrase: <- ここでは、CA局のパスフレーズを入れる。(4文字以上でないとエラーになる) ... Country Name (2 letter code) [XX]: <- ここでは大文字で JP と入力 State or Province Name (full name) []: <- ここでは県名を入力(例:Tokyo--to) Locality Name (eg, city) [Default City]: <- ここでは市町村区名を入力(例:Taito-ku) Organization Name (eg, company) [Default Company Ltd]: <- ここでは会社名を入力(例:My Company) Organizational Unit Name (eg, section) []: <- ここでは会社の部署名を入力(入力せず return でもOK) Common Name (eg, your name or your server's hostname) []: <- ここでは組織の通称を入力(※必須で重要な名前。例:mycompany.com) Email Address []: <- 連絡先メールアドレス ... A challenge password []: <- return のみ An optional company name []: <- return のみ
作業フォルダのdemoCA以下に、自己署名された以下のファイルが作成される。また demoCA/newcerts 以下にシリアル番号にファイル名が変更されたバックアップファイルが作成される。
careq.pem <- CA証明書署名要求ファイル(上記スクリプトの途中で作られた実質的には不要になったファイル) cacert.pem <- CA証明書のファイル private/cakey.pem <- CA秘密鍵のファイル
今後のサーバー証明書やクライアント証明書には、上記の下2つのファイルを利用する。
独自CAの場合で署名した証明書はブラウザなどから信用できない証明書を使っていると毎回ワーニングが発生する。そこでこの独自CAをWindowsに登録することで、ワーニングを表示させないようにすることができる。
# openssl x509 -inform pem -in demoCA/cacert.pem -outform der -out cacert.der
ここで作成されたDERファイルを、Windowsの、[コントロールパネル] -> [インターネットオプション] -> [コンテン ツ] -> [証明書] -> [信頼されたルート証明書] -> [インポート]で、作成されたDERを読み込ませることでインストールが完了する。その際に、証明書を配置する場所を確認してくるため「証明書をすべて次のストアに配置する」を選択し「信頼されたルート証明機関」を選ぶようにする。
上記で作成したDERファイルを、WEBサーバー上に設置しブラウザでアクセスすることでもインストールは可能。
AddType application/x-x509-ca-cert der <- Web serverの設定にmime-typeの追加
サーバー証明書などを作成の流れは、サーバー鍵を作成し、証明書要求ファイルを作成します。その後、CA局に証明書を発行してもらう流れとなります。
# openssl genrsa -des3 -out server.key 2048 # chmod 600 server.key
内容の確認
# openssl rsa -text -noout -in server.key
パスフレーズを消す
# openssl rsa -in server.key -out server.key
上記でコンフィグファイルが修正してあれば、タイプミスを減らせる。
# openssl req -new -key server.key -out server.csr -config /usr/local/ssl/openssl.cnf Country Name (2 letter code) [XX]: <- ここでは国コードを入力する(例:JP) State or Province Name (full name) []: <- ここには都道府県名を入力(例:Tokyo-to) Locality Name (eg, city) [Default City]: <- ここには市町村区名を入力(例:Taito-ku) Organization Name (eg, company) [Default Company Ltd]: <- ここには会社名を入力(例:My Company Corp.) Organizational Unit Name (eg, section) []: <- return のみ Common Name (eg, your name or your server's hostname) []: <- ここにはサーバー名(例:www.mycompany.com) A challenge password []: <- return のみ An optional company name []: <- return のみ
中身の確認
# openssl req -text -noout -in server.csr
ベリサインや、RapidSSLなどの正式なCA局に証明書を発行してもらうには、上記で作成したファイルを先方に送って、証明してもらうので、説明が不要なため、ここでは独自CA局による署名ー>証明書作成を説明する。
独自CAによる署名
# openssl ca -config /usr/local/ssl/openssl.cnf -out server.crt -infiles server.csr
2回ほど、y/n を聞いてくるが両方共 yes を選択。
<テスト起動>
# openvpn --config server.conf
<本番起動>
# openvpn --config server.conf
インターネット上における最も強固なセキュリティ方式の1つといえば、クライアント証明書方式がある。銀行などのオンラインバンキングにも利用される方式であり、利用者がアクセスする際にブラウザにクライアント証明書をインストールして、初めてアクセスが開始できる仕組みとなる。
最初はサーバー用の証明書を作成するような手順で進める。(Domain Name[CN]の部分はユーザーID(名前)を入力する。
# cd /usr/local/apache2 # openssl genrsa -des3 -out client.key 1024 # openssl rsa -in client.key -out client.key # openssl req -new -key client.key -out client.csr # openssl ca -in client.csr -out client.crt
ここまでは、サーバー証明書とほぼ同じ、CAをルートではなくサーバ証明書を参照して作成しているところが違うだけか。次に、クライアント証明書をPEM形式からPKCS12形式形式へ変換する。
# openssl pkcs12 -export -in client.crt -inkey client.key -certfile server.crt -out client.p12
# openssl pkcs12 -in client.p12 -nocerts -nodes -out client.key
※保存した client.key ファイルをそのままご使用できない場合は、"-----BEGIN RSA PRIVATE KEY-----”の行から“-----END RSA PRIVATE KEY-----"までの行をハイフンを含めてご使用する。
# openssl pkcs12 -in client.p12 -clcerts -nokeys -out server.crt
※保存した server.crt ファイルをそのままご使用できない場合は、"-----BEGIN CERTIFICATE-----”の行から“-----END CERTIFICATE-----"までの行をハイフンを含めてご使用する。
もしCA中間証明書が含まれていない場合には、空で出力される。
# openssl pkcs12 -in client.p12 -cacerts -nokeys -out middle.ca.crt
※証明書がそのまま利用できない場合には、上記サーバー証明書と同じ操作を行う。
# openssl rsa -in [パスワード付秘密鍵] -out [パスワード無し秘密鍵]
または
# ssh-keygen -p
httpd.confのファイルに以下の5行を追加する。(SSLの設定の所に一緒に)
SSLCACertificatePath /usr/local/ssl/CA SSLCACertificateFile /usr/local/ssl/CA/ca.crt SSLCARevocationFile /usr/local/ssl/CA/ca.crl SSLVerifyClient require SSLVerifyDepth 3
その後、失効ファイルを作成する。
# cd /usr/local/ssl/CA # openssl ca -gencrl -out ca.crl
設定した証明書などがどのように見えているか、以下のコマンドで確認できる。
# openssl s_client -connect www.gamvaro.com:443
秘密キーのハッシュがあっているか確認
# openssl rsa -in server.key -modulus -noout | openssl md5 # openssl x509 -in server.crt -modulus -noout | openssl md5
表示されるハッシュが同じであれば、同じ暗号キーで作成されている。