From 1f8c682f72f8c18e3e825aa883d1ef8d8beab747 Mon Sep 17 00:00:00 2001 From: p0358 Date: Fri, 11 Aug 2017 12:51:46 +0200 Subject: [PATCH 1/7] Add CLOUDFLARE_CONNECTION env variable Untested yet, lol @reader, if I don't change anything, it probably works --- mod_cloudflare.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mod_cloudflare.c b/mod_cloudflare.c index 6631291..1d84e2b 100644 --- a/mod_cloudflare.c +++ b/mod_cloudflare.c @@ -282,11 +282,12 @@ static int cloudflare_modify_connection(request_rec *r) const char *cf_visitor_header = NULL; apr_pool_userdata_get((void*)&conn, "mod_cloudflare-conn", c->pool); + + apr_table_t *e = r->subprocess_env; cf_visitor_header = apr_table_get(r->headers_in, "CF-Visitor"); if (cf_visitor_header != NULL) { if ((remote) && (strstr(cf_visitor_header, "https") != NULL)) { - apr_table_t *e = r->subprocess_env; apr_table_addn(e, "HTTPS", "on"); } } @@ -371,6 +372,8 @@ static int cloudflare_modify_connection(request_rec *r) } else { break; } + } else { + apr_table_addn(e, "CLOUDFLARE_CONNECTION", "true"); } } From 5ec41ad97bc9eb6318b6d3acebedb784828643c2 Mon Sep 17 00:00:00 2001 From: p0358 Date: Fri, 11 Aug 2017 13:14:03 +0200 Subject: [PATCH 2/7] Info about fork, yes, it works! :) --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index cc5d0de..bdafdaa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,21 @@ # mod_cloudflare for Apache # Copyright CloudFlare Inc. 2016 +Modded by p0358 + +## FORK INFO ## + +This fork adds `CLOUDFLARE_CONNECTION` env variable set to "true" if connection originated from one of module's trusted proxy IPs. It is very useful since you cannot add `DenyAllButCloudflare` directive everywhere, but instead you can now use `Require env CLOUDFLARE_CONNECTION` or `Require expr "-T env('CLOUDFLARE_CONNECTION')"` (the latter example provided if you want to mix it with other expressions, you could also consider the first one inside `RequireAll` block instead). + +To use it (replacing the original mode if you already use it), simply clone it and use instructions from below. On Ubuntu/Debian you can just execute: + + git clone https://github.com/p0358/mod_cloudflare.git + cd mod_cloudflare + apt install apache2-dev + apxs2 -a -i -c mod_cloudflare.c + service apache2 restart + + ## mod_cloudflare.c ## Based on mod_remoteip.c, this Apache extension will replace the remote_ip variable in user's logs with the correct remote IP sent from CloudFlare. The module only performs the IP substitution for requests originating from CloudFlare IPs by default. From 2b368abdefa390cdd66f666d84aa5673e475818a Mon Sep 17 00:00:00 2001 From: p0358 Date: Fri, 11 Aug 2017 13:29:54 +0200 Subject: [PATCH 3/7] Add Debian/Ubuntu OS --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index bdafdaa..fc64b12 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ To use it (replacing the original mode if you already use it), simply clone it a apxs2 -a -i -c mod_cloudflare.c service apache2 restart +CloudFlare is welcome to implement this in their official repo :) + ## mod_cloudflare.c ## @@ -35,6 +37,7 @@ An alternative way to install is to use GNU autotools, which requires that autoc ### OS Support ### +- Debian/Ubuntu - Supported - CentOS - Supported - CloudLinux - Not Supported From ae04957cf6f13af6e72e933b6206a8cfb7efcbf7 Mon Sep 17 00:00:00 2001 From: p0358 Date: Fri, 11 Aug 2017 13:32:44 +0200 Subject: [PATCH 4/7] Addition --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc64b12..61a1290 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Modded by p0358 This fork adds `CLOUDFLARE_CONNECTION` env variable set to "true" if connection originated from one of module's trusted proxy IPs. It is very useful since you cannot add `DenyAllButCloudflare` directive everywhere, but instead you can now use `Require env CLOUDFLARE_CONNECTION` or `Require expr "-T env('CLOUDFLARE_CONNECTION')"` (the latter example provided if you want to mix it with other expressions, you could also consider the first one inside `RequireAll` block instead). -To use it (replacing the original mode if you already use it), simply clone it and use instructions from below. On Ubuntu/Debian you can just execute: +To use it (replacing the original mode if you already use it), simply clone it and use install instructions from below. Or on Ubuntu/Debian you can just execute: git clone https://github.com/p0358/mod_cloudflare.git cd mod_cloudflare From 1c846928878aa98cf85305b8e2c81f1c5314a29a Mon Sep 17 00:00:00 2001 From: p0358 Date: Sun, 18 Nov 2018 18:42:02 +0100 Subject: [PATCH 5/7] Add PHP script that updates module's config with latest CF IPs --- mod_cloudflare_conf_ip_update.php | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 mod_cloudflare_conf_ip_update.php diff --git a/mod_cloudflare_conf_ip_update.php b/mod_cloudflare_conf_ip_update.php new file mode 100644 index 0000000..c6cb447 --- /dev/null +++ b/mod_cloudflare_conf_ip_update.php @@ -0,0 +1,45 @@ +/mod_cloudflare_conf_ip_update.php +// +// Created by p0358 + +$list = ''; +$arr = []; + +$ipv4 = file_get_contents('https://www.cloudflare.com/ips-v4'); +$ipv6 = file_get_contents('https://www.cloudflare.com/ips-v6'); + +$ipv4_arr = explode("\n", trim($ipv4)); +foreach ($ipv4_arr as $line) { + $arr[] = trim($line); +} + +$ipv6_arr = explode("\n", trim($ipv6)); +foreach ($ipv6_arr as $line) { + $arr[] = trim($line); +} + +//$arr[] = ''; -- you can append your public server's IP(s) here too +$arr[] = '127.0.0.1'; +$arr[] = '::1'; + +$list = implode(' ', $arr); + +$datestring = date('Y-m-d H:i:s'); + +$content = << + CloudFlareRemoteIPHeader CF-Connecting-IP + CloudFlareRemoteIPTrustedProxy $list + #DenyAllButCloudFlare + +# Updated using mod_cloudflare_conf_ip_update.php by p0358 at $datestring +CONTENT; + +file_put_contents('/etc/apache2/mods-available/cloudflare.conf', $content); From 05025fba0c91f7477e54f307a2d42767758dc2d8 Mon Sep 17 00:00:00 2001 From: p0358 Date: Sun, 18 Nov 2018 18:43:03 +0100 Subject: [PATCH 6/7] Update IPs (one IPv6 range removed), add TODO to check if my mods work --- mod_cloudflare.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mod_cloudflare.c b/mod_cloudflare.c index 1d84e2b..e9b2140 100644 --- a/mod_cloudflare.c +++ b/mod_cloudflare.c @@ -59,7 +59,6 @@ static const char* CF_DEFAULT_TRUSTED_PROXY[] = { "198.41.128.0/17", /* IPv6 Address Ranges */ "2400:cb00::/32", - "2405:8100::/32", "2405:b500::/32", "2606:4700::/32", "2803:f800::/32", @@ -373,7 +372,7 @@ static int cloudflare_modify_connection(request_rec *r) break; } } else { - apr_table_addn(e, "CLOUDFLARE_CONNECTION", "true"); + apr_table_addn(e, "CLOUDFLARE_CONNECTION", "true"); // TODO: Check if this is indeed appended to each request, as I had some issues with random 403s (my Apache config denying if this env variable was not set) } } From f5e812a2e57727cf96d363f21f3b0288b00979ec Mon Sep 17 00:00:00 2001 From: p0358 Date: Sun, 18 Nov 2018 23:39:17 +0100 Subject: [PATCH 7/7] Did some proper verification of results before writing to config file As suggested by @AndreiG6 also on this other branch (soon should delete it I guess) --- mod_cloudflare_conf_ip_update.php | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/mod_cloudflare_conf_ip_update.php b/mod_cloudflare_conf_ip_update.php index c6cb447..59c6e36 100644 --- a/mod_cloudflare_conf_ip_update.php +++ b/mod_cloudflare_conf_ip_update.php @@ -14,15 +14,30 @@ $ipv4 = file_get_contents('https://www.cloudflare.com/ips-v4'); $ipv6 = file_get_contents('https://www.cloudflare.com/ips-v6'); +if (empty($ipv4) || empty($ipv6)) { + fwrite(STDERR, "Error: script could not download the latest IP ranges from Cloudflare\n"); + exit(1); +} $ipv4_arr = explode("\n", trim($ipv4)); -foreach ($ipv4_arr as $line) { - $arr[] = trim($line); +foreach ($ipv4_arr as &$line) { + // Source: https://www.regextester.com/98096 + if (preg_match('/^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2])))$/', trim($line), $matches)) { + $arr[] = $matches[1]; + } } $ipv6_arr = explode("\n", trim($ipv6)); -foreach ($ipv6_arr as $line) { - $arr[] = trim($line); +foreach ($ipv6_arr as &$line) { + // Source: https://www.regextester.com/93988 + if (preg_match('/^s*(((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?)$/', trim($line), $matches)) { + $arr[] = $matches[1]; + } +} + +if (empty($arr)) { + fwrite(STDERR, "Error: script got 0 results while trying to get the latest IP ranges from Cloudflare, terminating\n"); + exit(2); } //$arr[] = ''; -- you can append your public server's IP(s) here too