Termuxネイティブ環境でacme-nginxを使いワイルドカード証明書を自動取得!

前回、別記事にすると言っていた件です。

Termux環境で動作するLet’s Encryptのワイルドカードドメインに対応した自動化ツールを探せ!

https://hack.gpl.jp/2020/09/11/wildcard-domain-acme/

今日のネタは、Termuxネイティブ環境で acme-nginx というPythonで、作られた自動化ツールで Let’s Encrypt のワイルドカードドメイン証明書を取得します。さぁうまく出来るでしょうか? ちなみに、ワイルドカード証明書とは、以下のようなことを言います。

ワイルドカード証明書とは

「*.example.jp」のように、コモンネームの一番左のラベルにアスタリスク(*)を指定したサーバー証明書です。

ワイルドカード証明書は「www.example.jp」「login.example.jp」「member.example.jp」のように、アスタリスクと同一階層のサブドメインのみが異なるすべてのサーバーにインストールできます。
また、JPRSの提供するワイルドカード証明書なら、「*.example.jp」の証明書を「example.jp」のようにアスタリスク(*)を除いたホスト名のサーバーでも利用できます。

https://jprs.jp/pubcert/about/wildcard/

では作ってみましょう。acme-nginx はもう入れてあるものとします。DNSはデジタルオーシャンに変更して、APIトークンを取得してあります。

ステップ1

適当な証明証を入れておくディレクトリを作っておきます。例では、example.jp というドメインで説明しています。

cd
mkdir -p ssl/example.jp
cd ssl/example.jp

ステップ2

アカウントキーと、ドメインキーを作成します。

openssl genrsa 4096 > account.key
openssl genrsa 4096 > example.jp.key

ステップ3

digitaloceanのトークンを環境変数に入れておきます。

export API_TOKEN=digitaloceanのトークン

ステップ4

証明書を発行します。WEBの認証はないので便利ですね。パスは、Termuxxの環境変数 $PREFIX に置き換えたほうが見やすいかもですね。

acme-nginx \
	--no-reload-nginx \
	-k /data/data/com.termux/files/home/ssl/example.jp/account.key \
	--dns-provider digitalocean \
	--domain-private-key /data/data/com.termux/files/home/ssl/example.jp/example.jp.key \
	-o /data/data/com.termux/files/home/ssl/example.jp/example.jp.crt \
	-d '*.example.jp' -d 'example.jp'

ドメインの指定は、*.example.jp と example.jp を指定します。そうしないと、example.jp でのドメインだけのアクセスで証明書が無効となります。
 実際のログは(ドメイン名は置き換えていますが)以下のようになります。

2020-09-13 02:45:40,777 - INFO - trying to create account key /data/data/com.termux/files/home/ssl/example.jp/account.key
2020-09-13 02:45:41,727 - INFO - trying to register acmev2 account
2020-09-13 02:45:43,612 - INFO - already registered
2020-09-13 02:45:43,613 - INFO - trying to create domain key
2020-09-13 02:45:43,615 - INFO - acmev2 dns challenge
2020-09-13 02:45:43,615 - INFO - preparing new order
2020-09-13 02:45:46,648 - INFO - order created
2020-09-13 02:45:47,644 - INFO - verifying domain example.jp
2020-09-13 02:45:47,670 - INFO - creating TXT dns record _acme-challenge.example.jp IN TXT uWmLyGGgK1Jyj(省略)RHo-A5TUKBAac
2020-09-13 02:45:50,642 - INFO - asking acme server to verify challenge
2020-09-13 02:45:52,486 - INFO - waiting for example.jp challenge verification
2020-09-13 02:45:53,239 - INFO - example.jp verified!
2020-09-13 02:45:53,240 - INFO - delete dns record
2020-09-13 02:45:56,793 - INFO - verifying domain example.jp
2020-09-13 02:45:56,817 - INFO - creating TXT dns record _acme-challenge.example.jp IN TXT hP2bwoYASAQYL(省略)VkiKGDupZxfw0
2020-09-13 02:45:59,551 - INFO - asking acme server to verify challenge
2020-09-13 02:46:02,005 - INFO - waiting for example.jp challenge verification
2020-09-13 02:46:02,884 - INFO - example.jp verified!
2020-09-13 02:46:02,885 - INFO - delete dns record
2020-09-13 02:46:05,385 - INFO - signing certificate
2020-09-13 02:46:08,480 - INFO - certificate signed!
2020-09-13 02:46:08,480 - INFO - downloading certificate
2020-09-13 02:46:09,472 - INFO - writing result file in /data/data/com.termux/files/home/ssl/example.jp/example.jp.crt

