この記事を作った動機

 私はプライベートネットワークにおいて、自分のためだけのサービスをhttpプロトコル経由で利用できるようにしているが、拡張機能とかの作成にあたり、httpsじゃないと不都合が生じるようになったことがきっかけで、https化に苦労することになり、もう嫌だということでこの記事を書くことになった。

 例えばyoutube上で動作する拡張機能が、自分だけのためのサービスが動いているhttpサーバをバックエンドとして使うことを考えると、http通信とhttps通信が一つのWebページを表示するために混在してしまうために、ブラウザ側で通信がブロックされたリ、騒がしいエラーが出てきてしまい、非常に不快な思いをすることになる。

前提としていること

 参考程度に前提条件とかも書いておく。

  • httpdを使っている。
  • opensslパッケージがインストール済み
  • すでにhttpdを使っていて、ブラウザでなんか表示できる状態にある。
  • あくまで個人用など、閉じられた環境において、https通信を実現したいと考えている。
  • このブログの様な、大っぴらに公開されているWebサイトには使えない手法であることを理解している。

https通信の実現方法

証明書を作る

 HTTPsを実現するために、mkcertコマンドを使って証明書を作成するが、どんな証明書が必要が一応自分の理解の範囲であり、間違っているかもしれないが、簡易的に書いておく。必要そうな証明書は以下のとおりである。

  • サーバ自体を証明する証明書
  • 各httpサーバとかのためにサービスごとに個別に用意される証明書

 この中で、サーバと通信するパソコンがインストールしているべき証明書は、「サーバ自体を証明する証明書」の証明書の公開鍵であり、「各httpサーバとかのためにサービスごとに個別に用意される証明書」の公開鍵ではない。

  1. mkcert コマンドのインストールを行う
     私は arch linux を使っているので、以下のようにパッケージマネージャを利用した。

    yay -S mkcert
    # たぶんリポジトリの分類がExtraにあるので、pacmanでもインストールできる
    # pacman -S mkcert
    
  2. mkcertの初期化を行う
     サーバ自体を証明する証明書の作成を行う。

    mkcert -install
    # 証明書が保存された場所を調べるためには以下のコマンドでできる。基本的にmkcert -installを実行したユーザのホームディレクトリのどこかにある。
    # mkcert -CAROOT
    # /home/username/.local/username/mkcert # 自分の環境だとこのような出力が得られる。
    
  3. httpサーバ用の証明書を作る
     次に以下のようにして、httpサーバが動いているドメイン名やIPアドレスを引数として、サービス用に証明書を作成する。この証明書は今回の場合であれば、httpdサーバの443番ポートを経由して、通信しているブラウザ等に送られることになる。

    # コマンドを実行したファイル内で証明書の公開鍵と秘密鍵ができてしまうため、一応作業用のフォルダを作っている。
    mkdir ./sslLocal/ 
    cd ./sslLocal
    
    # 各httpサーバとかのためにサービスごとに個別に用意される証明書を作成
    mkcert mydomain.name ipAddr # ドメイン名やIPアドレスなど複数指定できるらしいが、自分はとりあえずドメイン名だけにしてた。
    # あっ、mydomain.nameやipAddrとかは適宜読み替えてください
    

httpdが使う証明書を配置

 私は以下の様にして、httpサーバ用の証明書を配置した。

