On Tue, 30 Jan 2007, Bogdan Ribic wrote:
Hi all,
I have a question - would it be possible to intercept an incomming
request, figure out if it is a proxy CONNECT request for remote https
server and then redirect to a local SSL site.
Specifically, can this be accomplished through a connection level
filter, for example by pulling enough data from user request to figure out
if it was a CONNECT request to an https url and if it is pull the request
header, then make a sub-request to local https site.
Yes, it's possible, but probably not the best approach. I needed something
similar, and I did it by replacing proxy_connect.c with a customized
version that can redirect CONNECT requests to other hosts. I'm guessing
that's the best approach to do what you need.
Attached is a diff against 2.0.54 of my new module. Should apply cleanly
to any recent 2.0.x, and with a little work to 2.2.x as well.
It introduces a new server configuration directive "ConnectRedirect":
ConnectRedirect <hostname> <hostname> <port>
For example, "ConnectRedirect www.example.com localhost 4443" will
redirect CONNECT requests for www.example.com to localhost, on port 4443.
Using * for the first hostname implements a wildcard redirect.
Hope this is useful.
Ernst Jan
--- httpd-2.0.54/modules/proxy/proxy_connect.c 2005-02-04 21:21:18.000000000
+0100
+++ proxy/proxy_connect.c 2005-09-10 17:07:05.000000000 +0200
@@ -23,6 +23,16 @@
module AP_MODULE_DECLARE_DATA proxy_connect_module;
+struct redirect_entry {
+ char *orighostname;
+ char *hostname;
+ int port;
+};
+
+typedef struct {
+ apr_array_header_t *redirects;
+} proxy_connect_server_conf;
+
int ap_proxy_connect_canon(request_rec *r, char *url);
int ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf,
char *url, const char *proxyname,
@@ -98,6 +108,10 @@
const char *connectname;
int connectport = 0;
+ server_rec *s = r->server;
+ proxy_connect_server_conf *cconf =
+ (proxy_connect_server_conf *) ap_get_module_config(s->module_config,
&proxy_connect_module);
+
/* is this for us? */
if (r->method_number != M_CONNECT) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
@@ -116,13 +130,35 @@
/* we break the URL into host, port, uri */
if (APR_SUCCESS != apr_uri_parse_hostinfo(p, url, &uri)) {
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
+ return ap_proxyerror(r, HTTP_BAD_REQUEST,
apr_pstrcat(p, "URI cannot be parsed: ", url,
NULL));
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
"proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname,
uri.port);
+ char *hn = NULL;
+ int pn = 0;
+ struct redirect_entry *entries = (struct redirect_entry *)
cconf->redirects->elts;
+ for(i=0; i<cconf->redirects->nelts; i++) {
+ if (!strcmp(entries[i].orighostname, "*")) {
+ hn = entries[i].hostname;
+ pn = entries[i].port;
+ continue;
+ }
+ if (!strcasecmp(entries[i].orighostname, uri.hostname)) {
+ hn = entries[i].hostname;
+ pn = entries[i].port;
+ break;
+ }
+ }
+ if (hn) {
+ uri.hostname = hn;
+ uri.port = pn;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: CONNECT: redirecting %s to %s:%d", url, uri.hostname,
uri.port);
+ }
+
/* do a DNS lookup for the destination host */
err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port,
0, p);
@@ -366,12 +402,54 @@
proxy_hook_canon_handler(ap_proxy_connect_canon, NULL, NULL,
APR_HOOK_MIDDLE);
}
+static const char *add_connect_redirect(cmd_parms *cmd, void *dummy, const
char *a1, const char *a2, const char *a3)
+{
+ server_rec *s = cmd->server;
+ proxy_connect_server_conf *conf =
+ (proxy_connect_server_conf *) ap_get_module_config(s->module_config,
&proxy_connect_module);
+ struct redirect_entry *new;
+
+ new = apr_array_push(conf->redirects);
+ new->orighostname = apr_pstrdup(cmd->pool, a1);
+ new->hostname = apr_pstrdup(cmd->pool, a2);
+ new->port = atoi(a3);
+
+ return NULL;
+}
+
+static const command_rec proxy_connect_cmds[] =
+{
+ AP_INIT_TAKE3("ConnectRedirect", add_connect_redirect, NULL, RSRC_CONF,
+ "Redirect CONNECT requests to the specified host and port"),
+ {NULL}
+};
+
+static void *create_proxy_connect_config(apr_pool_t *p, server_rec *s)
+{
+ proxy_connect_server_conf *ps = apr_pcalloc(p,
sizeof(proxy_connect_server_conf));
+
+ ps->redirects = apr_array_make(p, 10, sizeof(struct redirect_entry));
+
+ return ps;
+}
+
+static void * merge_proxy_connect_config(apr_pool_t *p, void *basev, void
*overridesv)
+{
+ proxy_connect_server_conf *ps = apr_pcalloc(p,
sizeof(proxy_connect_server_conf));
+ proxy_connect_server_conf *base = (proxy_connect_server_conf *) basev;
+ proxy_connect_server_conf *overrides = (proxy_connect_server_conf *)
overridesv;
+
+ ps->redirects = apr_array_append(p, base->redirects, overrides->redirects);
+
+ return ps;
+}
+
module AP_MODULE_DECLARE_DATA proxy_connect_module = {
STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ create_proxy_connect_config,/* create per-server config structure */
+ merge_proxy_connect_config, /* merge per-server config structures */
+ proxy_connect_cmds, /* command apr_table_t */
ap_proxy_connect_register_hook /* register hooks */
};