WindowsリモートデスクトップをLet's EncryptでSSL証明書を発行して使う


Windows 10 Proで使えるリモートデスクトップですが、デフォルトだとオレオレの自己証明書なので、接続時に証明書が検証できない旨の確認が出てきます。そのままでも利用できるのですが、なんか気持ち悪いのでLet's Encryptで証明書を発行して使いたいと思います。

ソースコード

cert-win-remote-desktop - GitHub

前提

  • acme.shがサポートするDNSプロバイダを使っている
  • WSLを利用している

サポートしているDNSプロバイダのリストから見つけてください。日本の場合はMyDNS.JPが便利だと思います。独自ドメインをほかのところで取得していたとしても、DNSの設定をMyDNS.JPですれば問題ないです。

あなたのDNSプロバイダがacme.shにサポートされていない場合は、他のACMEクライアントを使い、適宜読み替えてください。
もしあなたのDNSプロバイダが上記のリストになく、80番ポートを開放可能ならばHTTP-01チャレンジを利用できます(ただし80番ポートをずっと開けておく必要があります)。

2020年9月時点で、Certbot for WindowsはDNS-01チャレンジをサポートしていないので、WSLでCertbotを利用することにします。

手順

  1. acme.shをインストールして自動更新のためにcronを設定する
  2. 証明書を発行する
  3. pfx形式に証明書を変換する
  4. pfxをインポートしていくつかの設定をする
  5. 定期タスクの設定をする

1. acme.shをインストールして自動更新のためにcronを設定する

acme.shをWSLにインストールします。

$ wget -O -  https://get.acme.sh | sh

インストールが終わったらターミナルを再起動します。

WSLでcronをセット

もし既にWSLでcronを起動しているのなら、acme.shの起動時にcronがセットされているはずです。
まだの場合は次のステップで、Windowsの起動時に自動起動させることができます。

一、sudoした時にパスワードを聞かれなくなるように設定する

$ sudo visudo
<username> ALL=NOPASSWD: ALL # add this line (put your username in <username>)

二、下記の内容で新しいbatファイルを作る。

wsl /bin/bash -l -c "sudo service cron start"

三、作ったファイルをC:\Users\<win-user>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startupへ移動する

2. 証明書を発行する

DNS-01チャレンジを利用するには、DNSのIDとパスワードなどを環境変数に設定する必要があります。DNSプロバイダによって必要なものが違いますので、以下のページから確認してください。
dnsapi

MyDNS.JPの場合はこんな感じです。

$ export MYDNSJP_MasterID=MasterID
$ export MYDNSJP_Password=Password

そしたら、証明書を発行します。

$ acme.sh --issue --dns <your-dns-provider> -d <your-domain>

注意: 複数のドメインを指定しないでください。何故かわかりませんが、ここで複数ドメインを(example.comと*.example.comのように)指定して発行するとWindowsリモートデスクトップに接続できないエラーを吐きました。ワイルドカードはOKなので、-d *.example.comのようにすれば、使いまわししやすいでしょう。

acme.shが証明書の発行に成功すると、/home/<user>/.acme.sh/<your-domain>の中に証明書やキーが入っているはずです。

更新 2021-05-22
最近なぜかacme.shでの更新が上手くいかないので、上記でうまくいかない場合は以下の記事の方法を試してみることをおすすめします。
【ポート開放なし】MyDNS.JPのワイルドカード証明書を簡単に取得する【Docker】

3. pfx形式に証明書を変換する

WSL/convert_to_pfx.shを使って、cer(pem)形式の証明書をpfx形式に変換します。このスクリプトは証明書のSHA-1ハッシュ値を中身に持つfingerprint.txtも同時に生成します。使う前に変数domainfile_dirを書き換えてください。

$ cd ~/
$ git clone https://github.com/norocchi/cert-win-remote-desktop.git
$ cd ~/cert-win-remote-desktop/wsl
$ nano convert_to_pfx.sh
# edit $domain and $file_dir
domain='<your-domain>'
file_dir='/home/<user>/cert-win-remote-desktop/wsl'
$ ./convert_to_pfx.sh

4. pfxをインポートしていくつかの設定をする

ここからはPowerShellターミナルを使いますが、その前にpowershell/cert.ps1を編集して、書き換えてください。

$ cd ~/cert-win-remote-desktop/powershell
$ nano cert.ps1
# edit $CERTWSLPATH and $DOMAIN
$CERTWSLPATH = '\\wsl$\Ubuntu\home\<user>\cert-win-remote-desktop\wsl\keys'
$DOMAIN = '<your-domain>'

powershell/cert.ps1をWindows側に移します。エクスプローラーか、下記のようなPowerShellコマンドが使えます。

cp \\wsl$\Ubuntu\home\<user>\cert-win-remote-desktop\powershell\cert.ps1 C:\Users\<win-user>\path\to\your\folder
cd C:\Users\<win-user>\path\to\your\folder

移したら、コマンドを実行します。

./cert.ps1

mmc.exeを開いて、ファイル>スナップインの追加と削除>証明書>追加>コンピューターアカウント>ローカルコンピューター>完了 と進み、個人>証明書を開きます。
追加したドメイン名が見えたら、pfxの証明書の追加に成功しています。
念のため、その証明書を右クリックして、すべてのタスク>秘密キーの管理を選択して、NETWORK SERVICEというユーザ名があることも確認しておきましょう。

それから、レジストリエディタ(regedit)を開き、HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcpまで行き、SSLCertificateSHA1Hashを見つけてください。見えている16進の数字がfingerprint.txtの値と同じことが確認できれば、スクリプトは正常に完了しています!

参考: これらのスクリプトは、このページと同じことをやっています。

5. 定期タスクの設定をする

それでは、自動更新のためにタスクをスケジューリングしましょう。
WSLのcronで、こんな感じで新たに毎日実行するジョブを作ります。

0 0 * * * /path/to/cert-win-remote-desktop/wsl/convert_to_pfx.sh

それから、Windowsのタスクスケジューラを開き、新しい基本タスクを作成します。
注意点としては、

  • 毎日(convert_to_pfx実行後)
  • 最上位の特権で
  • ユーザーがログオンしているときのみ

実行することです。
プログラム/スクリプトはC:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe、引数はC:\Users\<win-user>\path\to\your\folder\cert.ps1としてください。

おわり!おつかれさまでした!

参考文献