diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index af814cf..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,38 +0,0 @@ -stages: - - build - - deploy - -rpmbuild: - stage: build - image: gitlab-registry.cern.ch/cloud/ciadm - except: - - tags - script: - - if [ -z "$CI_BUILD_TAG" ]; then export CI_BUILD_TAG=$CI_DEFAULT_BUILD_TAG; fi - - export parser=(${CI_BUILD_TAG//-/ }) - - sed -i s/CERN_VERSION_PLACEHOLDER/${parser[0]}/g mod_proxy_protocol.spec - - sed -i s/CERN_RELEASE_PLACEHOLDER/${parser[1]}/g mod_proxy_protocol.spec - - curl https://gitlab.cern.ch/cloud-infrastructure/cloud-dev/raw/master/gitlab/rpmbuild.sh | bash - -kojicheck: - stage: build - image: gitlab-registry.cern.ch/cloud/ciadm - script: - - if [ -z "$CI_BUILD_TAG" ]; then export CI_BUILD_TAG=$CI_DEFAULT_BUILD_TAG; fi - - export parser=(${CI_BUILD_TAG//-/ }) - - sed -i s/CERN_VERSION_PLACEHOLDER/${parser[0]}/g mod_proxy_protocol.spec - - sed -i s/CERN_RELEASE_PLACEHOLDER/${parser[1]}/g mod_proxy_protocol.spec - - curl https://gitlab.cern.ch/cloud-infrastructure/cloud-dev/raw/master/gitlab/kojicheck.sh | bash - -kojibuild: - stage: deploy - image: gitlab-registry.cern.ch/cloud/ciadm - only: - - tags - script: - - export DIST='.el7.cern' - - if [ -z "$CI_BUILD_TAG" ]; then export CI_BUILD_TAG=$CI_DEFAULT_BUILD_TAG; fi - - export parser=(${CI_BUILD_TAG//-/ }) - - sed -i s/CERN_VERSION_PLACEHOLDER/${parser[0]}/g mod_proxy_protocol.spec - - sed -i s/CERN_RELEASE_PLACEHOLDER/${parser[1]}/g mod_proxy_protocol.spec - - curl https://gitlab.cern.ch/cloud-infrastructure/cloud-dev/raw/master/gitlab/kojibuild.sh | bash diff --git a/Makefile b/Makefile index 0627d7a..c0ff43b 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 mod_proxy_protocol.c + $(APXS) -c -Wc,-Wall mod_proxy_protocol.c # install the so - usually needs root access install: .libs/mod_proxy_protocol.so - $(APXS) -i mod_proxy_protocol.c + $(APXS) -i mod_proxy_protocol.la # generate the html doc docs: mod_proxy_protocol.html diff --git a/README.md b/README.md index cbc25bc..eebeb68 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ 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 a01fa61..47bcabd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +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 a0cdc0a..596d88b 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, apache2 (>= 2.4.0) +Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211 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 931c46d..e980146 100644 --- a/debian/docs +++ b/debian/docs @@ -1,5 +1,4 @@ README.md mod_proxy_protocol.xml mod_proxy_protocol.xml.meta -mod_proxy_protocol.html debian/README.Debian diff --git a/debian/lintian-overrides b/debian/lintian-overrides new file mode 100644 index 0000000..48369ea --- /dev/null +++ b/debian/lintian-overrides @@ -0,0 +1,2 @@ +libapache2-mod-proxy-protocol: apache2-module-depends-on-real-apache2-package +libapache2-mod-proxy-protocol: copyright-should-refer-to-common-license-file-for-apache-2 diff --git a/debian/rules b/debian/rules index db2bc2a..f311f7d 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 5766b80..e74fdf4 100644 --- a/mod_proxy_protocol.c +++ b/mod_proxy_protocol.c @@ -80,6 +80,37 @@ 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) { @@ -92,37 +123,19 @@ 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; } @@ -320,6 +333,18 @@ 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); @@ -379,7 +404,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, *next, *word, *host, *valid_addr_chars, *saveptr; + char *end, *word, *host, *valid_addr_chars, *saveptr; char buf[sizeof(hdr->v1.line)]; apr_port_t port; apr_status_t ret; @@ -488,8 +513,6 @@ 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 */ @@ -527,18 +550,17 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c, break; default: - /* unsupported protocol, keep local connection address */ - return HDR_DONE; + /* 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; } 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, ret, c, + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, "ProxyProtocol: unsupported command %.2hx", hdr->v2.ver_cmd); return HDR_ERROR; @@ -623,12 +645,25 @@ 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)) { - ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, - ctx->need - ctx->rcvd); + apr_off_t got, want = ctx->need - ctx->rcvd; + ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want); 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; } @@ -672,13 +707,20 @@ 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(((proxy_header *) ctx->header)->v2.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; + } } if (ctx->rcvd >= ctx->need) { - psts = pp_process_v2_header(f->c, conn_conf, - (proxy_header *) ctx->header); + psts = pp_process_v2_header(f->c, conn_conf, hdr); } } else { diff --git a/mod_proxy_protocol.spec b/mod_proxy_protocol.spec deleted file mode 100644 index 548f965..0000000 --- a/mod_proxy_protocol.spec +++ /dev/null @@ -1,72 +0,0 @@ -%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}} -%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn || echo missing-httpd-devel)}} -%{!?_httpd_confdir: %{expand: %%global _httpd_confdir %%{_sysconfdir}/httpd/conf.d}} -# /etc/httpd/conf.d with httpd < 2.4 and defined as /etc/httpd/conf.modules.d with httpd >= 2.4 -%{!?_httpd_modconfdir: %{expand: %%global _httpd_modconfdir %%{_sysconfdir}/httpd/conf.d}} -%{!?_httpd_moddir: %{expand: %%global _httpd_moddir %%{_libdir}/httpd/modules}} - -%global cern_version CERN_VERSION_PLACEHOLDER -%global cern_release CERN_RELEASE_PLACEHOLDER - -Name: mod_proxy_protocol -Summary: Apache module that implements the downstream server side of HAProxy's Proxy Protocol. -Version: %{cern_version} -Release: %{cern_release}%{?dist} -License: ASL 2.0 -Group: System Environment/Daemons -Source0: %{name}-%{version}.tar.gz -BuildRequires: httpd-devel -BuildRequires: gcc -BuildRequires: libtool -Requires: httpd -Requires: httpd-mmn = %{_httpd_mmn} - -# Suppress auto-provides for module DSO per -# https://fedoraproject.org/wiki/Packaging:AutoProvidesAndRequiresFiltering#Summary -%{?filter_provides_in: %filter_provides_in %{_libdir}/httpd/modules/.*\.so$} -%{?filter_setup} - -%description -HAProxy's Proxy Protocol is a way for upstream proxies and load balancers to -report the IP address of the original remote client to the downstream server, -without having to modify things like HTTP headers in the actual payload. -This package contains an Apache module that implements the downstream (i.e. the -receiving) server side of this protocol, thereby allowing other modules to see -and use the actual client's IP address instead of that of the upstream proxy or -load balancer. - -%prep -#%setup -q -n mod_proxy_protocol-%{version} -%setup -q -n %{name}-%{version} - -%build -%{_httpd_apxs} -c mod_proxy_protocol.c - -%install -rm -rf $RPM_BUILD_ROOT -install -Dm 755 .libs/mod_proxy_protocol.so $RPM_BUILD_ROOT%{_httpd_moddir}/mod_proxy_protocol.so - -%if "%{_httpd_modconfdir}" == "%{_httpd_confdir}" -# httpd <= 2.2.x -cat redhat/proxy_protocol.module > unified.conf -echo >> unified.conf -cat redhat/proxy_protocol.conf >> unified.conf -touch -c -r redhat/proxy_protocol.conf unified.conf -install -Dp -m 644 unified.conf $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf -%else -# httpd >= 2.4.x -install -Dp -m 644 redhat/proxy_protocol.module $RPM_BUILD_ROOT%{_httpd_modconfdir}/10-proxy_protocol.conf -install -Dp -m 644 redhat/proxy_protocol.conf $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf -%endif - -%files -%doc README.md LICENSE -%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}" -%config(noreplace) %{_httpd_modconfdir}/10-proxy_protocol.conf -%endif -%config(noreplace) %{_httpd_confdir}/proxy_protocol.conf -%{_httpd_moddir}/*.so - -%changelog -* Fri Dec 09 2016 Jose Castro Leon 0.1-1 -- First package release. diff --git a/redhat/mod_proxy_protocol.c-fix-apr14-compat.patch b/redhat/mod_proxy_protocol.c-fix-apr14-compat.patch deleted file mode 100644 index b51b514..0000000 --- a/redhat/mod_proxy_protocol.c-fix-apr14-compat.patch +++ /dev/null @@ -1,48 +0,0 @@ ---- mod_proxy_protocol.c-orig 2016-05-19 12:58:26.902187400 +0000 -+++ mod_proxy_protocol.c 2016-05-19 13:24:25.417638197 +0000 -@@ -44,6 +44,7 @@ - #include "ap_config.h" - #include "ap_listen.h" - #include "apr_strings.h" -+#include "apr_version.h" - - module AP_MODULE_DECLARE_DATA proxy_protocol_module; - -@@ -91,19 +92,37 @@ - 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; - } - diff --git a/redhat/mod_proxy_protocol.spec b/redhat/mod_proxy_protocol.spec deleted file mode 100644 index ac55116..0000000 --- a/redhat/mod_proxy_protocol.spec +++ /dev/null @@ -1,71 +0,0 @@ -%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn || echo 0-0)}} -%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}} -%{!?_httpd_confdir: %{expand: %%global _httpd_confdir %%{_sysconfdir}/httpd/conf.d}} -# /etc/httpd/conf.d with httpd < 2.4 and defined as /etc/httpd/conf.modules.d with httpd >= 2.4 -%{!?_httpd_modconfdir: %{expand: %%global _httpd_modconfdir %%{_sysconfdir}/httpd/conf.d}} -%{!?_httpd_moddir: %{expand: %%global _httpd_moddir %%{_libdir}/httpd/modules}} - -Name: mod_proxy_protocol -Summary: Apache module that implements the downstream server side of HAProxy's Proxy Protocol. -Version: 0.1 -Release: 1.20141031git62d2df6%{?dist} -License: ASL 2.0 -Group: System Environment/Daemons -Source0: https://github.com/roadrunner2/mod-proxy-protocol/archive/62d2df6c94eb0a18605e47f6236c08130d7e120d.tar.gz -Source1: proxy_protocol.module -Source2: proxy_protocol.conf -Patch0: mod_proxy_protocol.c-fix-apr14-compat.patch -BuildRequires: httpd-devel -Requires: httpd -URL: https://github.com/roadrunner2/mod-proxy-protocol - -# Suppress auto-provides for module DSO per -# https://fedoraproject.org/wiki/Packaging:AutoProvidesAndRequiresFiltering#Summary -%{?filter_provides_in: %filter_provides_in %{_libdir}/httpd/modules/.*\.so$} -%{?filter_setup} - -%description -HAProxy's Proxy Protocol is a way for upstream proxies and load balancers to -report the IP address of the original remote client to the downstream server, -without having to modify things like HTTP headers in the actual payload. -This package contains an Apache module that implements the downstream (i.e. the -receiving) server side of this protocol, thereby allowing other modules to see -and use the actual client's IP address instead of that of the upstream proxy or -load balancer. - -%prep -#%setup -q -n mod_proxy_protocol-%{version} -%setup -q -n mod-proxy-protocol-62d2df6c94eb0a18605e47f6236c08130d7e120d -%patch0 -p0 -F1 - -%build -%{_httpd_apxs} -c mod_proxy_protocol.c - -%install -rm -rf $RPM_BUILD_ROOT -install -Dm 755 .libs/mod_proxy_protocol.so $RPM_BUILD_ROOT%{_httpd_moddir}/mod_proxy_protocol.so - -%if "%{_httpd_modconfdir}" == "%{_httpd_confdir}" -# httpd <= 2.2.x -cat %{SOURCE1} > unified.conf -echo >> unified.conf -cat %{SOURCE2} >> unified.conf -touch -c -r %{SOURCE1} unified.conf -install -Dp -m 644 unified.conf $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf -%else -# httpd >= 2.4.x -install -Dp -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_httpd_modconfdir}/10-proxy_protocol.conf -install -Dp -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_httpd_confdir}/proxy_protocol.conf -%endif - -%files -%doc README.md LICENSE -%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}" -%config(noreplace) %{_httpd_modconfdir}/10-proxy_protocol.conf -%endif -%config(noreplace) %{_httpd_confdir}/proxy_protocol.conf -%{_httpd_moddir}/*.so - -%changelog -* Fri May 20 2016 earsdown 0.1-1.20141031git62d2df6 -- First package release. Includes mamanguy patch to fix APR 1.4.x compatibility. diff --git a/redhat/proxy_protocol.conf b/redhat/proxy_protocol.conf deleted file mode 100644 index f010951..0000000 --- a/redhat/proxy_protocol.conf +++ /dev/null @@ -1,3 +0,0 @@ - - #ProxyProtocol On - diff --git a/redhat/proxy_protocol.module b/redhat/proxy_protocol.module deleted file mode 100644 index 462835c..0000000 --- a/redhat/proxy_protocol.module +++ /dev/null @@ -1 +0,0 @@ -LoadModule proxy_protocol_module modules/mod_proxy_protocol.so