Jan 12, 2020

Jupyter Notebookのリモートアクセス設定をしてみた

ガラケー+格安SIM差しタブレットの2台持ちに憧れて数年、完全に時代遅れ感があった昨秋に、遂にiPad(Wi-Fi + Cellularモデル)を買ってしまった。データ通信専用の格安SIMも差した。定期的に見たいが我が家の旧式PCでは見れないWebサイトがあったので、この機会にと思って勢いで買ったのだが、購入して2ヶ月、予想通り、Webブラウザ以外ほとんど使っていない。折角なので何か他にも活用したいと思って、まず思いついたのはPythonのプログラミング環境構築だった。
外出先でプログラミングすることはまず無いのだが、筆者は、目の前にあるiPadのような高スペックのコンピューターにプログラミング環境が無いと、気になって仕方がないのである。
そして、筆者が今一番興味ある言語はPythonであり、iPadでやるならPython一択である。

少し調べた限り、今iPadでPythonプログラミングするならPythonista3の一択のようであるが、Pythonista3ではPandasを使えないようで、しかも有料だったので、今回は見送った。
仕方なく、Jupyter Notebookを使うことにした。

自宅のLANでiPadのSafariからJupyter Notebookに接続してみると、表示もコード入力も実行もできた。ソフトウェアキーボードではかなり辛く、特にTABキーが無いので補完が効かないのが致命的であるが、必要であればBluetoothキーボードを使ったりJunoというアプリを使えば解決しそうなので置いておくとして、とりあえず自宅のPCに起動したJupyter Notebookに外出先からアクセスできるようにすれば、目的が達成できそうである。

筆者はプロバイダーから動的に付与される自宅のIPアドレスをDDNSに登録するようにしているので、既に外から自宅内PCへのアクセスは可能である。実際、ルーターのポートフォワーディング(静的NAT)設定をするだけで、iPadからセルラー網経由で自宅PCのJupyter NotebookへHTTP接続できた。
しかし、HTTPだとパスワードが平文で送られてしまうのが問題である。
そこで、以下の3通りの方法を考えてみた。

(1) 自宅PCにSSHサーバーを設けてSSHトンネリングでJupyter Notebookに接続する
(2) ApacheにHTTPS接続し、Reverse ProxyでJupyter Notebookに接続する
(3) Jupyter Notebookに直接HTTPS接続する

(1)は筆者が過去にそうやって接続するしかないクラウドサービスを使ったことがあるので真っ先に思い付いた方法で、PCからは難なく成功したのだが、iPadで安全にSSHトンネリングしてキープさせるには有料アプリを使うしかなさそうなので、やめた。
(2)(3)を今回やってみたので、ここに記録する。

HTTPS接続したApacheのReverse ProxyでJupyter Notebookに接続する環境の作成方法

ここでは、https://ynomura.dip.jp/desktop/ipython/でデスクトップPC(192.168.0.80)のポート8888のJupyter Notebookに接続できるようにするものとする。

