セキュリティのため、ローカルホストやローカルネットワークにしかアクセスを許可していない Web アプリってあると思います。
例えば、オフィスで起動している社内サーバ。Jenkinsとか。Wikiとか。サーバ監視ツールとか。
例えば、本番環境で起動している Docker コンテナの中で動いているWebツールとか。
それらに、SSH経由で外からアクセスする方法です。
私の場合は、elasticsearch の head プラグインのWeb管理画面を起動しているのですが、ローカルホストからしかアクセスを許可してませんので、外からアクセスするには一工夫必要です。
そんな時に便利なのが SOCKS プロキシ。
SOCKS プロキシとは
乱暴にいうと、プロキシ接続先のサーバ上でブラウザを起動したような使用感となります。
ブラウザからのすべてのアクセスは、ポートを限定することなくすべてプロキシサーバ上からのリクエストとなります。
クライアントは Firefox に入ってますし、サーバは OpenSSH に組み込まれていますので、別途ソフトウェアのインストールは不要です。
まじ便利。
プロキシサーバの準備
OpenSSH から使えますので、ssh クライアントの -D オプションでローカルポートを指定するだけです。
$ ssh -D 10080 user@example.com
実行すると、普通に SSH クライアントが起動しますが、このクライアントの実行中はローカルの 10080 ポートをリッスンします。
ブラウザの設定
Firefox の場合、環境設定 →詳細 → ネットワーク → 接続 (プロキシ云々) の「接続設定」から指定します。
SOCKSホストを 127.0.0.1 、ポートを 10080 とすれば、先ほど起動した SSH クライアントが準備したポートを使いますので、これで SSH 接続先からリクエストするようになります。
自動でやる
さて、これを毎回オンオフするのはちょっと面倒ですね。簡単に設定する Firefox プラグインなどあるかもしれませんが、私は Selenium からやってます。
Python の場合は
$ pip install selenium
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference('network.proxy.type', 1)
profile.set_preference('network.proxy.socks', '127.0.0.1')
profile.set_preference('network.proxy.socks_port', 10080)
profile.set_preference('network.proxy.no_proxies_on', '')
driver = webdriver.Firefox(firefox_profile=profile)
driver.get('http://example.com')
このコードを実行すると、プロキシが設定された Firefox がポコっと起動します。
いつも使っている Firefox とは完全に別設定で起動するため、いつもの設定を壊すことはありません。
(ちなみに、set_preference の引数は、Firefox の about:config
のキーです。)
※ Firefox を終了させないままいくつも起動すると、mac のドックが Firefox だらけになるので、溜まってきたら
$ killall firefox-bin
でやっつけられます。
python fabric でやる
python の fabric でデプロイしてる方は、fabric のタスクを作ると便利です。
こんな感じでどうでしょう。
@runs_once
def elasticsearch_head():
"""
リモートサーバの Elasticsearch head を見る
"""
from threading import Timer
from selenium import webdriver
def open_firefox():
profile = webdriver.FirefoxProfile()
profile.set_preference('network.proxy.type', 1)
profile.set_preference('network.proxy.socks', '127.0.0.1')
profile.set_preference('network.proxy.socks_port', 10080)
profile.set_preference('network.proxy.no_proxies_on', '')
driver = webdriver.Firefox(firefox_profile=profile)
driver.get('127.0.0.1:9200/_plugin/head/')
t = Timer(0.5, open_firefox)
t.start()
# SOCKS の SSHトンネルを作る
local('ssh -D 10080 {}@{}'.format(env.user, env.hosts[0]))
こう作っておけば
$ fab develop elasticsearch_head
みたいな感じで、Webアプリが見れるわけです。