# 証明書を作成したディレクトリへ移動
cd ~/sslLocal/*

# ファイル内容を確認し、証明書の公開鍵と秘密鍵があることを確認する。
ls
-rw-------⠀username⠀1708⠀Nov  4 02:06:02⠀⠀mydomain.name-key.pem
-rw-r--r--⠀username⠀1452⠀Nov  4 02:06:02⠀⠀mydomain.name.pem

# httpdのconfigがあるところに、証明書を置いておく場所も作る。
sudo mkdir /etc/httpd/conf/ssl

# 署名書を作成したフォルダまで移動する。
cp ~/sslLocal/* /etc/httpd/conf/ssl/

httpdの設定

  1. ssl通信に必要なモジュールを読み込む。

    # このwebページを参考に、設定している。
    # https://wiki.archlinux.jp/index.php/Apache_HTTP_Server
    
    cd /etc/httpd/conf
    sudo nvim httpd.conf # 好きなエディタ使い管理者権限で開く
    
    ...
    # httpd.confの中にある、次の項目をコメントアウト
    LoadModule ssl_module modules/mod_ssl.so
    LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
    
    # この項目については、今回別途ssl通信用の設定を作成したため、利用しなかった。
    # Include conf/extra/httpd-ssl.conf
    ...
    
  2. SSL通信用にVirtualHostを作成
     SSL通信をするためには、httpdの設定を変更しておく必要がある。HTTPSのSSL通信には、確か443番が使われていて、その関係の設定である。
     本来は、/etc/httpd/conf/extra/httpd-ssl.conf 内に設定例があり、それを自分用に変更する形をとるのが、管理という観点からも王道っぽい。
     しかし、自分は個別にある、/etc/httpd/conf/extra/httpd-vhosts.confに設定してしまっている。この設定をしているときは、正直これがうまく動くかさえ分からなかったし手探りだたったので承知願います。。。

    cd /etc/httpd/conf/extra
    sudo nvim httpd-vhosts.conf
    
    # 多分最小構成はこんな感じだと思う
    ...
    <VirtualHost *:443>
        DocumentRoot "ssl通信をしたいWebページのフォルダまでのパス"
        ServerName mydomain.name
        SSLEngine on
        SSLCertificateFile "/etc/httpd/conf/ssl/mydomain.name.pem"
        SSLCertificateKeyFile "/etc/httpd/conf/ssl/mydomain.name-key.pem"
    </VirtualHost>
    ...
    
  3. httpdを再起動

    sudo systemctl restart httpd
    
    # 一応再起動後に設定の不備とかでコケて起動に失敗していないかなど確認する。failedとかエラーが出てなければたぶんOK
    systemctl status httpd
    

通信をしたいクライアントに、証明書をインストール

 ルート証明書として、「サーバ自体を証明する証明書」をインストールする。ここで間違えて、「各httpサーバとかのためにサービスごとに個別に用意される証明書」をインストールするとうまくいかず、泣く羽目になる。
 インストールの仕方はたぶんOS固有で説明するのはめんどくさいのでここでは割愛します。。。ポイントとしては、Windowsであれば、ルート証明書としてインストールすることと、信頼できない証明書の発行者ですみたいな警告が出てきたら、それは仕方なのないことなので、許可する方向で操作することくらいだと思う。うまくいけば、ブラウザを再起動すれば、証明書が認識され、晴れてhttpsが使えるはずである。

困ったこと

グダグダ駄文

 "https ローカル環境"などと調べるとmkcertコマンドを使って証明書を作ることで、SSL(TLS)によるHTTPs通信ができることが書いているWebページが見つかる。

 しかし、記事を書いている人がそんなの当たり前と思っているのか、私が思いっきり見落としているのかはわからないが、サービスごとの証明書を作ることは書いていて、rootCA.pemを通信を行うクライアントにインストールするということが抜けているWebページがあった。

 よくわからず間違いをして、httpサーバのために作成した証明書の公開鍵を間違ってインストールしてしましまい、いつまでたってもHTTPs通信が成功しないという辛いことになった。

 ちなみに後から、検索ワードを"mkcert 使い方"とか視点を変えた調べ方をすると、rootCA.pemのことが書いているサイトがあったので普通に盲点だった。調べ方が甘かったと言われたらその通りである。。。

 そもそも、結局のところ、私のSSL/TLS通信についての理解が浅いということでもあるとは思う。。。この記事に書いていることも間違えだらけだろうし、、、でもでも!、それでもとにかく動くようにできたので良しとしようw。

気になること

 なんか、このサイトとかに書いているように、プライベートネットワーク用に、実在のドメインを取得し、本物の証明書を使うという考え方もあるらしい。

 確かに、下手に証明書の設定をいじくりまわす必要のない点ではなんか理想的だけど、今のところ間に合っているので、このことは気になるがおいておくことにしている。

 後mkcertコマンドは、本番環境の様な厳密な環境では利用が推奨されていないらしい。ここら辺はよくわかっていないが、今回の件は、プライベートネットワークかつ個人用なので開発用だろうがとにかく良しとしておく。

 あっ、このブログはcertbotを使って、Let’s enscrypt経由でうまく通信できるようになっているはずなので、ある程度は大丈夫だと、、、信じたい。。。

参考にしたサイト