30秒くらいで、完了していますね。dnsにテキストレコードを書いている部分が2回あります。ちゃんと認証が通ればテキストレコードは削除していますね。これは便利!作者に感謝です!

ステップ4

あとは、キーと証明書をnginxに設定して再起動しておきます。

・Key
 /data/data/com.termux/files/home/ssl/example.jp/example.jp.key

・CRT
 /data/data/com.termux/files/home/ssl/example.jp/example.jp.crt

あとは、実際のクライアントから確認してみます。

おー、鍵マークがかかっていますね。うまくできているようです! 今度は、curlで https://gpl.jp にアクセスできるか確認してみます。WordPressには、このドメインはマッピングしていないので、静的ファイルが置いてあるURLに対してアクセスしてみます。curlクライアントはリモートのMacからです。

$ curl -Iv https://gpl.jp/license.txt
*   Trying 116.58.181.140...
* TCP_NODELAY set
* Connected to gpl.jp (116.58.181.140) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.gpl.jp
*  start date: Sep 12 16:46:12 2020 GMT
*  expire date: Dec 11 16:46:12 2020 GMT
*  subjectAltName: host "gpl.jp" matched cert's "gpl.jp"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fd360002000)
> HEAD /license.txt HTTP/2
> Host: gpl.jp
> User-Agent: curl/7.54.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200 
HTTP/2 200 
< server: nginx
server: nginx
< date: Sat, 12 Sep 2020 18:09:29 GMT
date: Sat, 12 Sep 2020 18:09:29 GMT
< content-type: text/plain; charset=utf-8
content-type: text/plain; charset=utf-8
< content-length: 19915
content-length: 19915
< last-modified: Wed, 12 Feb 2020 11:54:05 GMT
last-modified: Wed, 12 Feb 2020 11:54:05 GMT
< vary: Accept-Encoding
vary: Accept-Encoding
< etag: "5e43e75d-4dcb"
etag: "5e43e75d-4dcb"
< strict-transport-security: max-age=15552000
strict-transport-security: max-age=15552000
< x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
< x-frame-options: DENY
x-frame-options: DENY
< x-frame-options: SAMEORIGIN
x-frame-options: SAMEORIGIN
< x-frame-options: ALLOW-FROM https://www.youtube.com https://www.wordpress.com
x-frame-options: ALLOW-FROM https://www.youtube.com https://www.wordpress.com
< x-content-type-options: nosniff
x-content-type-options: nosniff
< content-security-policy: default-src * 'self' data: 'unsafe-inline' 'unsafe-eval' ;
content-security-policy: default-src * 'self' data: 'unsafe-inline' 'unsafe-eval' ;
< referrer-policy: strict-origin
referrer-policy: strict-origin
< permissions-policy: fullscreen=() geolocation=()
permissions-policy: fullscreen=() geolocation=()
< x-hacker: Hello. :-)
x-hacker: Hello. :-)
< accept-ranges: bytes
accept-ranges: bytes

< 
* Connection #0 to host gpl.jp left intact

ちょっと長いですが、途中「SSL certificate verify ok.」が出ていますね。接続は、TLS2 でHTTP/2 プロトコルになっていますね。これで当初の目的は達成できました! チェックサイトでは、A+判定出ていました。問題なさそうですね。

SSL Server Test (Qualys SSL Labs)

https://www.ssllabs.com/ssltest/

あとは、自動実行すればいいんですが termux の限られたリソースの中で cronjobを回して、ログを出し、何かあったらメールするっていうのをやるべきか、その他の方法を採用するかで迷っています。

 そもそも、termux でcronjobはちゃんと動くか確認しておかないとです。なんたって、androidシステム上で動いているわけですから。Dozeモードの影響とかそういうのは大丈夫なのか確認しないとです。

定期実行しておく

手動で実行していましたが、Site24x7 の監視サービスからアラートが飛んでくるので(これはありがたい機能ですが)cronに登録しておきました。しばらく様子を見てみます。

