/etc/hosts を書き換えなくても気軽に特定のサーバに通信できるプロキシが欲しいと思ったんですが、意外にちょうど良いのがなかったので自作しました。
<追記>
proxy.pac で十分ではという意見をブコメでいただいたんですが、やりたいのは「本番系リバースプロキシやロードバランサを通さずに特定のサーバだけに任意のタイミングでアクセスする手段」を、システムファイル書き換えを伴わずに行う方法なので今回のコンセプトとは少しばかり違うのです・・・。
追記>
るびまに Webrick でプロキシサーバの記事がある
#!/usr/bin/env ruby
require 'webrick'
require 'webrick/httpproxy'
# プロキシサーバオブジェクトを作る
s = WEBrick::HTTPProxyServer.new({})
# SIGINT を捕捉する。
Signal.trap('INT') do
# 捕捉した場合、シャットダウンする。
s.shutdown
end
# サーバを起動する。
s.start
こんな風にかけるんだよと。
とりあえず構造を理解する
service メソッドが本体のようだ。
HTTP通信要求が発生したとき、CONNECTの場合はdo_CONNECTメソッドに、それ以外は proxy_service メソッドに振られる。引数は (req, res) になっている。
do_CONNECT では req.unparsed_uri を元に接続を確立してる。そうでないやつらは req.host を使って http モジュールに委譲しているようだ。
ここまで分かれば大丈夫。
example.com への通信をすべてAWS(ELB)へ向けるプロキシを作る
まあイメージ的には example.com は本当はどっかでちゃんと動いているんだけど、開発用にAWSに立てたどこぞのロードバランサに向けたいと思いねぇ。
これを参考にカスタマイズさせていただいた。
require 'webrick'
require 'webrick/httpproxy'
UPSTREAM='fugafuga-example-no-1-1111.ap-northeast-1.elb.amazonaws.com'
def rewrite_url(uri)
uri.sub!(/^.+example\.com/, UPSTREAM)
end
class ProxyServer < WEBrick::HTTPProxyServer
# HTTP の場合はここで書き換え
def proxy_service(req, res)
print "proxy_service: #{req.host} -> "
rewrite_url(req.host)
puts req.host
super
end
# CONNECT の場合はここで書き換え (HTTPSの確立のタイミングなど)
def do_CONNECT(req, res)
print "proxy_connect: #{req.unparsed_uri} -> "
rewrite_url(req.unparsed_uri)
puts req.unparsed_uri
# プロキシのメイン処理
super
end
end
config = { :BindAddress => '0.0.0.0', :Port => 8080, :Logger => WEBrick::Log::new(nil, WEBrick::Log::WARN), }
s = ProxyServer.new( config )
Signal.trap('INT') do
s.shutdown
end
s.start
でけた。
Firefoxの FoxyProxy などと併用することでむやみに便利になる
もちろん、開発機へ繋いでいるのかどうか分からなくなる危険性が常にあります。
まとめ
接続先を書き換えられるプロキシって意外に手軽なのがないもんですね。
今回はややこしいことはしてないですが、ロギングやパフォーマンスの測定、アクセス制御など簡単に書けます。
標準的な ruby のライブラリで動作するので、必要なときにさっと自分で設置するような使い方ができるので重宝しそうです。