■Apache(2.4)の設定
HTTPSのVirtualHostは設定済、SSL/TLSサーバ証明書もインストール済みとする。
結果として、以下の設定で成功した。

  • proxy, proxy_http, proxy_wstunnelモジュールの有効化
    sudo a2enmod proxy
    sudo a2enmod proxy_http
    sudo a2enmod proxy_wstunnel
  • sites-enabled/*の<VirtualHost *:443>の所に以下のように/desktop/ipython/の設定を追加
    
    <VirtualHost *:443>
    	...
    
    	<Location /desktop/ipython/>
    		ProxyPass http://192.168.0.80:8888/desktop/ipython/
    		ProxyPassReverse http://192.168.0.80:8888/desktop/ipython/
    		ProxyPreserveHost On
    
    		Order deny,allow
    		Deny from all
    		Allow from 192.168. pXXXXXXX-mobac01.tokyo.ocn.ne.jp
    	</Location>
    	<Location /desktop/ipython/api/kernels/>
    		ProxyPass ws://192.168.0.80:8888/desktop/ipython/api/kernels/
    		ProxyPassReverse ws://192.168.0.80:8888/desktop/ipython/api/kernels/
    	</Location>
    
    </VirtualHost>
    
    "pXXXXXXX-mobac01.tokyo.ocn.ne.jp"というのは、筆者のiPadのFQDN(アドレス)である。これは時々変化するのだが、"-mobac01.tokyo.ocn.ne.jp"の部分は変わらないようなので、Allowの所に"-mobac01.tokyo.ocn.ne.jp"と書きたいのだが、残念ながらそれは通らないらしい。(https://httpd.apache.org/docs/2.4/ja/mod/mod_access_compat.htmlに、"Allow from apache.org"と書くと foo.apache.org にはマッチするが、 fooapache.org にはマッチしないと書かれている。マッチすると困るので当たり前であるが)
    "ProxyPreserveHosts On"としないと、Jupyter Notebookで"Blocking Cross Origin API request. Origin: https://ynomura.dip.jp, Host: 192.168.0.80:8888"というエラーになる。
参考: Deploying behind a reverse proxy - jupyterhub/jupyterhub

■Jupyter Notebook側の設定

  • リモートアクセスを可能にする設定
    jupyter_notebook_config.pyにて
    c.NotebookApp.ip = '*'
    とする。
  • パスワード設定
    Jupyter Notebookにて
    from notebook.auth import passwd
    passwd()
    としてハッシュ化されたパスワードを得て、jupyter_notebook_config.pyにて
    c.NotebookApp.password = u'(ハッシュ化されたパスワード)'
    とする。
    参考: Securing a notebook server - Jupyter Notebook documentation
  • URL変更
    jupyter_notebook_config.pyに
    c.NotebookApp.base_url = '/desktop/ipython/'
    を追加する。
    これをせず、https://ynomura.dip.jp/desktop/ipython/をhttp://192.168.0.80:8888/にリレーする方法がわからなかった。

■Jupyter NotebookをHTTPSサーバーにする設定方法

Jupyter Notebook DocumentationのUsing SSL for encrypted communicationの所に全て書いてあった。
  • リモートアクセスを可能にする設定
    上記と同じ
  • パスワード設定
    上記と同じ
  • SSL/TLSサーバ証明書と秘密鍵の設定
    jupyter_notebook_config.pyに
    c.NotebookApp.certfile = u'/absolute/path/to/your/certificate/mycert.pem'
    c.NotebookApp.keyfile = u'/absolute/path/to/your/certificate/mykey.key'
    の2行を追加する。
  • ポート番号変更
    ポート8888をインターネットに解放するのはすぐ狙われそうで抵抗があるので、変更する。ルーターのNAPT機能でポート番号を変換できれば良いのだが、筆者宅のルーターはNATしか対応していないので、Jupyter Notebookの待ち受け番号を変更する。
    jupyter_notebook_config.pyに
    c.NotebookApp.port = XXXXX
    を追加する。
  • ポートの解放、NAT設定
    Jupyter Notebookを起動するPCのFirewallのポートXXXXXを解放し、ポートXXXXX宛のパケットをそのPCに転送するようにルーターのNAT設定を変更する。
  • URL変更
    インターネットからhttps://既知のドメイン名:ポート番号/でアクセス可能だと気になるので、せめてhttps://既知のドメイン名:ポート番号/何らかのパス/としておく。
    Jupyter Notebookを起動するPCでもApacheを立ち上げるなどしてhttps://未知のホスト名.既知のサーバー名:ポート番号/とする方が無難だが、動作確認した方法の1つとして控えておく。
    jupyter_notebook_config.pyに
    c.NotebookApp.base_url = '/desktop/ipython/'
    を追加する。

See more ...

Posted at 23:33 in PC一般 | WriteBacks (0)
WriteBacks