diff --git a/Makefile b/Makefile index c0ff43b..0627d7a 100644 --- a/Makefile +++ b/Makefile @@ -12,11 +12,11 @@ all: .libs/mod_proxy_protocol.so # build the so in the current directory .libs/mod_proxy_protocol.so: mod_proxy_protocol.c - $(APXS) -c -Wc,-Wall mod_proxy_protocol.c + $(APXS) -c mod_proxy_protocol.c # install the so - usually needs root access install: .libs/mod_proxy_protocol.so - $(APXS) -i mod_proxy_protocol.la + $(APXS) -i mod_proxy_protocol.c # generate the html doc docs: mod_proxy_protocol.html diff --git a/README.md b/README.md index eebeb68..cbc25bc 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,6 @@ This is an [Apache](http://httpd.apache.org/) module that implements the server side of HAProxy's [Proxy Protocol](http://blog.haproxy.com/haproxy/proxy-protocol/). -Note: as of Apache 2.4.30 this code has been merged into -[mod_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html), -with the `ProxyProtocol` directive renamed to `RemoteIPProxyProtocol`. - ## Build and Install You'll need the apache development packages installed (typically something diff --git a/debian/changelog b/debian/changelog index d732ac3..a01fa61 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,15 +1,3 @@ -mod-proxy-protocol (0.2-2) UNRELEASED; urgency=medium - - * Add patch for CVE-2019-10097 - - -- Mario Fetka Wed, 12 Feb 2020 11:54:28 +0100 - -mod-proxy-protocol (0.2-1) xenial; urgency=low - - * Merged patch to fix http/2 issues. - - -- Roadrunner2 Tue, 20 Mar 2018 02:11:49 -0700 - mod-proxy-protocol (0.1-1) trusty; urgency=low * Initial release diff --git a/debian/control b/debian/control index 596d88b..a0cdc0a 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Homepage: https://github.com/roadrunner2/mod-proxy-protocol Package: libapache2-mod-proxy-protocol Architecture: amd64 -Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211 +Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211, apache2 (>= 2.4.0) Description: Apache module for proxy protocol The proxy protocol is a way for upstream proxies and load-balancers to for the ip-address of the client to the server. This package contains diff --git a/debian/docs b/debian/docs index e980146..931c46d 100644 --- a/debian/docs +++ b/debian/docs @@ -1,4 +1,5 @@ README.md mod_proxy_protocol.xml mod_proxy_protocol.xml.meta +mod_proxy_protocol.html debian/README.Debian diff --git a/debian/rules b/debian/rules index f311f7d..db2bc2a 100755 --- a/debian/rules +++ b/debian/rules @@ -4,7 +4,7 @@ build: dh_testdir - make all # docs + make all docs clean: dh_testdir diff --git a/mod_proxy_protocol.c b/mod_proxy_protocol.c index e74fdf4..5766b80 100644 --- a/mod_proxy_protocol.c +++ b/mod_proxy_protocol.c @@ -80,37 +80,6 @@ static int pp_hook_pre_config(apr_pool_t *pconf, apr_pool_t *plog, return OK; } -#if !(APR_VERSION_AT_LEAST(1,5,0)) -static APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr) -{ - static const char inaddr_any[ -#if APR_HAVE_IPV6 - sizeof(struct in6_addr) -#else - sizeof(struct in_addr) -#endif - ] = {0}; - - if (addr->ipaddr_ptr /* IP address initialized */ - && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */ - if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) { - return 1; - } -#if APR_HAVE_IPV6 - if (addr->family == AF_INET6 - && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) { - struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3]; - - if (!memcmp(inaddr_any, v4, sizeof *v4)) { - return 1; - } - } -#endif - } - return 0; -} -#endif - /* Similar apr_sockaddr_equal, except that it compares ports too. */ static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2) { @@ -123,19 +92,37 @@ static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2) static int pp_sockaddr_compat(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2) { /* test exact address equality */ +#if !(APR_VERSION_AT_LEAST(1,5,0)) + apr_sockaddr_t addr0; + static const char inaddr_any[ sizeof(struct in_addr) ] = {0}; +#endif + if (apr_sockaddr_equal(addr1, addr2) && (addr1->port == addr2->port || addr1->port == 0 || addr2->port == 0)) { return 1; } +#if APR_VERSION_AT_LEAST(1,5,0) /* test address wildcards */ if (apr_sockaddr_is_wildcard(addr1) && (addr1->port == 0 || addr1->port == addr2->port)) { +#else + addr0.ipaddr_ptr = &inaddr_any; + addr0.ipaddr_len = addr1->ipaddr_len; + if (apr_sockaddr_equal(&addr0, addr1) && + (addr1->port == 0 || addr1->port == addr2->port)) { +#endif return 1; } +#if APR_VERSION_AT_LEAST (1,5,0) if (apr_sockaddr_is_wildcard(addr2) && (addr2->port == 0 || addr2->port == addr1->port)) { +#else + addr0.ipaddr_len = addr2->ipaddr_len; + if (apr_sockaddr_equal(&addr0, addr2) && + (addr2->port == 0 || addr2->port == addr1->port)) { +#endif return 1; } @@ -333,18 +320,6 @@ static int pp_hook_pre_connection(conn_rec *c, void *csd) pp_config *conf; pp_conn_config *conn_conf; - /* Establish master config in slave connections, so that request - * processing finds it. */ - if (c->master != NULL) { - conn_conf = ap_get_module_config(c->master->conn_config, - &proxy_protocol_module); - if (conn_conf) { - ap_set_module_config(c->conn_config, &proxy_protocol_module, - conn_conf); - } - return DECLINED; - } - /* check if we're enabled for this connection */ conf = ap_get_module_config(ap_server_conf->module_config, &proxy_protocol_module); @@ -404,7 +379,7 @@ static pp_parse_status_t pp_process_v1_header(conn_rec *c, proxy_header *hdr, apr_size_t len, apr_size_t *hdr_len) { - char *end, *word, *host, *valid_addr_chars, *saveptr; + char *end, *next, *word, *host, *valid_addr_chars, *saveptr; char buf[sizeof(hdr->v1.line)]; apr_port_t port; apr_status_t ret; @@ -513,6 +488,8 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c, proxy_header *hdr) { apr_status_t ret; + struct in_addr *in_addr; + struct in6_addr *in6_addr; switch (hdr->v2.ver_cmd & 0xF) { case 0x01: /* PROXY command */ @@ -550,17 +527,18 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c, break; default: - /* unsupported protocol */ - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183) - "RemoteIPProxyProtocol: unsupported protocol %.2hx", - (unsigned short)hdr->v2.fam); - return HDR_ERROR; + /* unsupported protocol, keep local connection address */ + return HDR_DONE; } break; /* we got a sockaddr now */ + case 0x00: /* LOCAL command */ + /* keep local connection address for LOCAL */ + return HDR_DONE; + default: /* not a supported command */ - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, "ProxyProtocol: unsupported command %.2hx", hdr->v2.ver_cmd); return HDR_ERROR; @@ -645,25 +623,12 @@ static apr_status_t pp_input_filter(ap_filter_t *f, /* try to read a header's worth of data */ while (!ctx->done) { if (APR_BRIGADE_EMPTY(ctx->bb)) { - apr_off_t got, want = ctx->need - ctx->rcvd; - ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want); + ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, + ctx->need - ctx->rcvd); if (ret != APR_SUCCESS) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10184) - "failed reading input"); return ret; } - - ret = apr_brigade_length(ctx->bb, 1, &got); - if (ret || got > want) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10185) - "RemoteIPProxyProtocol header too long, " - "got %" APR_OFF_T_FMT " expected %" APR_OFF_T_FMT, - got, want); - f->c->aborted = 1; - return APR_ECONNABORTED; - } } - if (APR_BRIGADE_EMPTY(ctx->bb)) { return APR_EOF; } @@ -707,20 +672,13 @@ static apr_status_t pp_input_filter(ap_filter_t *f, ctx->rcvd, &ctx->need); } else if (ctx->version == 2) { - proxy_header *hdr = (proxy_header *) ctx->header; - if (ctx->rcvd >= MIN_V2_HDR_LEN) { - ctx->need = MIN_V2_HDR_LEN + ntohs(hdr->v2.len); - if (ctx->need > sizeof(proxy_v2)) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(10186) - "RemoteIPProxyProtocol protocol header length too long"); - f->c->aborted = 1; - apr_brigade_destroy(ctx->bb); - return APR_ECONNABORTED; - } + ctx->need = MIN_V2_HDR_LEN + + ntohs(((proxy_header *) ctx->header)->v2.len); } if (ctx->rcvd >= ctx->need) { - psts = pp_process_v2_header(f->c, conn_conf, hdr); + psts = pp_process_v2_header(f->c, conn_conf, + (proxy_header *) ctx->header); } } else {