Lines 23-31
Link Here
|
23 |
#include "httpd.h" |
23 |
#include "httpd.h" |
24 |
#include "http_config.h" |
24 |
#include "http_config.h" |
25 |
#include "http_connection.h" |
25 |
#include "http_connection.h" |
26 |
#include "http_protocol.h" |
|
|
27 |
#include "http_log.h" |
26 |
#include "http_log.h" |
28 |
#include "http_main.h" |
27 |
#include "http_main.h" |
|
|
28 |
#include "http_protocol.h" |
29 |
#include "http_request.h" |
29 |
#include "apr_strings.h" |
30 |
#include "apr_strings.h" |
30 |
#include "apr_lib.h" |
31 |
#include "apr_lib.h" |
31 |
#define APR_WANT_BYTEFUNC |
32 |
#define APR_WANT_BYTEFUNC |
Lines 55-60
typedef struct {
Link Here
|
55 |
* from the proxy-via IP header value list) |
56 |
* from the proxy-via IP header value list) |
56 |
*/ |
57 |
*/ |
57 |
const char *proxies_header_name; |
58 |
const char *proxies_header_name; |
|
|
59 |
/** A header that may indicate user is using a |
60 |
* HTTPS connection to the reverse-proxy, and |
61 |
* the value that it must match for it to do so. |
62 |
*/ |
63 |
const char *secure_header_name; |
64 |
const char *secure_header_value; |
65 |
unsigned short secure_port; |
58 |
/** A list of trusted proxies, ideally configured |
66 |
/** A list of trusted proxies, ideally configured |
59 |
* with the most commonly encountered listed first |
67 |
* with the most commonly encountered listed first |
60 |
*/ |
68 |
*/ |
Lines 150-155
typedef struct {
Link Here
|
150 |
apr_sockaddr_t *client_addr; |
158 |
apr_sockaddr_t *client_addr; |
151 |
/** Character representation of the client */ |
159 |
/** Character representation of the client */ |
152 |
char *client_ip; |
160 |
char *client_ip; |
|
|
161 |
/** The port on which the proxy server received the connection */ |
162 |
unsigned short server_port; |
153 |
/** Flag indicating that the PROXY header may be omitted on this |
163 |
/** Flag indicating that the PROXY header may be omitted on this |
154 |
connection (do not abort if it is missing). */ |
164 |
connection (do not abort if it is missing). */ |
155 |
int proxy_protocol_optional; |
165 |
int proxy_protocol_optional; |
Lines 168-173
static void *create_remoteip_server_config(apr_pool_t *p, server_rec *s)
Link Here
|
168 |
* config->pp_optional = 0; |
178 |
* config->pp_optional = 0; |
169 |
*/ |
179 |
*/ |
170 |
config->pool = p; |
180 |
config->pool = p; |
|
|
181 |
config->secure_port = 443; |
171 |
return config; |
182 |
return config; |
172 |
} |
183 |
} |
173 |
|
184 |
|
Lines 191-196
static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv,
Link Here
|
191 |
config->pp_optional = server->pp_optional |
202 |
config->pp_optional = server->pp_optional |
192 |
? server->pp_optional |
203 |
? server->pp_optional |
193 |
: global->pp_optional; |
204 |
: global->pp_optional; |
|
|
205 |
config->secure_header_name = server->secure_header_name |
206 |
? server->secure_header_name |
207 |
: global->secure_header_name; |
208 |
config->secure_header_value = server->secure_header_value |
209 |
? server->secure_header_value |
210 |
: global->secure_header_value; |
211 |
config->secure_port = server->secure_port |
212 |
? server->secure_port |
213 |
: global->secure_port; |
194 |
return config; |
214 |
return config; |
195 |
} |
215 |
} |
196 |
|
216 |
|
Lines 212-217
static const char *proxies_header_name_set(cmd_parms *cmd, void *dummy,
Link Here
|
212 |
return NULL; |
232 |
return NULL; |
213 |
} |
233 |
} |
214 |
|
234 |
|
|
|
235 |
static const char *secure_header_set(cmd_parms *cmd, void *dummy, |
236 |
const char *name, const char *value) |
237 |
{ |
238 |
remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, |
239 |
&remoteip_module); |
240 |
if (!name || !value) |
241 |
return "SecureIndicatorHeader requires header name and valid value"; |
242 |
|
243 |
config->secure_header_name = name; |
244 |
config->secure_header_value = value; |
245 |
return NULL; |
246 |
} |
247 |
|
248 |
static int parse_validate_port(const char *src, unsigned short *dst) |
249 |
{ |
250 |
if (src) { |
251 |
char *tail; |
252 |
int intval; |
253 |
intval = apr_strtoi64(src, &tail, 0); |
254 |
if (errno == 0 && *tail == '\0' && intval > 0 && intval < 65536) { |
255 |
*dst = (unsigned short) intval; |
256 |
return 0; /* no error */ |
257 |
} |
258 |
return 2; /* not a number or invaid port range */ |
259 |
} |
260 |
return 1; /* null pointer */ |
261 |
} |
262 |
|
263 |
static const char *secure_port_set(cmd_parms *cmd, void *dummy, const char *value) |
264 |
{ |
265 |
remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, |
266 |
&remoteip_module); |
267 |
if (parse_validate_port(value, &config->secure_port)) |
268 |
return "SecureIndicatorSSLPort must be an integer between 0 and 65536"; |
269 |
|
270 |
return NULL; |
271 |
} |
272 |
|
215 |
/* Would be quite nice if APR exported this */ |
273 |
/* Would be quite nice if APR exported this */ |
216 |
/* apr:network_io/unix/sockaddr.c */ |
274 |
/* apr:network_io/unix/sockaddr.c */ |
217 |
static int looks_like_ip(const char *ipstr) |
275 |
static int looks_like_ip(const char *ipstr) |
Lines 506-511
static int remoteip_modify_request(request_rec *r)
Link Here
|
506 |
char *proxy_ips = NULL; |
564 |
char *proxy_ips = NULL; |
507 |
char *parse_remote; |
565 |
char *parse_remote; |
508 |
char *eos; |
566 |
char *eos; |
|
|
567 |
char *secure = NULL; |
509 |
unsigned char *addrbyte; |
568 |
unsigned char *addrbyte; |
510 |
|
569 |
|
511 |
/* If no RemoteIPInternalProxy, RemoteIPInternalProxyList, RemoteIPTrustedProxy |
570 |
/* If no RemoteIPInternalProxy, RemoteIPInternalProxyList, RemoteIPTrustedProxy |
Lines 540-545
static int remoteip_modify_request(request_rec *r)
Link Here
|
540 |
r->useragent_addr = conn_config->client_addr; |
599 |
r->useragent_addr = conn_config->client_addr; |
541 |
r->useragent_ip = conn_config->client_ip; |
600 |
r->useragent_ip = conn_config->client_ip; |
542 |
|
601 |
|
|
|
602 |
if (conn_config->server_port == config->secure_port) { |
603 |
apr_table_setn(r->subprocess_env, "HTTPS", "on"); |
604 |
} |
605 |
|
543 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
606 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
544 |
"Using %s as client's IP from PROXY protocol", r->useragent_ip); |
607 |
"Using %s as client's IP from PROXY protocol", r->useragent_ip); |
545 |
return OK; |
608 |
return OK; |
Lines 698-703
static int remoteip_modify_request(request_rec *r)
Link Here
|
698 |
return OK; |
761 |
return OK; |
699 |
} |
762 |
} |
700 |
|
763 |
|
|
|
764 |
if (config->secure_header_name) { |
765 |
secure = (char *) apr_table_get(r->headers_in, config->secure_header_name); |
766 |
} |
767 |
|
768 |
if (secure) { |
769 |
if (!strcmp(secure, config->secure_header_value)) { |
770 |
apr_table_setn(r->subprocess_env, "HTTPS", "on"); |
771 |
} |
772 |
/* Header is available. Unset even if no match. */ |
773 |
apr_table_unset(r->headers_in, config->secure_header_name); |
774 |
} |
775 |
else { |
776 |
secure = NULL; |
777 |
} |
778 |
|
701 |
/* Port is not known so set it to zero; otherwise it can be misleading */ |
779 |
/* Port is not known so set it to zero; otherwise it can be misleading */ |
702 |
req->useragent_addr->port = 0; |
780 |
req->useragent_addr->port = 0; |
703 |
|
781 |
|
Lines 724-736
static int remoteip_modify_request(request_rec *r)
Link Here
|
724 |
|
802 |
|
725 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
803 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
726 |
req->proxy_ips |
804 |
req->proxy_ips |
727 |
? "Using %s as client's IP by proxies %s" |
805 |
? "Using %s as client's IP by %s proxies %s via" |
728 |
: "Using %s as client's IP by internal proxies%s", |
806 |
: "Using %s as client's IP by %s internal proxies %s", |
729 |
req->useragent_ip, |
807 |
req->useragent_ip, |
|
|
808 |
secure ? "HTTPS" : "HTTP", |
730 |
(req->proxy_ips ? req->proxy_ips : "")); |
809 |
(req->proxy_ips ? req->proxy_ips : "")); |
731 |
return OK; |
810 |
return OK; |
732 |
} |
811 |
} |
733 |
|
812 |
|
|
|
813 |
static int remoteip_ssl_hook_Fixup(struct request_rec *r) |
814 |
{ |
815 |
request_rec *realreq = r; |
816 |
/* for internal redirect via mod_rewrite and other handlers */ |
817 |
while (realreq->prev && apr_table_get(realreq->subprocess_env, "REDIRECT_STATUS")) |
818 |
realreq = realreq->prev; |
819 |
|
820 |
const char* secure = apr_table_get(realreq->subprocess_env, "HTTPS"); |
821 |
if (secure && secure[0] == 'o' && secure[1] == 'n' && secure[2] == '\0') |
822 |
apr_table_setn(r->subprocess_env, "HTTPS", "on"); |
823 |
return OK; |
824 |
} |
825 |
|
826 |
static const char* remoteip_read_scheme(const request_rec *r) |
827 |
{ |
828 |
const char* secure = (const char *) apr_table_get(r->subprocess_env, "HTTPS"); |
829 |
if (secure && !strcmp(secure, "on")) |
830 |
return "https"; |
831 |
return NULL; |
832 |
} |
833 |
|
834 |
static unsigned short remoteip_read_port(const request_rec *r) |
835 |
{ |
836 |
const char* secure = (const char *) apr_table_get(r->subprocess_env, "HTTPS"); |
837 |
if (secure && !strcmp(secure, "on")) { |
838 |
remoteip_config_t *config = (remoteip_config_t *) |
839 |
ap_get_module_config(r->server->module_config, &remoteip_module); |
840 |
return config->secure_port; |
841 |
} |
842 |
return 0; |
843 |
} |
844 |
|
734 |
static int remoteip_is_server_port(apr_port_t port) |
845 |
static int remoteip_is_server_port(apr_port_t port) |
735 |
{ |
846 |
{ |
736 |
ap_listen_rec *lr; |
847 |
ap_listen_rec *lr; |
Lines 827-833
static remoteip_parse_status_t remoteip_process_v1_header(conn_rec *c,
Link Here
|
827 |
|
938 |
|
828 |
/* parse client-port */ |
939 |
/* parse client-port */ |
829 |
GET_NEXT_WORD("client-port") |
940 |
GET_NEXT_WORD("client-port") |
830 |
if (sscanf(word, "%hu", &port) != 1) { |
941 |
if (parse_validate_port(word, &port)) { |
831 |
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03501) |
942 |
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(03501) |
832 |
"RemoteIPProxyProtocol: error parsing port '%s' in header '%s'", |
943 |
"RemoteIPProxyProtocol: error parsing port '%s' in header '%s'", |
833 |
word, hdr->v1.line); |
944 |
word, hdr->v1.line); |
Lines 835-848
static remoteip_parse_status_t remoteip_process_v1_header(conn_rec *c,
Link Here
|
835 |
} |
946 |
} |
836 |
|
947 |
|
837 |
/* parse dest-port */ |
948 |
/* parse dest-port */ |
838 |
/* GET_NEXT_WORD("destination-port") - no-op since we don't care about it */ |
949 |
GET_NEXT_WORD("destination-port") |
|
|
950 |
|
951 |
if (parse_validate_port(word, &conn_conf->server_port)) { |
952 |
ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03502) |
953 |
"RemoteIPProxyProtocol: error parsing port '%s' in header '%s'", |
954 |
word, hdr->v1.line); |
955 |
return HDR_ERROR; |
956 |
} |
839 |
|
957 |
|
840 |
/* create a socketaddr from the info */ |
958 |
/* create a socketaddr from the info */ |
841 |
ret = apr_sockaddr_info_get(&conn_conf->client_addr, host, family, port, 0, |
959 |
ret = apr_sockaddr_info_get(&conn_conf->client_addr, host, family, port, 0, |
842 |
c->pool); |
960 |
c->pool); |
843 |
if (ret != APR_SUCCESS) { |
961 |
if (ret != APR_SUCCESS) { |
844 |
conn_conf->client_addr = NULL; |
962 |
conn_conf->client_addr = NULL; |
845 |
ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03502) |
963 |
ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, APLOGNO(03503) |
846 |
"RemoteIPProxyProtocol: error converting family '%d', host '%s'," |
964 |
"RemoteIPProxyProtocol: error converting family '%d', host '%s'," |
847 |
" and port '%hu' to sockaddr; header was '%s'", |
965 |
" and port '%hu' to sockaddr; header was '%s'", |
848 |
family, host, port, hdr->v1.line); |
966 |
family, host, port, hdr->v1.line); |
Lines 935-940
static remoteip_parse_status_t remoteip_process_v2_header(conn_rec *c,
Link Here
|
935 |
return HDR_ERROR; |
1053 |
return HDR_ERROR; |
936 |
} |
1054 |
} |
937 |
|
1055 |
|
|
|
1056 |
conn_conf->server_port = hdr->v2.addr.ip4.dst_port; |
938 |
conn_conf->client_addr->sa.sin.sin_addr.s_addr = |
1057 |
conn_conf->client_addr->sa.sin.sin_addr.s_addr = |
939 |
hdr->v2.addr.ip4.src_addr; |
1058 |
hdr->v2.addr.ip4.src_addr; |
940 |
break; |
1059 |
break; |
Lines 951-956
static remoteip_parse_status_t remoteip_process_v2_header(conn_rec *c,
Link Here
|
951 |
"RemoteIPProxyProtocol: error creating sockaddr"); |
1070 |
"RemoteIPProxyProtocol: error creating sockaddr"); |
952 |
return HDR_ERROR; |
1071 |
return HDR_ERROR; |
953 |
} |
1072 |
} |
|
|
1073 |
conn_conf->server_port = hdr->v2.addr.ip6.dst_port; |
954 |
memcpy(&conn_conf->client_addr->sa.sin6.sin6_addr.s6_addr, |
1074 |
memcpy(&conn_conf->client_addr->sa.sin6.sin6_addr.s6_addr, |
955 |
hdr->v2.addr.ip6.src_addr, 16); |
1075 |
hdr->v2.addr.ip6.src_addr, 16); |
956 |
break; |
1076 |
break; |
Lines 1232-1237
static const command_rec remoteip_cmds[] =
Link Here
|
1232 |
RSRC_CONF | EXEC_ON_READ, |
1352 |
RSRC_CONF | EXEC_ON_READ, |
1233 |
"The filename to read the list of internal proxies, " |
1353 |
"The filename to read the list of internal proxies, " |
1234 |
"see the RemoteIPInternalProxy directive"), |
1354 |
"see the RemoteIPInternalProxy directive"), |
|
|
1355 |
AP_INIT_TAKE2("SecureIndicatorHeader", secure_header_set, NULL, RSRC_CONF, |
1356 |
"Specifies a request header and value that indicates a secure connection, " |
1357 |
"e.g. \"X-Forwarded-Proto https\" or \"X-Secure-Connection on\""), |
1358 |
AP_INIT_TAKE1("SecureIndicatorSSLPort", secure_port_set, NULL, RSRC_CONF, |
1359 |
"Port to be used for redirections if SecureIndicatorHeader is set, " |
1360 |
"Default is \"SecureInidcatorSSLPort 443\" "), |
1235 |
AP_INIT_TAKE1("RemoteIPProxyProtocol", remoteip_enable_proxy_protocol, NULL, |
1361 |
AP_INIT_TAKE1("RemoteIPProxyProtocol", remoteip_enable_proxy_protocol, NULL, |
1236 |
RSRC_CONF, "Enable PROXY protocol handling (`on', `off', `optional')"), |
1362 |
RSRC_CONF, "Enable PROXY protocol handling (`on', `off', `optional')"), |
1237 |
{ NULL } |
1363 |
{ NULL } |
Lines 1249-1254
static void register_hooks(apr_pool_t *p)
Link Here
|
1249 |
ap_hook_post_config(remoteip_hook_post_config, NULL, NULL, APR_HOOK_MIDDLE); |
1375 |
ap_hook_post_config(remoteip_hook_post_config, NULL, NULL, APR_HOOK_MIDDLE); |
1250 |
ap_hook_pre_connection(remoteip_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); |
1376 |
ap_hook_pre_connection(remoteip_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); |
1251 |
ap_hook_post_read_request(remoteip_modify_request, NULL, NULL, APR_HOOK_FIRST); |
1377 |
ap_hook_post_read_request(remoteip_modify_request, NULL, NULL, APR_HOOK_FIRST); |
|
|
1378 |
ap_hook_http_scheme(remoteip_read_scheme, NULL, NULL, APR_HOOK_FIRST); |
1379 |
ap_hook_default_port(remoteip_read_port, NULL, NULL, APR_HOOK_FIRST); |
1380 |
ap_hook_fixups(remoteip_ssl_hook_Fixup, NULL, NULL, APR_HOOK_MIDDLE); |
1252 |
} |
1381 |
} |
1253 |
|
1382 |
|
1254 |
AP_DECLARE_MODULE(remoteip) = { |
1383 |
AP_DECLARE_MODULE(remoteip) = { |