Okada Hiroshi の blog

typo が多いです

インフルエンザの予防接種に行ってきました

インフルエンザの予防接種にいってきました。

一応、検索して近所の医院の内、予防接種をやっていると明記してある所で電話予約して行きました。

予防接種は別に内科でなくてもやっているようで、僕が今回接種を受けたのは眼科でした。

www.baba-eyeclinic.com

平日の昼間だったので待ち時間は 0 でした。

値段は 3000円 でした。 なお、地域によっても違うでしょうが、年齢によっては安くなるので、子供には受けさせた方が良いと思います。

f:id:OkadaHiroshi:20181024211218j:plain

snap (Snappy) で Docker をインストールして sudo 無しで実行する方法

今まで、 Docker を Ubuntu にインストールするときには Docker 公式サイトの Get Docker CE for Ubuntu | Docker Documentation の手順の通りにしていました。

けれども snap でインストールれば、docker-compose も同時にインストールできて管理も楽なので、snap を使ってインストールしてみました。

ところが、

$ sudo snap install docker

とすると docker というグループが出来ず、 ユーザーを docker グループに所属させられないので、Docker を使うたびに

$ sudo docker run hello-word 

等と sudo しなくてはならなくなりません。

少しググって Using docker requires sudo · Issue #1 · docker/docker-snap · GitHub というスレッドで、解決方法を見つけました。

要するに

$ sudo addgroup --system docker
$ sudo adduser $USER docker
$ newgrp docker
$ sudo snap install docker

みたいに snap で Docker をインストールする 前に docker というグループを作っておけば良いということです。

これで

$ docker run hello-word 

のように sudo 無しで docker を実行できます。

放送大学に入学しました

10月から放送大学に入学しました。

学生証

入学した理由は数学や科学をもう一度勉強したかったためです。

僕は一応大学は物理科をでているのですが、当時は今ほど大学を卒業するのは難しくなかった上、卒研の実験を頑張ることによって誤魔化したのではっきりいって学力はないです。

社会人になってからも、最低限の線形代数とかはプログラムを作る上で必要だったので復習しましたが、それ以外はサッパリです。

もちろん、インターネット上の情報や講座、本だけで勉強すれば、放送大学より安く勉強できるのですが、やはり単位のための試験があって一定の期間の間に勉強しなければならないというプレッシャーが僕には必要だと思っています。

卒業を目指すかどうか決めていませんが、とりあえず無理のない範囲で単位を取っていきたいと思います。(一応10年いられるので)

2段階認証ワンタイムパスワード (TOTP) クライアント を Ubuntu (コマンドライン) で

最近は多くのサイトが2段階認証を採用していて、僕も気がついたら 10個以上のサービスで使用しています。

一般的には、 Google 認証システムや、その互換アプリをスマホに入れて使っていると思います。 僕は IIJ SmartKey|スライド認証・ワンタイムパスワード管理 というのを使っています。

けれどもスマホを紛失、破損した場合に備え、バックアップとしてPCでも TOTP(時間ベースのワンタイムパスワード) を生成できるようにしておくと便利です。

今回は、ぼくの使っているる Ubuntu での TOTPクライアントについて解説したいと思います。

なお、今回は CLI での作業となります。また安全のため Ubutnu の公式リポジトリの (apt でインストール) できるパッケージのみを使うことにします。

環境は Ubuntu 18.04 ですが、 Ubuntu 16.04 にも同じパッケージが有るので OK だと思います。それより古いバージョンについては調べていません。

パッケージのインストール

インストールするのは、バーコードを読み取るための zbar-tools と、ワンタイムパスワードを生成する oathtool (つづり注意) です

$ sudo apt install zbar-tools oathtool

QR コードの読み取り

2段階認証を有効にすると次のような QR コードが表示されると思います。

f:id:OkadaHiroshi:20181017161854p:plain

もし、これを totp.png のようなファイルに保存したとすると、

$ zbarimg totp.png

でファイルから QR コードを読み込むことができます。

あるいは PC にカメラがついていれば、

$ zbarcam

と入力するとカメラが起動し、QRコードを読み込むことができます。

いずれにしても

QR-Code:QR-Code:otpauth://totp/Amazon%20Web%20Services:sample1@12345678901?secret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&issuer=Amazon%20Web%20Services
scanned 1 barcode symbols from 1 images in 0.07 seconds

と表示されるので secret= と次の & の間に有ある XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX の部分を記録してください。

参考: Key Uri Format · google/google-authenticator Wiki · GitHub

( 保存した画像や、この文字列が漏れると2段階パスワードが破られていましますので、取扱には注意してください。)

ワンタイムパスワードの生成

$ oathtool --totp=sha1 --base32 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

のように、先程の文字列を oathtool に与えるとワンタイムパスワードが標準出力に表示されます。

このコマンド行を、パスワード管理アプリ等に保管して管理すると良いのではと思います。

RawGit が終了するそうです。

RawGit という githubgithub gists のファイルを CDN で配布してくれる便利なサービスがあるのですが残念なことに終了するそうです。

rawgit.com

( マルウエアと戦うのに労力を使いたくないそうです、不毛な作業をしたくない気持ちはよく理解できます。)

少し前に書いた 自動リロード - Okada Hiroshi の blog も gist を RawGit 経由で配信していたので、 この際なので github page で配信することにしました。

大したアクセスもないのに RawGit を使っていたのは、gist では .js ファイルのヘッダーが Content-Type: text/plain; charset=utf-8 になってしまうためです、githbub page ではContent-Type: application/javascript; charset=utf-8 と正しくセットされます 。

新しい URL は https://hiroshiokada.github.io/shortcodes/poor-mans-autoreload.js です。

ついでに js の minify もしてみました。 GitHub - HiroshiOkada/shortcodes: A collection of short codes

ロートルなのでタスクランナーではなく Makefile を使っています。

自宅で実行している Jupyter Notebook を外からアクセスしたかったので、リバースプロキシを設定しました

Jupyter Nodebook が便利なので、最近は自宅のデスクトップで立ち上げっぱなしにして、外出先からは ssh protfowarding で接続していました。

けれども、ブラウザだけでアクセスできたほうが便利な事も多いので、nginx の reverse proxy の経由でアクセスできるように設定をしました。

JupyterHub という複数の Jupyter Notebook を reverse proxy 経由で配信する設定の文書は以下にありました。

Using a reverse proxy — JupyterHub 0.9.4 documentation

単一の Jupyter Notebook Server でも大きな違いはないと思いますので、それを参考に僕の環境で必要だった調整加えた設定を以下に記述します。

(以下、 jupXXXX.toycode.com は仮の名前です、実際には少し違う名前で運用しています。)

自宅のネットワーク構成

f:id:OkadaHiroshi:20181010141822p:plain

  • デスクトップ PC (192.168.100.100) の 8888番ポートで Jupyter Notebook を実行しています。
  • 有線ルータの簡易DNS機能で自宅ネットワークの内部では jupXXXX.toycode.com を名前解決すると 192.168.100.200 (HP ProLiant) を返すようになっています。
  • 外部のインターネット上では、*.toycode.comは自宅のグローバルIPに結び付けられているので、jupXXXX.toycode.com を名前解決すると自宅のグローバルIPアドレスが返ってきます。
  • 有線ルータの静的NAT機能で外から来た 443 (https) ポートは Ubuntu 16.04 Server がインストールされている 192.168.100.200 (HP ProLiant) の 443 (https) ポートに届くようになっています。

192.168.100.200 (HP ProLiant) 上で実行している nginx の Dockerfile

nginx は Docker コンテナ上で実行しています。SNI (名前ベースのバーチャルホスト) になっています。

Dockerfile はこんな感じです。

FROM nginx:mainline-alpine

RUN apk update -q && apk add openssl
RUN openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

RUN rm /etc/nginx/conf.d/*

COPY nginx.conf server.crt server.key /etc/nginx/
COPY conf.d/ /etc/nginx/conf.d/

EXPOSE 80 443

nginx.conf

 user  nginx;
 worker_processes  1;

 error_log  /var/log/nginx/error.log warn;
 pid        /var/run/nginx.pid;


 events {
     worker_connections  1024;
 }


 http {
     include       /etc/nginx/mime.types;
     default_type  application/octet-stream;

     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';

     access_log  /var/log/nginx/access.log  main;

     sendfile    on;

     keepalive_timeout  65;

     gzip  on;

     server {
         listen 80 default_server;
         server_name  _;
         return 444;
     }

     server {
       listen 443 ssl default_server;
       server_name  _;
       ssl_certificate      /etc/nginx/server.crt;
       ssl_certificate_key  /etc/nginx/server.key;
       return 444;
     }

+    map $http_upgrade $connection_upgrade {
+        default upgrade;
+        ''      close;
+    }
+
+    ssl_session_timeout 5m;
+    ssl_session_cache shared:SSL:1m;
+
     include /etc/nginx/conf.d/*.conf;
 }
  • +が元の nginx:mainline-alpine の nginx.conf に追記した部分です。
  • Using a reverse proxy — JupyterHub 0.9.4 documentation に記述してあった内容を一部 http セクションに移動しました。
  • 特に ssl_session_cache shared:SSL: はバーチャルホスト間で共用するので server セクションではなくてここに書くべきだと思います。
  • 有効期間等は、自分一人で使うので負荷も大したことはないし、間違えた場合にキャッシュ等が長時間残ってしまうのを避けるため短めに設定しまました。

conf.d/jupXXXX.conf

server {
    listen 80;
    server_name jupXXXX.toycode.com;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;

    server_name jupXXXX.toycode.com;

    charset UTF-8;

    ssl_certificate /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    add_header Strict-Transport-Security max-age=3600;

    location / {
        proxy_http_version 1.1;

        proxy_pass http://192.168.100.100:8888;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 300;

        # websocket headers
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

}
  • return 301 https://$server_name$request_uri; http は恒久的に使う予定がないので 302 ではなくて 301 にしました。
  • listen 443 ssl; nginx公式サイトのngx_http_ssl_module によると ssl on; という書き方は obsolete だそうです。
  • ssl_protocols TLSv1.2; 僕の使っているブラウザは全て TLSv1.2 をサポートしているので TLSv1.1 等は記述しませんでした。
  • proxy_http_version 1.1; 必要なので追加しました。
  • ssl_stapling の設定は resolver の設定が必要で、僕の場合は LAN 内では外側とは別なIPアドレスを返しているので削除しました。
  • ここでも有効期間等を短めに設定しています。
  • ssl の証明書は以前の記事 で取得したワイルドカード証明書を利用しています。

結論

いまの所、これで上手く動いています。正直いって暗号のアルゴリズム ssl_ciphers についてはコピペしただけので自信がありません。

(SSL Server Test は一応 A になりました。)

中間証明書の連結

8月29日に購入したワイルドカード証明書ですが、僕が普段使っている環境では問題がなかったのですが、一部の環境※1では中間証明書がインストールされていないようなので、中間証明書を連結しました。

www.ssl2buy.com

上記のページの New AlphaSSL / Wildcard Intermediate certificateAlphaSSL Root CA certificateintermediate.crtroot.crt という名前で保存して。

$ mv toycode.crt toycode1.crt
$ cat toycode1.crt intermediate.crt root.crt > toycode.crt

で連結した証明書ファイルを作成しました。

※1 python やそれを使っている aws ツール