# update SSL . Run at 5:30 on the 1st and 15th of every month
30 5 1,15 * * /data/data/com.termux/files/home/ssl/gpl.jp/renew-cert.sh | $PREFIX/bin/msmtp junkhack@gpl.jp

あとがき

気になることはいろいろありますが、そろそろデータの引っ越しをやりますかね。 WordPress.com から速めに引っ越しして、新環境で記事を書いて行きたいです。

スマホ上に作った自宅サーバのWordPressで、テスト評価がほぼオールAになった!

はい、ただ今引っ越し準備中でして、このブログをスマートフォン上に作ったWordPressサーバに引っ越しします。9月末か10月頭予定で各種チューニングをやっていましたが、ついにスピードテスト系の評価サイトでほぼオールAを取ることに成功しました。

いくつかある評価サイトの中では、ここが一番好きです。ここの計測サイトは東京リージョンもあり、また各種グラフが見やすくビデオプレビューまで付いて来ます。

WEBPAGETEST

https://www.webpagetest.org/

主な評価観点は、左から以下のようになっています。

  1. セキュリティ
  2. 初期アクセスまでの時間
  3. Keep-alive通信がONか?
  4. 圧縮転送されているか?
  5. イメージの圧縮はどうか?
  6. 静的コンテンツがキャッシュされているか?
  7. CDNを使っているか?

7番のCDNは一部、WordPressのをつかっていますが、全部は使っていないので、x になっています。これはどうするかまだ迷っています。一度、国内のCDNをテストで使ってみようと思ったのですがうまく動作せずでした。まだ原因がわかっていません。

 難易度的には、簡単なものから3・4・5・6・2・1・7で難しかったです。今回は、自分なりの考えをメモりつつ、1つづつ紹介していきたいなと思います。必ず正解っていう部分はないところでもあるので、あくまで自分はこんな対策と対応をしたよっていう感じです。いろいろツッコミどころはあるとは思いますが、何かあればコメントでお気軽にどうぞ。

難易度G・Keep-alive通信がONか?

これは apache を使おうが、nginx を使おうが最初からデフォルトONになっているので意識せずともAになると思います。今回は、最終的に nginx を使うことにしましたので、nginx.conf に以下を設定しています。タイムアウト時間は短いほうが良いと思います。でも、ここは突き詰めると難しい部分です。興味がある方は、以下などを一読されると良いかなと思います。

ぜんぶTIME_WAITのせいだ!

https://qiita.com/kuni-nakaji/items/c07004c7d9e5bb683bc2
http {
::(省略)
    keepalive_requests 100;
    keepalive_timeout  3;
::(省略)

termux 上の android OSでは、一般的なLinuxと違ってKernelパラメータも調整されているはずですので、ここが何が適切なのかを明確にするには root権限のあるスマホで termux を動かし負荷テストをしながら、各種TCPの状態遷移を見ていくのが正しい姿勢です。という意味では一番難しい部類ですが、今回はそこまで突っ込まないことにします。

難易度F・圧縮転送されているか?

圧縮レベルは1でも十分という意見はありそうです。

http {
::(省略)
    gzip  on;
    gzip_vary       on;
    gzip_proxied    any;
    gzip_comp_level 6;
    gzip_types      text/plain text/css text/xml text/javascript
                    application/json application/javascript application/x-javascript
                    application/xml application/rss+xml application/atom+xml
                    image/svg+xml;
::(省略)

難易度E・イメージの圧縮はどうか?

これは今回は、ジェットパックのプラグインでwordpress のCDN側から画像が出ています。そこで適切に圧縮してくれているので簡単です。ただ、やりだすと奥が深いので、中間くらいの位置付けにしてあります。

難易度D・静的コンテンツがキャッシュされているか?

これは、レスポンスヘッダにNo max-age または expiresをつければ解決します。具体的には、nginxの設定で以下を設定すればOKです。

location ~* \.(jpg|jpeg|gif|png|css|js|swf|ico|pdf|svg|eot|ttf|woff)$ {
    expires 60d;
    add_header Cache-Control "public, no-transform";
    access_log off;
}

難易度C・初期アクセスまでの時間

これは、WordPress側でキャッシュを作るのが一番最速です。各種プラグインがありますが、いろいろ試した結果、今の所はAutoptimizeに落ち着いています。

デフォルト設定でも十分効果はあります。迷ってる設定としては、Google フォントの削除 をするかしないかです。表示の綺麗さを取るか、お客様に快適にアクセスしてもらうのを取るか ですね。あとは、ネットワーク的な速度の部分があります。今は InterLink の回線上にいますが、少し工夫してある部分といえば、常時利用する経路とは分離してあるくらいでしょうか? WiFiの5G接続でもこのくらいは出ますよという参考値になればと思います。WiFiルーターの側にスマホ(サーバ)は置いてあります。距離を離すと応答速度が遅れます。

難易度B・セキュリティ

これが結構難しかったです。まず、WordPress の最新を使ってもjquery 1.12.4でした。これは脆弱性があるので、あげて置きたいところですが WordPressはIE8のことも考えて意図的に落としているようです(たぶん)。なので、以下プラグインで上書きしています。

しかし、これ以外もやることがあって以下のチェックサイトに行ったほうがわかりやすいかもしれません。各種セキュリー関連のhttpヘッダーを付与する必要があります。

https://securityheaders.com/

最初はここ、真っ赤でF判定だったです。

対策としては、NGINXの設定でヘッダに以下をつければA判定となりクリアになりますが、まだiFrameの設定が未完結です。X-Frame-Optionsは、古く Content-Security-Policy の指定で行うのが良さそうです。frame-ancestors を指定し組み込める参照元を制限する方法が良いということはわかっているのですが、まだ設定値が決まりません。A判定は取っていますが、内容がない状態です。

add_header Strict-Transport-Security "max-age=15552000"; 
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Frame-Options "ALLOW-FROM https://www.youtube.com";
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src * 'self' data: 'unsafe-inline' 'unsafe-eval' ;";
add_header Referrer-Policy strict-origin always;
add_header Permissions-Policy "fullscreen=() geolocation=()";

難易度A・CDNを使っているか?

ここは、DNSの向け先を変えたり、CDNのキャッシュをコントロールしたりする必要があり、運用とも関わる部分です。一度設定したのですが、うまく動作せずここは今の所一番の課題となっています。そもそも、月間5000ページビューにも行かないこのサイトでCDNを導入する必要があるかどうか? という点もありますが、一度やって見ないとわかりません。あと仕事ではなく、趣味なので無料のものしか使う気はありません。さて、どこがいいんでしょうかね?

あとがき

このサーバは、スマホで動いていてWiFiの無線で繋がっていますが、こんなちっさな筐体でもWordPressが動く、しかもA評価までもらえるなんて! 感動です。Termuxは最高のアプリですね。神アプリ認定です。

 しかも、常時SSL対応ですよ。もちろん、無料のSSL証明書です。なんだか時代は刻々と進化していますね。

Termux環境で動作するLet’s Encryptのワイルドカードドメインに対応した自動化ツールを探せ!

termuxで動作するのがほしい!

先日、termux上で動作を試したちっさな acme-tiny というPython製のACMEクライアントですがどうやら調べたらワイルドカードには対応していないようです。ACMEとは、Automatic Certificate Management Environment の略で、ざっくり言えばSSL証明書発行の管理をやりとりするプロトコルです。rfc8555 にあるようです。この中でワイルドカード証明書はDNSチャレンジによる認証が必要ということです。

acmy-tinyの設計方針

acmy-tiny のプログラムは全部で198行です。作者は小さなプログラムにとどめておきたいようです。以下のように、200行くらいにとどめておきたいので、DNSチャレンジのサポート(ワイルドカードサポート)はしませんということです。

I don’t plan on adding DNS challenge support (thus no wildcard support)

https://github.com/diafygi/acme-tiny/issues/195#issuecomment-372097617

I don’t plan on increasing the line limit above 200.

https://github.com/diafygi/acme-tiny/issues/195#issuecomment-372097580

作者の方針なんで、仕方ないですね。でも、必要以上の機能は追加しないと言い切るのは立派なことです。当初のコンセプトは崩さず。きっと200行以内の小さなプログラムであることがどこかで生きてくるはずです。

 で、通常はこれで十分事足ります。このブログでも hack.gpl.jpというドメインの証明書が取れればいいので問題ありませんが、*.gpl.jp にも使えるようにしてみたいので、一度触れておきたいんですよね。昔は、ワイルドカードドメインの証明書って結構高くて手が出なかったのを覚えています。

ワイルドカードの証明書がほしい!

 使いたい理由として、ワイルドカードの証明書を入れておくと、移行がスムーズになるというのもあります。実は、サブドメインを hack.gpl.jp にしようかなと思っていますので、hack.gpl.jp もマッピングしておこうかなと。つまり、今作っているスマホ新サーバでは、hack.gpl.jp として運用しておいて、wordpress の設定で複数のドメインにもマッピングできるようにしておけば、DNSの切替でどっちも同じところにアクセスできるようになります。(たぶん)

https://hack.gpl.jp/
https://hack.gpl.jp/

そういう運用や移行はやったことないんですが、理論上はできそうです。これを実現するためには、ワイルドカードの証明書があると便利かなと。使わないならば、バーチャルホストの設定を2つ作り、シングルの証明書を2つ発行するという方法でもいいのですが。いやいや、せっかくワイルドカードのSSL証明書が無料で発行できるならばチャレンジするしかないでしょう!w

acme-nginx ワイルドカード証明書対応の小さなやつ!

 さて、なんか良いのは無さそうかなと、世界は広いので誰か絶対作ってるはずです。・・・はい! ありました。acme-nginx です。まだ未確認ですが termuxでも動作するはずです。

ReadMeを読んでみると、どうやらDNSのテキストレコードも自動的に書き換えるようで、これはAPIが完備したDNSプロバイダーじゃないとダメなようです。現在、動作するのは、デジタルオーシャンと、AWS Route53のDNSです。

バリュードメインのAPI

acme-nginxが、デジタルオーシャンのDNSと、AWS Toute53に対応しているのはわかりましたが、現在使っているのはバリュードメインです。ここもつい最近、APIが完備されたので、使えないか調査してみることにしました。もし使える感じなら、acme-nginx に機能を拡張すればいいだけです。

バリュードメインのAPIマニュアルはここにあります。

バリュードメインAPIドキュメント (1.0.0)

https://www.value-domain.com/api/doc/domain/

実際に、APIトークンを発行していじってみました。curlに、jq をパイプしてjsonデータを見やすくしています。jqは、termuxにもあるし、macの brewにもあります。jq、便利ですね。Qitaで知りました!

curl -H 'Authorization: Bearer ★トークン' \
-H 'Content-Type:application/json' \
-X GET \
'https://api.value-domain.com/v1/freedns/{★domainid or domianname}' | jq

トークンや、ドメインID or ドメイン名など入れると以下のように出てきます。

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1388    0  1388    0     0   2258      0 --:--:-- --:--:-- --:--:--  2260
{
  "results": {
    "domainid": "xxxxxx",
    "domainname": "gpl.jp",
    "records": "#InterLink\na www 116.58.181.140\n# gpl.jp\na @ 116.58.181.140\na hack 116.58.181.140\na jh 116.58.181.140〜省略〜\na * 116.58.181.140",
    "ttl": "60"
  },
  "request_id": "20200911xxxxxxxxxxxxxxxxxxV",
  "request": {
    "path": "/v1/freedns/xxxxxxxx",
    "method": "GET",
    "params": []
  }
}

で、このrecordsっていう値、バリュードメイン使ったことがある人ならわかると思いますが、管理画面で設定するテキストの一覧がずらっと出てきます。バリュードメインAPIドキュメントの「DNS設定の変更」の部分を読んでみると、レコードごとに改行区切りの文字列です。

はい! つまり、aレコード単体で追加や削除とか、txtレコードだけ追加とかそういうことはできません。もしそれらを実装するとなると、recordsの値をパースしてチェックして書き換えるという面倒な作業が必要です。技術的には不可能ではないのですが、そこまで作るつもりはありません。

まぁ、その荒さ(テキスト一覧の設定ファイル)がバリュードメインの良いところでもあるのですが。設定ファイルをテキストファイルで管理しているだけなので、コンパネからがっつり一括登録・編集するのが便利なんですよね。

ということで、寝ました! このテキストファイルを処理する部分まで作るとメンドくさいので、デジタルオーシャンのAPIはどうなっているのか気力が復活した時にでも調べることにします。

デジタルオーシャンのAPI

さて、日が暮れて夜があけました。ぼちぼち、デジタルオーシャンのAPIでも調べることにします。ということで、以下がドキュメントです。

Create a New Domain Record

LINK

なるほど、良くできていますね。個別にレコードタイプ(A、MX、CNAMEなど)を指定し、データを更新も可能です。これなら、DNSを変更したほうが速いですね!

バリュードメインから、デジタルオーシャンへDNSを変更

というわけで、ちょっと調べたところデジタルオーシャンのDNSだけ使うなら無料なので、ネームサーバの向け先を変更しました。デジタルオーシャンの管理パネル、なかなか使いやすかったです。

設定を行い、google のG Suite Toolbox で引くとNSが切り替わっていました。

https://toolbox.googleapps.com/apps/dig/#NS/

;QUESTION
gpl.jp. IN NS
;ANSWER
gpl.jp. 1799 IN NS ns2.digitalocean.com.
gpl.jp. 1799 IN NS ns3.digitalocean.com.
gpl.jp. 1799 IN NS ns1.digitalocean.com.

ようこそ、デジタルオーシャンへ

名前が直接的でいいですね! デジタルの海です。ここはレジストラ業務はやっていないので、ドメイン取得はできないです。しかし、どこで取得したドメインでもネームサーバの向け先をデジタルオーシャンにすれば使えます。更新料金は、自分の場合はバリュードメインに支払います。デジタルオーシャンはAPIも充実していて、使いやすそうです。仮想サーバは日本にリージョンがまだないと思うので、安くて使いやすければそのうち、使ってみるかもしれません。

※追記 半年ほど経過しましたが、平均レスポンスタイムは94msでした。自分の場合は許容範囲です。ここで実際のレスポンスタイムを見れます。(DNSのグラフ)

DigitalOceanのDNS周りでは、以下の制約がありますのでご注意を。自動翻訳なんでちょっと変ですが。

DigitalOceanは現在ドメイン登録サービスを提供していません。DigitalOcean DNSを使用するには、ドメイン名をレジストラに登録し、DigitalOceanのネームサーバーを指すようにドメインのNSレコードを更新する必要があります

デフォルトでは、最大50のドメインを追加できます。サポートチケット開いて、増加が必要な理由を説明することで、制限を引き上げることができます。

すべてのDNSレコードには、30秒以上のTTL値が必要です。
DigitalOcean DNSは、以下のCAAレコード機能をサポートしていません。

値にセミコロン(;)を送信して、証明書の発行を禁止します。
CA名の後に名前と値のタグを許可します。例:letsencrypt.org; abc=cde

ワイルドカードレコードでカバーされるホスト名で作成されたレコードは、そのホスト名のワイルドカード解決を停止します。たとえば、にAワイルドカードレコードがあり*.example.com、ホスト名にMXレコードを追加するemail.example.comと、Aワイルドカードレコードはで提供されなくなりますemail.example.com。ただし、email.example.comユースケースで必要な場合は、ホスト名に明示的なAレコードを追加できます。

DigitalOcean DNSはタグをサポートしていません。

DigitalOceanの利用規約では、OFAC認定国からの国コードトップレベルドメイン(ccTLD)を追加することは禁止されています。国のリストなどの詳細については、参照ネットワークの合法的な使用にセクションを利用規約

https://www.digitalocean.com/docs/networking/dns/

さて、では記事が長くなりすぎるので、acme-nginx でワイルドカードドメイン証明書を取得するお楽しみは、別記事にします。では、また〜!

Termuxでのスマホサーバ、SSLアクセスでも耐えれそうかな?

TermuxでのLet’s Encrypt SSL化がやっとできたのでメモっておきます!

まず心配だったのは、SSLアクセスしたときのレスポンスですが、まぁ我慢どころといった感じでしょうか。

非SSLと比べると、接続には少し時間がかかっています。実際にスマホからSIM通信してみると、若干ワンテンポ送れる感じです。

証明書は、Let’s Encrypt でこれは3ヶ月ごとに更新しないといけないので自動化が必須となってきます。手動でやってもいいのですが、絶対面倒になって証明書を切らしてしまうので。で、自動化には certbot のスクリプトが有名なんですが、これは依存関係などがあったり、root (スクリプト中で su したり)が必須とかで、Termux では動きません。動かす方法もあるのでしょうが、世の中にはもっと小さな自動化ツールがありました!

acme-tiny っていうPython製の自動化PGです。pythonとopenssl があれば動くそうです。pip で入れて見ます。

ステップ1 pythonを入れる

pythonが必要なので、なければ入れます。今回は、もう入れてあるので次です。

$ dpkg-query -l | grep python
ii  python             3.8.5             aarch64      Python 3 programming language intended to enable clear programs

$ pkg install python -y

ステップ2 PIPで acme-tiny を入れる

$ pip install acme-tiny

pip が古いとか言われたら、以下で。

$ python3 -m pip install --upgrade pip

以下に入るようです。

$ which acme-tiny
/data/data/com.termux/files/usr/bin/acme-tiny

$ find $PREFIX -name *acme*
/data/data/com.termux/files/usr/bin/acme-tiny
/data/data/com.termux/files/usr/lib/python3.8/site-packages/acme_tiny.py
/data/data/com.termux/files/usr/lib/python3.8/site-packages/__pycache__/acme_tiny.cpython-38.pyc
/data/data/com.termux/files/usr/lib/python3.8/site-packages/acme_tiny-4.1.0.dist-info

ステップ3 Let’s Encryptアカウントの秘密鍵

どこか適当な場所にディレクトリを作って、そこで作業します。

$ cd
$ mkdir ssl
$ cd ssl
$ openssl genrsa 4096 > account.key

ステップ4 ドメイン用の秘密鍵を作成

ドメイン名は、読み替えてみてください。

$ openssl genrsa 4096 > www.example.jp.key

ステップ5 ドメインの証明書署名要求(CSR)を作成

シングルドメイン
$ openssl req -new -sha256 -key www.example.jp.key -subj "/CN=www.example.jp" > www.example.jp.csr

サブドメインのワイルドカード証明書はどうやって作るのかまだ知りません。課題です。

ステップ6 証明書に署名してもらう

$ mkdir -p /data/data/com.termux/files/home/【WEBROOT】/.well-known/acme-challenge/

$ acme-tiny --disable-check --account-key ./account.key --csr ./www.example.jp.csr --acme-dir /data/data/com.termux/files/home/【WEBROOT】/.well-known/acme-challenge/ > ./www.example.jp.crt

ここで、–disable-check を入れていますがこれは先日記載したUターンNAT(ヘアピンNAT)ができないため、自分自身のWEBにアクセスできないからです。そういう問題がない場合は、削除してください。

こんな感じで出来ると思います。crtができない場合は何かが悪いです。ログにヒントがありますので慌てず、探りましょう!

.
├── account.key
├── www.example.jp.crt 署名された証明書
├── www.example.jp.csr
└──  www.example.jp.key 鍵

.WEBROOT
    └── .well-known
        └── acme-challenge
           └──xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ステップ7 nginxの設定

設定ファイル抜粋。ルータとtermuxはポート転送しています。

http {
::(略)
    ssl_session_timeout 30m;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
::(略)
server {
     listen      8443;
::(略)
     ssl_certificate     /data/data/com.termux/files/home/ssl/www.example.jp.crt;
     ssl_certificate_key /data/data/com.termux/files/home/ssl/www.example.jp.key;
::(略)

なぜか、location で、.well-known/acme-challenge/ の場所が以下のように指定したら、アクセスできませんでした。なので、これは消して、実際のWEBROOTに/.well-known/acme-challenge/を作りました。

location ^~ /.well-known/acme-challenge/ {
    root /data/data/com.termux/files/home/【acme-challengeがあるパス】;
}
location = /.well-known/acme-challenge/ {
    return 404;
}

以下の評価が先にマッチしてしまって、これも一時的に消しました。

location ~ /\. {
    return 404;
}

nginxの設定、不慣れなんでどこかおかしいんでしょうね。

ワイルドカード証明書が取得できるようにしたら、cronに定期実行してもらおうと思いますが、もう少しいろいろ試してみてからにします。

SSLのチェックも良さそうです。

PageSpeed Insightsのモバイルのスコアも良さそうです。

PC版は100点出ました!

ということで、Termux のnginxとphp-fpmで無料の証明書を入れて速度的にも問題なさそうかなという感じです。

あとは、今回出たもろもろの問題をクリアにしてマクロを定期実行できればOKです。ぼちぼちやっていきます。でも、10月はじめまでには、移行完了しないといけませんので、それまでにはCDN問題もクリアして試してみたいです。

良くわからんこと!

・nginxのlocationのマッチはどうなってるのか?

・ワイルドカード証明書はどうやって作るのか?CSRの作り方っぽいが?

・リバースプロキシーでSSLアクセスするにはどうしたら?

アバター吹き出しをWordPressの自前ブログでやっと使える!

いやー、前から吹き出しを使ったブログを書いてみたかったんですが、やっと使えるのでちょっと開発サーバでテストしてみています。吹き出しっていうのは、こんな感じ。

アバターから言葉が出て、ブログがちょっと楽しくなる感じのやつです。よく見るでしょ? これが前からやりたかったんです。これを実現するプラグインやテーマはいくつかありますが、選んだのは「Word Balloon」っていうプラグインです。これは良くできていますね!

どんな感じで使うかは、こんな感じ。投稿画面で文字を入力後、選択して変換アイコンを押し、「Word Balloon」を選択するだけ。

こうすると以下のように登録したアバターと吹き出しになって表示されます。

ブロックを選択して、アバターを変更したり、位置を右側にしたりできます。このプラグインではアバターは3つまで無料で登録できます。3つもあればとりあえずは十分ですよね。もっとたくさん使う様になればそれほど高くもないですから、有料版のサブスクリプションも考えてもいいかもです。

 あと、このアバターですが「ZEPETO」っていうアプリで自撮り写真から作ったものです。結構、面白いですのでぜひお試しを。

iPhone使いは、iOS版もあります。

ぴーちゃんのモデルさんは、こちらから利用させてもらっています。

速く、SSL設定して新しいブログでいろいろ書いてみたいですね。では、また!

スマホサーバの構成をNGINX+php-fpm+mariadbの構成にしてWordPressを動かして速度を計測しておいた

NGINXとphp-fpm構成にしてみました。いつもの計測サイトです。

夜間のネットワークが一番空いている時なんで、速い感じでしょうか?

GCP東京リージョンからの、apache ab は以下。182/sec 〜!速っ 78秒かかっていたテストが5.5秒。あ、これWordPressのキャッシュ効かせる前でしたね。apache構成でも同じ条件でサイド計測しておかないと。

$ ab -n 1000 -c 100 http://jh.gpl.jp/
::
Server Software:        nginx
Server Hostname:        jh.gpl.jp
Server Port:            80

Document Path:          /
Document Length:        15997 bytes

Concurrency Level:      100
Time taken for tests:   5.479 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      16202000 bytes
HTML transferred:       15997000 bytes
Requests per second:    182.52 [#/sec] (mean)
Time per request:       547.887 [ms] (mean)
Time per request:       5.479 [ms] (mean, across all concurrent requests)
Transfer rate:          2887.87 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       16   20   6.5     19     149
Processing:    57  487  82.1    480     747
Waiting:       39  467  82.0    460     724
Total:         88  507  82.5    501     783

Percentage of the requests served within a certain time (ms)
  50%    501
  66%    531
  75%    544
  80%    551
  90%    578
  95%    642
  98%    702
  99%    738
 100%    783 (longest request)

まだ、SSLとか設定はこれからでパラメータなども未調整です。設定値は以下のサイトを大いに参考にさせていただきました。

NginxでWordPressを使う時の設定をまとめてみた

あとは、SSL設定をtermuxでどうやるかですね。自動化したいので、どんな感じの仕組みが動くんでしょうか。

あ、それからRapid START CDNのフェイスブックチャットに応答があったんで、もう一度試してみるかもしれません。

 追記

やっぱりWEBフォント読まないほうが速いんで、Autoptimizeで試験的にカットしてみました。

読み込むものが少なくなれば、表示するのも速いですね。WEBフォントがなくなることで、多少文字の表示は意図したものと違うことになりますが、快適に読んでもらえるほうが良いと思うので、とりあえずはWEBフォントは外す方向で。

あと、モバイル向けのスコアがかなり変わりました。

まぁ、そのうち気が変わるかもしれませんが。