mod_extract_forwarded を改造
mod_proxy_http を使うかどうかでソースを書き換えなくちゃいけないのは面倒なので,APR の DSO 関数とか使ってがんばってみました。
本来は関数の hook は register_hooks
callback stage で登録するのが筋なんですが,ap_pre_config
hook で登録するという黒魔術を使ってます。これが ap_post_config
だとなぜか proxy_hook_scheme_handler
hook がうまく呼んでもらえないという罠((そんかわし,ap_pre_config
だとなぜか Apache 内的再起動のあおりを食わないというメリットもありました))。まさに黒魔術。
mod_proxy 等が DSO ではなく static link されてるとうまくいきません。まぁそこはそれ。あと win32 だと apr_dso_sym
で取得する関数のプロトタイプ typedef
が微妙なことになってしまうかも。
#ちなみに以前のパッチは作者には投げてあるんですが,レスポンスがありません
以下退屈なパッチが続きます。いつの日かどこぞに check-in するので,参考程度扱いで。
--- mod_extract_forwarded.c (revision 2) +++ mod_extract_forwarded.c (revision 8) @@ -117,16 +117,6 @@ #include <arpa/inet.h> #include <netinet/in.h> -/* - * #define USING_proxy_http_module if proxy_http.c module is either - * compiled into Apache 2 or it is being loaded as a DSO. If proxy_http.c - * module is not loaded then this module will generate an error when and - * if it is loaded as a DSO. In that case comment out the #define, recompile - * and reinstall this module. BUT do not forget to change things back if - * proxy_http.c module is reinstated - */ -#define USING_proxy_http_module 1 - /*--------------------------------------------------------------------------*/ /* */ /* Data declarations. */ @@ -758,7 +748,7 @@ { if (conf->debug == MEF_DEBUG_ON) { - fprintf(stderr,"MEF: phase:%s, $s not acceptabler proxy, %s\n", + fprintf(stderr,"MEF: phase:%s, %s not acceptabler proxy, %s\n", phase, conn->remote_ip, r->unparsed_uri); fflush(stderr); } @@ -925,6 +915,9 @@ * spoof one) is added to the X-Forwarded-For header. */ static int mef_before_proxy_http(request_rec *r, +#if AP_SERVER_MINORVERSION_NUMBER >= 2 + proxy_worker *worker, +#endif proxy_server_conf *pconf, char *url, const char *proxyname, apr_port_t proxyport) @@ -977,6 +970,97 @@ return DECLINED; } +static const char ID_MOD_ME[] = "mod_extract_forwarded"; +static const char ID_MOD_PROXY[] = "mod_proxy.c"; +static const char ID_MOD_PROXY_HTTP[] = "mod_proxy_http.c"; + +typedef PROXY_DECLARE(void) proxy_hook_scheme_handler_t + (proxy_HOOK_scheme_handler_t *pf, + const char * const *aszPre, const char * const *aszSucc, int nOrder); + +static module *mod_proxy_is_installed(apr_pool_t *p) +{ + module *mod_proxy; + + mod_proxy = ap_find_linked_module(ID_MOD_PROXY); + if (! mod_proxy) { + ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p, + "%s: mod_proxy is not loaded", ID_MOD_ME); + return NULL; + } + if (! ap_find_linked_module(ID_MOD_PROXY_HTTP)) { + ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p, + "%s: mod_proxy_http is not loaded", ID_MOD_ME); + return NULL; + } + + return mod_proxy; +} + +static int install_proxy_hook_scheme_handler(module *mod_proxy, apr_pool_t *p) +{ + static const char *const aszSucc[] = { ID_MOD_PROXY_HTTP, NULL }; + apr_status_t r; + apr_dso_handle_t *dso; + apr_dso_handle_sym_t handle_sym; + proxy_hook_scheme_handler_t *hook_scheme_handler; + + dso = (apr_dso_handle_t *) mod_proxy->dynamic_load_handle; + + if (! dso) { + ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p, + "%s: mod_proxy seems not to be DSO module", ID_MOD_ME); + return !OK; + } + + r = apr_dso_sym(&handle_sym, dso, "proxy_hook_scheme_handler"); + if (r != APR_SUCCESS) { + char my_error[256]; + + ap_log_perror(APLOG_MARK, APLOG_ERR, r, p, + "%s: couldn't get proxy_hook_scheme_handler (%s)", + ID_MOD_ME, + apr_dso_error(dso, my_error, sizeof(my_error))); + return !OK; + } + /* avoid warning for strict-aliasing */ + hook_scheme_handler = (proxy_hook_scheme_handler_t *) handle_sym; + + hook_scheme_handler(mef_before_proxy_http, NULL, aszSucc, + APR_HOOK_FIRST); + + ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p, + "%s: hook installed", ID_MOD_ME); + + return OK; +} + +/* + * NOTICE: + * ap_hook_post_config() is too late. + * ap_hook_pre_config() seems to be called only once + * whereas ap_hook_post_config() is called twice. + */ +static int mef_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) +{ + int r; + module *mod_proxy = mod_proxy_is_installed(p); + if (! mod_proxy) + return OK; + + /* + * Only need to register the following handlers if proxy_http_module + * is going to be loaded + */ + r = install_proxy_hook_scheme_handler(mod_proxy, p); + if (r != OK) + return r; + + ap_hook_log_transaction(mef_logging, NULL, NULL, APR_HOOK_FIRST); + + return OK; +} + /*--------------------------------------------------------------------------*/ /* */ /* Data structures pulling all the mef module's bits together */ @@ -987,6 +1071,8 @@ */ static void mef_register_hooks(apr_pool_t *p) { + ap_hook_pre_config(mef_pre_config, NULL, NULL, APR_HOOK_LAST); + ap_hook_post_read_request(mef_post_read_request, NULL, NULL, APR_HOOK_FIRST); ap_hook_translate_name(mef_uri_translate, NULL, NULL, APR_HOOK_FIRST); @@ -996,16 +1082,6 @@ * ap_hook_header_parser(mef_header_parser, NULL, NULL, APR_HOOK_FIRST); */ ap_hook_access_checker(mef_access_check, NULL, NULL, APR_HOOK_FIRST); -#ifdef USING_proxy_http_module - /* - * Only need to register the following handlers if proxy_http_module - * is going to be loaded - */ - static const char *const mef_proxy_b4[] = { "proxy_http.c", NULL }; - proxy_hook_scheme_handler(mef_before_proxy_http, NULL, mef_proxy_b4, - APR_HOOK_FIRST); - ap_hook_log_transaction(mef_logging, NULL, NULL, APR_HOOK_FIRST); -#endif /* USING_proxy_http_module */ } /*