Linuxめも

GoogleがやたらとSSL対応を勧めてくるんですよ。
やっぱり今後はSSL対応が必須になる時代が来そうです。

でもSSLって高いイメージがあるし、証明書の更新も面倒。
今の時代無料でできねーかなと調べてみたらなんかできそうな雰囲気。

Let's Encrypt で無料でSSLが導入できるようです。
証明書の発行・インストール・更新のプロセスを自動化できるようです。

制限があります。
https://letsencrypt.org/docs/rate-limits/

制限についての説明はこちらが詳しいです。
ありがとうございます。
http://qiita.com/sawanoboly/items/8e3c57aa2e30fc58c4e3

参考

クライアントソフトCertbotのインストール

# wget https://dl.eff.org/certbot-auto
# chmod 700 certbot-auto

ヘルプは以下で確認できます。

# ./certbot-auto --help

以下を実行すると、自動的にyumが実行され、必要なパッケージがインストールされます。

# ./certbot-auto

CentOS6.2ではyumにて python-pip-1.3.1-4.el6.noarch がダウンロードできずにエラーになってしまいました。

epelリポジトリを入れるとハマるみたいです。
設定を書き換えます。

# vi /etc/yum.repos.d/epel.repo
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch

baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch

CentOS5.5など古いOSは以下を参考にさせてもらえば利用が可能そうです。
https://clouds.tokyo/blog/linux_lets_cent5/

証明書の取得

同一サーバで別ドメインの証明書を取得する場合は、443ポートがすでに稼働しているために取得が完了できません。
そのため開始前にWEBサーバを止めておきます。
また、メールアドレスの入力と同意の設問はスキップされます。

# ./certbot-auto certonly
How would you like to authenticate with the ACME CA?
-------------------------------------------------------------------------------
1: Place files in webroot directory (webroot)
2: Spin up a temporary webserver (standalone)
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

2を入力
※certbot-autoのバージョンが上がって順番が入れ替わっている場合があるので注意が必要です。

Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):

メールアドレスを入力

-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel:

Aを入力

Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c' to cancel):

証明書を導入したいドメインをカンマもしくはスペース区切りで入力

成功すれば /etc/letsencrypt/archive/ドメイン/ 以下に4ファイル生成されます。

数字は更新するたびにインクリメントされるようです。
シンボリックリンクが以下に作成されるので、WEBサーバへの設定は以下を指定します。

Apache 2.4.8未満では公開鍵、中間証明書、秘密鍵を使用します。
それ以上やNginxではサーバ証明書と中間証明書が結合されたファイル、秘密鍵を使用します。

WEBサーバを停止せずに証明書を取得する

Webrootプラグインを使用することでWEBサーバを停止することなく証明書を取得することができます。
WEBサーバで公開している絶対パスを指定します。

# ./certbot-auto certonly --webroot -w /home/example.com/public_html -d example.com

Alias設定をしている場合は以下になります。

# ./certbot-auto certonly --webroot -w /home/example.com/public_html -d example.com -d www.example.com

複数のドメインで1つの証明書を取得する場合は以下になります。

# ./certbot-auto certonly --webroot -w /home/example.com/public_html -d example.com -w /home/other.example.com/public_html -d other.example.com

Webrootプラグインを使用すると、/home/example.com/public_html/.well-known/ 以下に一時的にファイルが生成され、認証が行われるようです。

Apacheの設定

ソースでインストールしている場合は --enable-ssl が有効になっているか確認。
以下の行があるか確認します。

LoadModule ssl_module modules/mod_ssl.so

以下をApacheの設定ファイルに追加します。

Apache 2.4.8未満の場合

Listen 443

<VirtualHost *:443>
    ServerName ドメイン:443
    DocumentRoot "/home/ドメイン/public_html"

    SSLEngine on
    SSLHonorCipherOrder on
    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    SSLProtocol -All +TLSv1 +TLSv1.1 +TLSv1.2
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5

    SSLCertificateFile /etc/letsencrypt/live/ドメイン/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/ドメイン/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/ドメイン/chain.pem

    <Directory "/home/ドメイン/public_html">
        Options FollowSymLinks
        AllowOverride ALL
        Require all granted
    </Directory>

    ErrorLog "logs/ssl_error_log"
    CustomLog "logs/ssl_access_log" combined
</VirtualHost>

Apache 2.4.8以降の場合

