2009-03-13 うおーWEBrickすげぇー
簡単すぎるー
が、はまると深い(笑)
◆ [日記][プログラム] WEBrick (ruby) でproxy! 特に認証
いや、ヘッダとかコンテンツとかフィルタリングとか妙な動作を(笑)したい訳よ。分かるかなぁ?(笑)
それはともかく。
個人で使うなら、ほとんどのケースがRubyist Magazine - WEBrickでプロキシサーバを作って遊ぶのページだけで事足りる。
ぶっちゃけると
#!/usr/bin/env ruby
require 'webrick'
require 'webrick/httpproxy'
server = WEBrick::HTTPProxyServer.new({
:BindAddress => '127.0.0.1',
:Port => 3128,
:ProxyVia => false
})
trap('INT'){ server.shutdown }
server.start
こんな感じでできあがりなのである(ruby環境必須)
いやぁ楽ちんだねぇ。ここまでならば
ポート番号が3128なのはsquidへの嫌がらせです(ぉぃ
さて、次の段階へ行くよ~
認証してみましょう。プロキシ認証。圧縮proxy - とある技術屋の戯言当たりを参考に。
proxy_user、proxy_passってユーザとパスワードで認証。
こんな感じ
#!/usr/bin/env ruby
require 'webrick'
require 'webrick/httpproxy'
server = WEBrick::HTTPProxyServer.new({
:ProxyAuthProc => Proc.new() { | req, res |
WEBrick::HTTPAuth.proxy_basic_auth(req, res, 'proxy') { | user, pass |
user == 'proxy_user' and pass == 'proxy_pass'
}
},
:BindAddress => '127.0.0.1',
:Port => 3128,
:ProxyVia => false
})
trap('INT'){ server.shutdown }
server.start
ぶっちゃけ、:ProxyAuthProcの行が増えただけ。
固定じゃなくてどこかに問い合わせたければ、多分user ==とか書いてある行を書き変えれば良い。
ここまでもまぁまぁ楽。さて、地獄はまだまだだぜ!?
次。多段プロキシ。認証がなければかなり簡単。
#!/usr/bin/env ruby
require 'webrick'
require 'webrick/httpproxy'
require 'uri'
server = WEBrick::HTTPProxyServer.new({
:BindAddress => '127.0.0.1',
:Port => 3129,
:ProxyVia => false,
:ProxyURI => URI.parse('http://localhost:3128')
})
trap('INT'){ server.shutdown }
server.start
最初のバージョンから、:ProxyURIの行が増えただけ。ポートがぶつかるからここからのポートは3189で(一個ずらしただけカヨ)
認証無しのプロキシならこれで終了。
さて。認証の話に移ろうか。
さっきの(認証有りの)プロキシと組み合わせて見ると分かりますが、この組み合わせだと、「Proxy Authentication Required」と言われます。要するに上位のProxyサーバに問い合わせたらパスワードがねーよケッと言われてます。実はこの解決法は、「多人数に対して」多段プロキシを提供しないのであれば凄く簡単に解決できます。
#!/usr/bin/env ruby
require 'webrick'
require 'webrick/httpproxy'
require 'uri'
server = WEBrick::HTTPProxyServer.new({
:BindAddress => '127.0.0.1',
:Port => 3129,
:ProxyVia => false,
:ProxyURI => URI.parse('http://proxy_user:proxy_pass@localhost:3128')
})
trap('INT'){ server.shutdown }
server.start
ぶっちゃけ、:ProxyURIで指定するURIをhttp://ユーザ名:パスワード@サーバ名:ポート とするだけ。
この表記、httpの他の認証や、ftpのエセURL(ftp://anonymous:ituki@ftpserver/)とかにも使えます。覚えておくと便利かも。
まあ、ここまでは使ってる人が多い(?)と思われるのですんなり来ました。ここまでは
さて、今日みごとに踏み抜いた床を見てみましょう。死ぬかと思いました。
やりたかったこと:上位の認証有りのプロキシサーバに対して、複数ユーザを(上位で認証するIDとPASSを用いて)認証有りで、多段プロキシ
何言ってるか分かりますか?(笑)
先ほどは:ProxyURIで指定したproxy_userとproxy_passですが、今回は、人ごとに別のuserとpassが割当たっていて、親のproxyサーバのユーザとパスワードで認証したい。
当然ですが固定の人になるわけにはいかないので、URI.parseでIDとパスワードを指定する方法は使えません。
これ、どこかに正解あるのかなぁ……
と言う訳で、私なりの解です。
#!/usr/bin/env ruby
require 'webrick'
require 'webrick/httpproxy'
require 'uri'
module WEBrick
class HTTPProxyServerAuth < HTTPProxyServer
def proxy_auth(req, res)
if proc = @config[:ProxyAuthProc]
proc.call(req, res)
end
if req["Proxy-Authorization"] and (proxy = @config[:ProxyURI]) then
/^Basic\s+(.*)/o =~ req["Proxy-Authorization"]
up = ($1).unpack("m*")[0].split(":", 2)
proxy.user = up[0]
req.user = up[0]
proxy.password = up[1]
@config[:ProxyURI] = proxy
end
res["Proxy-Authenticate"] = "Basic realm=\"proxy\""
req.header.delete("proxy-authorization")
end
end
end
server = WEBrick::HTTPProxyServerAuth.new({
:BindAddress => '127.0.0.1',
:Port => 3129,
:ProxyVia => false,
:ProxyURI => URI.parse('http://localhost:3128')
})
trap('INT'){ server.shutdown }
server.start
(違ってたらゴメン)
もう魔法の言葉に見えるよママン。
HTTPProxyServerを継承したHTTPProxyServerAuthで、proxy_authで強引に:ProxyURIに書いてあったかのように書き換える作戦です。
変なヘッダ吐いてたらゴメン(^^; んでもって3129で待機してる(下位の)プロキシサーバに、407なのに認証したかのようにユーザ名が残るのは仕様です……いやなら21行目のreq.user = up[0]を削除のこと(ただし、認証が通っても誰か分からなくなります。多分(^^;)
誰かもっといい方法プリーズ!(笑)
◆ [情報] iTunes 8.1 登場。2 件の欠陥が修正
使ってる人はアップデート
◆ [情報] Acrobat 9.1 / Adobe Reader 9.1 出ました。
使ってる人は(ry
◆ [情報][ネタ] 若者はMP3の「雑音」がお好き?
ちと面白かったので