CVE-2012-どさにっき 〜2012年3月下旬〜

by やまや
<< = >>

2012年3月27日(火)

mod_lua でリバースプロクシ

_ もちろん apache 2.4、mod_lua が必要。さらに、mod_proxy と mod_proxy_http も。ProxyPass の設定は lua で置き替えるけど、よそにアクセスしにいく動作そのものは mod_proxy* がおこなうのでこいつらが不要になるわけではない。

-- httpd.conf
LuaHookTranslateName /path/to/proxy.lua reverse_proxy

-- proxy.lua
backend = "http://127.0.0.1:8080"

function reverse_proxy(r)
    r.handler = "proxy-server"
    r.proxyreq = apache2.PROXYREQ_REVERSE
    r.filename = "proxy:" .. backend .. r.uri
    return(apache2.OK)
end
なーんにも考えずに、うしろにただリクエストをまわすだけ。この程度なら素直に ProxyPass を使った方がずっとマシ。複雑な条件によってプロクシしたりしなかったりを制御しようとすると lua のうまみが出てくる。たとえば、上の例を
backend = { "http://...", "http://...", ... }

function backend_random(be)
    return(be[math.random(#be)])
end
backend_selector = backend_random

function reverse_proxy(r)
    r.handler = "proxy-server"
    r.proxyreq = apache2.PROXYREQ_REVERSE
    r.filename = "proxy:" .. backend_selector(backend) .. r.uri
    return(apache2.OK)
end
のように修正すると、複数のバックエンドに対してリクエストをランダムに振り分けるようなことが mod_proxy_balancer なしで実現できる。もちろん、関数をてきとーに書き換えればランダム以外の方法で振り分けることもできる。

_ その他、以前 mod_lua をいじったときの記録。開発版の 2.3 で mod_lua をあそんでみた 。2.4 で仕様が変わった DefaultType の挙動を mod_lua でエミュレートする

_ ほんとはこんなことしてあそんでる余裕はないはずなんだが。こういうときほど現実から逃げたくなるのが世の常。だって叩いても叩いてもバグが減らないんだもん…。


2012年3月30日(金)

mod_lua でさらにあそぶ

_ mod_mime の AddType とか AddCharset とかでやっていることを mod_lua にやらせてみるテスト。AddHogehoge と DefaultHogehoge 系の機能はほぼ実装してるけど、RemoveHogehoge は不可。hoge.html.utf-8 みたいな二重拡張子は可。DefaultType は実は mod_mime ではなく core の機能のため実装していない( こちらをどうぞ)。

-- httpd.conf
LuaHookTypeChecker /path/to/mod_mime.lua emulate_mod_mime
# その他 mod_mime をロードしないようにして、かつ関連ディレクティブ全削除

-- mod_mime.lua
mime_types = {	-- AddType
    ["html"] = "text/html",
    ["htm"] = "text/html",
    ["shtml"] = "text/html",
    ["txt"] = "text/plain",
    ["jpg"] = "image/jpeg",
    ["gif"] = "image/gif",
    ["png"] = "image/png",
    default = "text/plain"	-- DefaultType
}

charset = {	-- AddCharset
    ["euc"] = "EUC-JP",
    ["jis"] = "ISO-2022-JP",
    ["sjis"] = "SHIT_JIS",
    ["utf-8"] = "UTF-8",
    ["iso8859-1"] = "ISO-8859-1",
    -- default = "iso-8859-1"	-- AddDefaultCharset
}

language = {	-- AddLanguage
    ["ja"] = "ja",
    ["en"] = "en",
    -- default = "en"	-- DefaultLanguage
}

encoding = {	-- AddEncoding
    ["gz"] = "x-gzip",
    ["tgz"] = "x-gzip",
    ["z"] = "x-compress",
}

handler = {	-- AddHandler
    ["lua"] = "lua-script",
    ["cgi"] = "cgi-script",
    ["var"] = "type-map",
    ["asis"] = "send-as-is",
}

filter = {	-- AddOutputFilter
    ["shtml"] = "INCLUDES",
}

function emulate_mod_mime(r)
    local lang = language.default
    local cs = charset.default
    for suffix in r.filename:lower():gmatch"%.([%w_-]+)" do
        if mime_types[suffix] then
            r.content_type = mime_types[suffix]
        elseif language[suffix] then
            lang = language[suffix]
        elseif charset[suffix] then
            cs = charset[suffix]
        elseif encoding[suffix] then
            r.headers_out["Content-Encoding"] = encoding[suffix]
        elseif handler[suffix] then
            r.handler = handler[suffix]
        end
        --[[
        if filter[suffix] then
            r:add_output_filter(filter[suffix])
        end
        ]]
    end
    if r.content_type and r.content_type:lower():sub(1,5) == "text/" then
        if lang then
            r.headers_out["Content-Language"] = lang
        end
        if cs and not r.content_type:lower():match"charset=" then
            r.content_type = r.content_type .. "; charset=" .. cs
        end
    end
end

_ ドキュメントには r:addoutputfilter() というメソッドがあるように書いてますが、嘘です。正しくは r:add_output_filter() で、だけど使ってもフィルタかからない上、たまにせぐふぉで死にます。なので上ではコメントアウトしてます。使いかた間違ってないよねぇ? ほかにもドキュメントの嘘はたくさんあって、

とか。まあ、そういうわけで mod_lua はまだまだ実用レベルにはほど遠いので、遊ぶにはいいけどマジメな用途に使おうなんて思ってはいけない。


<< = >>
やまや