<VirtualHost *:443>
    ServerName ドメイン:443
    DocumentRoot "/home/ドメイン/public_html"

    SSLEngine on
    SSLHonorCipherOrder on
    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    SSLProtocol -All +TLSv1 +TLSv1.1 +TLSv1.2
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5

    SSLCertificateFile /etc/letsencrypt/live/ドメイン/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/ドメイン/privkey.pem

    <Directory "/home/ドメイン/public_html">
        Options FollowSymLinks
        AllowOverride ALL
        Require all granted
    </Directory>

    ErrorLog "logs/ssl_error_log"
    CustomLog "logs/ssl_access_log" combined
</VirtualHost>

httpへのアクセスをhttpsへ転送させる

.htaccessを設置してhttpにアクセスがあった場合はhttpsへそのまま転送させます。

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

自動更新の設定

crontabに登録しておくことで自動更新が可能です。

通常はこんな感じ

0 9 * * * /pathto/certbot-auto renew --post-hook "/etc/rc.d/init.d/httpd graceful"

毎月1日午前9時に一括更新する場合

0 9 1 * * /etc/rc.d/init.d/httpd stop && /pathto/certbot-auto renew --force-renew && /etc/rc.d/init.d/httpd start

毎月1日午前9時に特定のドメインを更新する場合

0 9 1 * * /etc/rc.d/init.d/httpd stop && /pathto/certbot-auto certonly --standalone -d example.com -d example2.com --renew-by-default && /etc/rc.d/init.d/httpd start

ログは /var/log/letsencrypt/letsencrypt.log に出力されています。

有効期限などの確認

# ./certbot-auto certificates
-------------------------------------------------------------------------------
Found the following certs:
  Certificate Name: example.com
    Domains: example.com
    Expiry Date: 2017-08-22 23:01:00+00:00 (VALID: 55 days)
    Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
-------------------------------------------------------------------------------

証明書の破棄

以下のコマンドで削除するドメインを聞かれるので、番号を選択します。

# ./certbot-auto delete -d sub.example.com
Which certificate(s) would you like to delete?

pip UnicodeDecodeError

エラーが出て実行できないようになりました。

# ./certbot-auto
Creating virtual environment...
Installing Python packages...
Had a problem while installing Python packages.

pip prints the following errors:
=====================================================
DEPRECATION: Python 2.6 is no longer supported by the Python core team, please upgrade your Python. A future version of pip will drop support for Python 2.6 Exception:
Traceback (most recent call last):
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/commands/install.py", line 272, in run
    with self._build_session(options) as session:
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/basecommand.py", line 72, in _build_session
    insecure_hosts=options.trusted_hosts,
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/download.py", line 329, in __init__
    self.headers["User-Agent"] = user_agent()
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/download.py", line 93, in user_agent
    from pip._vendor import distro
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/_vendor/distro.py", line 1050, in <module>
    _distro = LinuxDistribution()
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/_vendor/distro.py", line 594, in __init__
    if include_lsb else {}
  File "/opt/eff.org/certbot/venv/lib/python2.6/site-packages/pip/_vendor/distro.py", line 922, in _get_lsb_release_info
    stdout, stderr = stdout.decode('utf-8'), stderr.decode('utf-8')
  File "/opt/eff.org/certbot/venv/lib64/python2.6/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa5 in position 22: invalid start byte
=====================================================

Certbot has problem setting up the virtual environment.

We were not be able to guess the right solution from your pip output.

Consult https://certbot.eff.org/docs/install.html#problems-with-python-virtual-environment for possible solutions.
You may also find some support resources at https://certbot.eff.org/support/ .

サーバをEUC-JPで設定していることが原因のようです。

# cat /etc/sysconfig/i18n
LANG="ja_JP.eucJP"

これで動きました。

# LANG=ja_JP.UTF-8 ./certbot-auto

CentOS5で導入する

CentOS5ではPythonのバージョンが古いため動作しません。
互換クライアントがあるようなので、dehydratedを利用してみます。
https://community.letsencrypt.org/t/list-of-client-implementations/2103

dehydratedの設置

GitHubから dehydrated-master.zip をダウンロードします。

# mkdir /usr/local/etc/dehydrated

解凍したファイル類をアップします。

# cp /usr/local/etc/dehydrated/docs/examples/config /usr/local/etc/dehydrated/

証明書を取得するドメインを指定します。
複数の場合は半角スペースで区切ります。

# echo 'example.com' > /usr/local/etc/dehydrated/domains.txt

Apacheの設定

Apacheをパッケージでインストールしている場合

