Okada Hiroshi の blog

typo が多いです

自宅で実行している 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 ツール

自動リロード

静的なサイトでも開発中には自動リロードして欲しいこともあるので、自動リロードするスクリプトを書いてみました。

poor man's autoreload

以下のスニペットを HTML 文書の head や body の内側に挿入すると 800ミリ秒ごとにHTML文書を(内部的に読み込んで)変化があったらリロードします。

<script src="https://cdn.rawgit.com/HiroshiOkada/6344f094955f3fc31deeffeec2718ff6/raw/4578f0948fa86cff08302a43aea1d913798ce23f/poor-mans-autoreload.js"></script>

追記

10分間変化がなかったらチェックを停止するようにしました。

追記 (2018-10-14)

使っていた RawGit というサービスが終了するので、gist でなく github page を使うことにしました。上記の代わりに以下を使ってください。

 <script src="https://hiroshiokada.github.io/shortcodes/poor-mans-autoreload.js"></script>

RawGit が終了するそうです。 - Okada Hiroshi の blog

GoogleニュースのRSS URL 組み立て

一時期 RSS リーダから遠ざかっていたのですが。最近また Miniflux という RSS インストールして使っています。

Google ニュースRSS 経由で 読みたいので、RSS フィードの URL を生成する簡単な Webアプリを CodePen で書いてみした。

入力欄にキーワードを(空白区切りで)いれて作成ボタンを押してください。

ちなみに URL の仕様は下記の記事を参考にしました。

www.yoshiteru.net

anond.hatelabo.jp

Google スプレッドシートにテキストを貼りつける

Google スプレッドシートにタブやカンマ区切りのテキストを貼り付けるると、貼りつけた直後は列が一つになってしまいます。 けれども貼付け後、テキストを列に分割を選択すると、期待したとおりに列に分割されます。

こういうのは知っている人にとっては当たり前なのでしょうが、僕は今日初めて知ったので書いてみました。

f:id:OkadaHiroshi:20180831162721g:plain

参考: セルのテキストを複数の列に分割する - パソコン - ドキュメント エディタ ヘルプ

SSL ワイルドカード証明書を購入しました

個人で所有しているドメイン toycode.com のワイルドカード証明書の期限が近づいてきたので新しい物を購入しました。

最近は Let's Encrypt があるので SSL 証明書を自前でもっているメリットは少なくないのですが、それでもワイルドカード証明書を一つ用意しておくと色々実験したりするのに便利です。

前回は namecheap という所から買いましたが、今回はさらに安く買える所がないか調べてみました。

プロバイダ サイトURL SSLブランド名 1年 2年
SSL2BUY https://www.ssl2buy.com/ AlphaSSL Wildcard $42.00 $80.00
Cheap SSLL https://cheapsslsecurity.com Comodo PositiveSSL Wildcard $72.95 $127.66
namecheap https://www.namecheap.com Comodo EssentialSSL Wildcard $74.88 $145.76

SSL2BUY という所が 2年で $80 (9000円程度) なので、ここで購入することにしました。

なお、日本語で展開しているところは例えば SSLストア だと2年で3万5000円、サイフにやさしいSSL証明書だと 4万4800円 と高いです。

基本的には持っているドメインの admin 等のメールアドレスか、ドメインwhois に登録されているメールアドレスがあれば、 あとはメールと Web サイトの指示に従っていけば良いのですが、CSR と private key は手元で作成する必要があります。

CSR と private key は openssl がインストールされていれば以下のようにして作成することが出来ます。

$ openssl req -new -newkey rsa:2048 -nodes -keyout toycode.key -out toycode.csr
Generating a 2048 bit RSA private key
...............................+++
.........................+++
writing new private key to 'toycode.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Shinjuku
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Hiroshi Okada
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:*.toycode.com
Email Address []:okadahiroshi@miobox.jp

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

なお、SSL の証明書は XXXXXXX: Your SSL Certificate for *.toycode.com has been issued のような題名の email で送られてきて、添付ファイルでなく、本文中の末尾に

-----BEGIN CERTIFICATE-----

... 30行以上の文字列...

-----END CERTIFICATE-----

というふうに書かれれいるので、この部分をコピペして、例えば toycode.cer みたいなファイルに保管します。

SSL サーバの起動にはこのファイルと先ほど作ったキーファイル (上記の例だと toycode.key) が必要です。