Okada Hiroshi の blog

typo が多いです

ローカルで開発中のコンテンツも初期の段階から https (ssl) で配信する (その3) Let's Encrypt を使ってワイルドカード証明書を取得しました。

5. Let's Encrypt のクライアントソフト Certbot をインストールしました。

PPA を追加して certbot をインストールしました。

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt update
$ sudo apt install certbot

6. certbot を使って証明書を取得しました。

証明書を要求するために次のようなコマンドを入力しました。

sudo certbot certonly --manual --preferred-challenges=dns-01 --server=https://acme-v02.api.letsencrypt.org/directory --agree-tos -m okadahiroshi@mibox.jp -d '*.local.toycode.com'

すると以下のように表示されます。途中で Are you OK with your IP being logged? 「あなたのIPアドレスを記録しますがよろしいですか?」と聞かれるので y と答えました。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for local.toycode.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.local.toycode.com with the following value:

1QjY1MdTuF1gjGmJexopl7N9DosUTaSyGz7gDCGlck0

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

ここで、DNS の TXT フィールドに貼り付ける認証用の文字列 が表示されました。

ここでもう一つ別なターミナルを開いて zone ファイル /etc/nsd/local.toycode.com.zone に TXT フィールドを加えました。 もちろん serial も増やしました。

$TTL 1m
local.toycode.com. IN SOA ns-local.toycode.com. postmaster.toycode.com. (
  2  ; serial
  5m ; refresh
  2m ; retry
  6h ; expire
  1m ; minimum
  )

@ IN NS ns-local.toycode.com.

ns-local IN A 35.199.184.64 

_acme-challenge.local.toycode.com. IN TXT "1QjY1MdTuF1gjGmJexopl7N9DosUTaSyGz7gDCGlck0"

a192-168-1-1 IN A 192.168.1.1
a192-168-1-2 IN A 192.168.1.2
以下略

/etc/nsd/local.toycode.com.zone を編集し終わったら、$ sudo nsd-control reloadで zone ファイルを読み込ませました。 そして、$ dig txt _acme-challenge.local.toycode.com +noedns +short"1QjY1MdTuF1gjGmJexopl7N9DosUTaSyGz7gDCGlck0" が返ってくることを確認しました。

zone ファイルの更新が終わったので、もとのターミナルに戻って、enter キーを押しました。すると

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/local.toycode.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/local.toycode.com/privkey.pem
   Your cert will expire on 2019-04-15. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

と表示され、/etc/letsencrypt/live/local.toycode.com/fullchain.pemドメインの証明書と中間認証局の証明書の連結されたものが、 /etc/letsencrypt/live/local.toycode.com/privkey.pem秘密鍵ファイルが保存されました。(実際にはこれらはシンボリックリンクで実体は別な場所に保管されています。)

なお上には表示されていませんが。/etc/letsencrypt/live/local.toycode.com/ ディレクトリには

ファイル名 内容
cert.pem ドメインの証明書
chain.pem 中間認証局の証明書
fullchain.pem ドメインの証明書と中間認証局の証明書の連結されたもの
privkey.pem 秘密鍵

の4個のファイルが保存されていました。

以上でワイルドカード証明書の取得ができました。

ローカルで開発中のコンテンツも初期の段階から https (ssl) で配信する (その2) NSD のインストールと設定

4. NSD をインストールしました。

今回はマシンのリソースも少ないので DNSコンテンツサーバ(権威DNSサーバ) として軽量だと言われている NSD https://unbound.jp/nsd4/ https://www.nlnetlabs.nl/projects/nsd/ を使ってみました。

インストール自体は apt で簡単にインストールできます。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install nsd

今回 DNS をセットアップ中に自分自身の名前解決等ができないとエラー等がこったり反応が悪くなるので /etc/hosts に以下のエントリーを追記しました。

35.199.184.64 ns-local.toycode.com
127.0.1.1 ns-local

/etc/nsd/nsd.conf を次のようにしました。

server:
        do-ip4: yes
        do-ip6: no
        port: 53
        username: nsd
        zonesdir: "/etc/nsd"
        pidfile: "/run/nsd/nsd.pid"
        logfile: "/var/log/nsd.log"

zone:
        name: "local.toycode.com"
        zonefile: "local.toycode.com.zone"

/etc/nsd/local.toycode.com.zone を作成し、次のようにしました。

$TTL 1m
local.toycode.com. IN SOA ns-local.toycode.com. postmaster.toycode.com. (
  1  ; serial
  5m ; refresh
  2m ; retry
  6h ; expire
  1m ; minimum
  )

@ IN NS ns-local.toycode.com.

ns-local IN A 35.199.184.64 

a127-0-0-1 IN A 127.0.0.1

a192-168-1-1 IN A 192.168.1.1
a192-168-1-2 IN A 192.168.1.2
a192-168-1-3 IN A 192.168.1.3
a192-168-1-4 IN A 192.168.1.4
a192-168-1-5 IN A 192.168.1.5
a192-168-1-6 IN A 192.168.1.6
a192-168-1-7 IN A 192.168.1.7
a192-168-1-8 IN A 192.168.1.8
a192-168-1-9 IN A 192.168.1.9
a192-168-1-10 IN A 192.168.1.10
a192-168-1-11 IN A 192.168.1.11
a192-168-1-12 IN A 192.168.1.12
a192-168-1-13 IN A 192.168.1.13
以下略

TTL は後で修正が早く反映されるように極端に短い値にしています。ある程度たったら大きな値 (1dとか) に書き換える予定です。シリアルは後でスクリプト等で修正するかもしれないので、一般的な日付をベースにしたものにしていません。

使いそうなアドレスは全て登録しました、僕がよく利用するネットワークは 192.168.1.0/24 192.168.2.0/24 192.168.100.0/24 192.168.101.0/24 なので すべて登録しました。

NSD は BIND とちがって $GENERATE が無いので一々記述する必要があります。スクリプト言語等で生成しても良いでしょう。ぼくは vim を使っているので

良く使うアドレスは個別にわかりやすい名前を割り当てても良いとおもいます。

:for net in [1,2,100,101] | for host in range(1,254) | put='a192-168-' . net . '-' . host . ' IN A 192.168.' . net . '.' . host | endfor | endfor

で生成しました。

また port 53 がバッティングして NSD が起動できなかったので、systemd-resolved.service を止めました。そして resolve.conf を手動で書き換えて 8.8.8.8 を参照するようにしました。

$ sudo systemctl disable systemd-resolved.service 
$ sudo service systemd-resolved stop
$ sudo rm /etc/resolv.conf 
$ echo nameserver 8.8.8.8 | sudo tee /etc/resolv.conf 

この辺はちょっとハマりました、以上の設定で動いていますが正当なやり方かどうかはわかりません。

参考: dns - How to disable systemd-resolved in Ubuntu? - Ask Ubuntu

5. ちゃんと名前が引けているかどうか確認しました。

nsd の起動は $ sudo nsd-control start zone ファイルの再読込は(シリアルを増やして) $ sudo nsd-control reload です。

zone ファイルの編集が終わって読み込んだら以下のようなコマンドで手元のコンピュータで 名前が引けるか確認しました。

$ dig A a192-168-1-1.local.toycode.com +short
$ nslookup -type=A a192-168-1-1.local.toycode.com
$ getent hosts a192-168-1-3.local.toycode.com

ローカルで開発中のコンテンツも初期の段階から https (ssl) で配信する (その1)

はてなブックマーク などごく一部のサービスを除いて多くの Web サービスが https で配信されるようになりました。 これはセキュリティ的には非常に良いことなのですが、開発している時には不便な事もあります。

例えば

  • OAuth 2.0 のコールバック URL は大抵の場合 localhost 以外だと https である必要があります。けれども、開発中にも隣においてある PC やスマホからアスセスしたい。
  • Web ブラウザから加速度センサー等のセンサーを読み出すためには https でないと動作しない。 Sensors For The Web!  |  Web  |  Google Developers
  • html 文書中で間違えて http で供給されるコンテンツを参照していても (エラーが出ないので) 気が付かず https 環境にアップロードして初めて気がつく。

などのです。

これを防ぐために開発の初期の段階から ssl 化しておく事が望ましいです。

https で配信するためには、ホスト名とそれに対応した ssl 証明書が必要です。例えば僕の自宅 LAN の場合 192.168.100.* というアドレスが DHCP dで配布されますので、DNS サーバーにこれらのホストを登録して、対応する ssl 証明書を取得すれば、ローカルで開発中のコンテンツも ssl で配信できます。

具体的には僕の所有しているドメイン toycode.com のサブドメイン local.toycode.com というのを作って、 a192-168-100-2.local.toycode.com なら 192.168.100.2、 a192-168-100-3.local.toycode.com なら 192.168.100.3 というアドレスが引けるようにして、さらに *.local.toycode.com のワイルドカード証明書を取得することにより ssl 化を行うことにしました。

今回は Google Compute Engine (GCE) の無料枠の f1-micro インスタンス上に DNS サーバーを立てて、let's encrypt でワイルドカード証明書を取得することにより、ほとんど追加の費用なしで上記の事を実現できましたので、手順を説明します。

この方法はオレオレ証明書を使う方法やトンネリングを使う方法に比べてクライアント側の設定がいらないのが利点だと思います。

1. GCE のインスタンスを作成しました。

GCE の無料枠の f1-micro インスタンスの立て方はネットワーク上に山ほど記事があるので、割愛します。今回は DNS サーバーとして利用しますので、固定IP を取得します。固定IPはインスタンスに割当ないと課金されるので確実にインスタンスに割り当てる必要があります。

ブートディスクは Ubuntu 18.04 LTS を使用しました。名前は nc-local としました。今回 IP アドレスは 35.199.181.64 でした。

f:id:OkadaHiroshi:20190116145210p:plain

2. ファイアーウォールのルールを作成してポート 53 を開けました。

ファイアーウォールのルールを作成します。名前とか説明は何でも良いのですが、注意点としては UDP 53、TCP 53 の両方を開けるルールにすることです。 ターゲットタグの名前は覚えやすいように dns-server にしました。

f:id:OkadaHiroshi:20190116150214p:plain

指定したターゲットタグを VM インスタンス nc-local に割り当てました。 スクリーンショットでは http と https のポートも開いていますが今回の目的には不要です。

f:id:OkadaHiroshi:20190116150450p:plain

3. toycode.com の DNS サーバーから local.toycode.com のサブドメインの権限を移譲しました。

toycode.com の DNS サーバーは amazon の route 53 を使っています。local.toycode.com の権限を移譲させるために、aws の Route 53 Management Console を使って次の2つのレコード を追加しました。

f:id:OkadaHiroshi:20190116151616p:plain

他のサービスを使っていてもほぼ同様の事ができると思います。

ドメインのメインのネームサーバーは2つ以上必要ですが、サブドメインのネームサーバーは(冗長性を考えなければ)1つで OK です。

Web メモアプリとしても GitHub を使っています。

報道されているように GitHub の 無料ユーザーも無制限にプライベートリポジトリを利用可能に なりました。

僕は今までプライベートリポジトリを使うためだけに月に$7 をGitHub に払っていましたが、無料ユーザーに戻しました。 $7 を払わなくて良くなったのは良いことですが、無料になると文句も言いにくいので、サービスが低下しないように MS には頑張ってもらいたいと思います。

ところで、僕は以前から Web上で自分用のメモをとるのに Github を使っています。** 今まで EvernoteDropbox Paper, Google Document, Google Docs 等を使っていて今一つしっくり来ませんでしたが。

GitHub に メモ用のプライベートリポジトリを作ってそこでメモを取るのがシンプルで使いやすいです。

Markdown がリアルタイムにレンダリングされないのは不便だと感じる人も多いでしょうが、僕はその分コンパクトに表示されて画面を有効に使えるので気に入っています。 またメモを削除しても履歴が全部残っているので安心感が違います。(commit メッセージはちゃんと書いていませんが)

GitHub が無くなることは無いと思いますが、バックアップも git clone するだけなので非常に簡単です。

プログラムが書ければ、足りない機能があってももローカルに clone して簡単なスクリプトで処理したり、 CI で処理を回すことも(古い日付の物をディレクトリにまとめる等) 簡単なのでプログラムをかける人にはお勧めだと思います。

今更ながらブックマークレット作成

ちょっとブックマークレットを作たくなったので、今更ながら作成ツールを作りました。

オンラインにはもっと高機能なものも溢れていますが、個人的にはほぼ ChromeFirefox しか使わないので、入力、出力される JavaScript 両方とも新しめな物にしたかったのと、自分のブログに貼っておれば後で探さなくても済むので、作成しました。

python3.7 最小限の web サーバー

今年の中頃からぼちぼち python の勉強を始めています。普段は Jupyter Notebook でデータ処理等のスクリプトとかを書いて練習しています。

今日は気分を変えてミニマムな web サーバーってどうやって書くか調べてみました。

公式リファレンスだと https://docs.python.org/ja/3/library/http.server.html あたりなのですが、do_GET() あたりの書き方がわからなくて、おもったより時間がかかりました。(1時間くらい) web には未だ python2.x の情報が溢れているし、python3.x でもバージョンによって思ったより差異があって調べにくかったです。

Hello とだけ返す web サーバ (python3.7)

#!/usr/bin/env python3.7

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyHTTPRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.end_headers()
        self.wfile.write(bytearray('Hello', 'utf-8'))

my_httpserver = HTTPServer(('', 8080), MyHTTPRequestHandler)

try:
    my_httpserver.serve_forever()
except KeyboardInterrupt:
    pass

# ちゃんと閉じないとしばらくアドレスが開放されないので明示的に閉じる
my_httpserver.server_close() 

Ubuntu のコード名とバージョン、元 debian のバージョン

頻繁にググルので自分用のメモです。

バージョン コードネーム 読み 意味 エンドオブライフ Debian Debian コード名
18.10 Cosmic Cuttlefish コスミック・カトルフィッシュ 宇宙のコウイカ 2019-07 10 buster
18.04 LTS Bionic Beaver バイオニック・ビーバー 生体工学のビーバー 2023-04 10 buster
16.04 LTS Xenial Xerus ジニアル・ジリス(ジラス) おもてなしのアラゲジリス 2021-04 9 stretch
14.04 LTS Trusty Tahr トラスティー・タール 信頼できるタール 2019-04 8 jessie

情報元 URL