# mkdir /var/www/dehydrated
# mkdir -p /var/www/html/.well-known/acme-challenge
# vi /etc/httpd/conf/httpd.conf
<IfModule alias_module>
    Alias /.well-known/acme-challenge /var/www/dehydrated
</IfModule>

Apacheをソースからインストールしている場合

# mkdir /usr/local/apache2/htdocs/dehydrated
# mkdir -p /usr/local/apache2/htdocs/.well-known/acme-challenge
# vi /usr/local/apache2/conf/httpd.conf
<IfModule alias_module>
    Alias /.well-known/acme-challenge /usr/local/apache2/htdocs/dehydrated
</IfModule>

アカウントを登録

# /usr/local/etc/dehydrated/dehydrated --register --accept-terms

エラーが出た…

ERROR: Problem connecting to server (get for https://acme-v01.api.letsencrypt.org/directory; curl returned with 60)

ルート証明書が古いことが原因らしいので、新しい証明書を取得。

# wget https://curl.haxx.se/ca/cacert.pem
OpenSSL: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
SSL による接続が確立できません。
# wget --secure-protocol=SSLv2 https://curl.haxx.se/ca/cacert.pem
curl.haxx.se|151.101.90.49|:443 に接続しています... 接続しました。
SSL による接続が確立できません。

ダメだ…。
手元のパソコンでダウンロードしてからサーバへアップ。屈辱的…

# cd /etc/pki/tls/certs
# mv ca-bundle.crt ca-bundle.crt.org
# mv cacert.pem ca-bundle.crt
# /usr/local/etc/dehydrated/dehydrated --register --accept-terms

エラーが出た…

ERROR: Problem connecting to server (get for https://acme-v01.api.letsencrypt.org/directory; curl returned with 35)

opensslのバージョンが古いせいらしい。
↑これは違うみたい

# yum update openssl openssl-devel
Loaded plugins: fastestmirror
Determining fastest mirrors
YumRepo Error: All mirror URLs are not using ftp, http[s] or file.
 Eg. Invalid release/
removing mirrorlist with no valid mirrors: /var/cache/yum/addons/mirrorlist.txt
Error: Cannot find a valid baseurl for repo: addons
# vi CentOS-Base.repo

各mirrorlist, baseurlをコメントにし、それぞれ追加

[base]
baseurl=http://vault.centos.org/5.5/os/$basearch/

[updates]
baseurl=http://vault.centos.org/5.5/updates/$basearch/

[addons]
baseurl=http://vault.centos.org/5.5/addons/$basearch/

[extras]
baseurl=http://vault.centos.org/5.5/extras/$basearch/

[centosplus]
baseurl=http://vault.centos.org/5.5/centosplus/$basearch/

[contrib]
baseurl=http://vault.centos.org/5.5/contrib/$basearch/

curlが古いみたい
tarをダウンロード
https://curl.haxx.se/download.html

# tar xvzf curl-7.58.0.tar.gz
# cd curl-7.58.0
# ./configure --enable-libcurl-option
# make install

改めてアカウントを登録

# /usr/local/etc/dehydrated/dehydrated --register --accept-terms
# INFO: Using main config file /usr/local/etc/dehydrated/config
+ Generating account key...
+ Registering account key with ACME server...
+ Done!

これで /usr/local/etc/dehydrated/accounts 以下が生成される。

証明書の発行

# /usr/local/etc/dehydrated/dehydrated --config /usr/local/etc/dehydrated/config --cron
# INFO: Using main config file /usr/local/etc/dehydrated/config
Processing example.com
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting authorization for example.com...
 中略
 + Done!

sedのオプションエラーが出たけど /usr/local/etc/dehydrated/certs/ 以下に証明書が生成されます。

証明書をApacheに設定

上記の方法でApacheにSSLの設定をします。

   SSLCertificateFile /usr/local/etc/dehydrated/certs/example.com/fullchain.pem
   SSLCertificateKeyFile /usr/local/etc/dehydrated/certs/example.com/privkey.pem
   SSLCertificateChainFile /usr/local/etc/dehydrated/certs/example.com/chain.pem

証明書の更新

cronで取得時と同様にコマンド実行で可能なようです。

# /usr/local/etc/dehydrated/dehydrated --config /usr/local/etc/dehydrated/config --cron

有効期限の確認

$ openssl s_client -connect example.com:443 < /dev/null 2> /dev/null | openssl x509 -text | grep "Not After"
Not After : May 11 08:35:01 2018 GMT

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS