From 5c1673b29f2e4cf4a9efd445d29eb2715291e292 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 5 Apr 2020 14:14:31 +0200 Subject: [PATCH] Allow Apache-friendly fine-tuning --- xExtension-ImageProxy/README.md | 49 ++++++++++++++- xExtension-ImageProxy/configure.phtml | 35 ++++++++++- xExtension-ImageProxy/extension.php | 90 +++++++++++++++++++++------ xExtension-ImageProxy/i18n/en/ext.php | 6 +- xExtension-ImageProxy/i18n/fr/ext.php | 6 +- xExtension-ImageProxy/metadata.json | 2 +- 6 files changed, 162 insertions(+), 26 deletions(-) diff --git a/xExtension-ImageProxy/README.md b/xExtension-ImageProxy/README.md index b26f744..b51e2e5 100644 --- a/xExtension-ImageProxy/README.md +++ b/xExtension-ImageProxy/README.md @@ -4,10 +4,57 @@ This FreshRSS extension allows you to get rid of insecure content warnings or di To use it, upload this entire directory to the FreshRSS `./extensions` directory on your server and enable it on the extension panel in FreshRSS. +## Configuration settings + +* `proxy_url` (default: `https://images.example.com/?url=`): the URL that is prependended to the original image URL + +* `scheme_http` (default: `1`): whether to proxy HTTP resources + +* `scheme_https` (default: `0`): whether to proxy HTTPS resources + +* `scheme_default` (default: `http`): which scheme to use for resources that do not include one (if set to `-`, those will not be proxied) + +* `scheme_include` (default: `0`): whether to include the scheme - `http*://` - in the proxied URL + +* `url_encode` (default: `1`): whether to URL-encode (RFC 3986) the proxied URL + ## Proxy Settings By default this extension will use the [images.weserv.nl](https://images.weserv.nl) image caching and resizing proxy, but instead you can supply your own proxy URL in the settings. An example URL would look like ``https://images.example.com/?url=``. +By ticking the `scheme_https` checkbox, you can also force the use of the proxy, even for images coming through an encrypted channel. This makes the server that hosts your FreshRSS instance the only point of entry for images, preventing your client from connecting directly to the RSS sources to recover them (which could be a privacy concern in extreme cases). + The source code for the images.weserv.nl proxy can be found at [github.com/andrieslouw/imagesweserv](https://github.com/andrieslouw/imagesweserv), but of course other methods are available. For example, in Apache you could [use `mod_rewrite` to set up a simple proxy](https://httpd.apache.org/docs/2.2/rewrite/proxy.html) and similar methods are available in nginx and lighttpd. Alternatively you could use a simple PHP script, [along these lines](https://github.com/Alexxz/Simple-php-proxy-script). Keep in mind that too simple a proxy could introduce security risks, which is why the default proxy processes the images. -By ticking the dedicated checkbox, you can also force the use of the proxy, even for images coming through an encrypted channel. This makes the server that hosts your FreshRSS instance the only point of entry for images, preventing your client from connecting directly to the RSS sources to recover them (which could be a privacy concern in extreme cases). +### Apache configuration + +In order to use Apache `mod_rewrite`, you will need to set the following settings: + +* `proxy_url` = ``https://www.example.org/proxy/`` + +* `scheme_include` = **1** + +* `url_encode` = **0** + +Along the following Apache configuration for the `www.example.org` virtual host: + +``` + # WARNING: Multiple '/' are trimmed to a single one! + RewriteCond %{REQUEST_URI} ^/proxy/https:/+(.*)$ + RewriteRule ^ https://%1 [QSA,P,L] + RewriteCond %{REQUEST_URI} ^/proxy/http:/+(.*)$ + RewriteRule ^ http://%1 [QSA,P,L] + + # CRITICAL: Do NOT leave your proxy opened to everyone!!! + # Local network + Require ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 + # Users + AuthType Basic + AuthName "Proxy - Authorized Users ONLY" + AuthBasicProvider file + AuthUserFile /etc/apache2/htpasswd/users + Require valid-user + # Local network OR authenticated users + Satisfy any + +``` diff --git a/xExtension-ImageProxy/configure.phtml b/xExtension-ImageProxy/configure.phtml index 6060f40..2e054f0 100644 --- a/xExtension-ImageProxy/configure.phtml +++ b/xExtension-ImageProxy/configure.phtml @@ -5,9 +5,40 @@
- + +
+
- image_proxy_force ? 'checked' : ''); ?>> + image_proxy_scheme_http ? 'checked' : ''); ?>> +
+
+
+ +
+ image_proxy_scheme_https ? 'checked' : ''); ?>> +
+
+
+ +
+ +
+
+
+ +
+ image_proxy_scheme_include ? 'checked' : ''); ?>> +
+
+
+ +
+ image_proxy_url_encode ? 'checked' : ''); ?>>
diff --git a/xExtension-ImageProxy/extension.php b/xExtension-ImageProxy/extension.php index f040ff0..8d0e5fe 100644 --- a/xExtension-ImageProxy/extension.php +++ b/xExtension-ImageProxy/extension.php @@ -1,45 +1,95 @@ registerHook('entry_before_display', array('ImageProxyExtension', 'setImageProxyHook')); - - if (FreshRSS_Context::$user_conf->image_proxy_url != '') { - self::$proxy_url = FreshRSS_Context::$user_conf->image_proxy_url; + // Defaults + $save = false; + if (is_null(FreshRSS_Context::$user_conf->image_proxy_url)) { + FreshRSS_Context::$user_conf->image_proxy_url = self::PROXY_URL; + $save = true; + } + if (is_null(FreshRSS_Context::$user_conf->image_proxy_scheme_http)) { + FreshRSS_Context::$user_conf->image_proxy_scheme_http = self::SCHEME_HTTP; + $save = true; + } + if (is_null(FreshRSS_Context::$user_conf->image_proxy_scheme_https)) { + FreshRSS_Context::$user_conf->image_proxy_scheme_https = self::SCHEME_HTTPS; + // Legacy + if (!is_null(FreshRSS_Context::$user_conf->image_proxy_force)) { + FreshRSS_Context::$user_conf->image_proxy_scheme_https = FreshRSS_Context::$user_conf->image_proxy_force; + FreshRSS_Context::$user_conf->image_proxy_force = null; // Minz -> unset + } + $save = true; + } + if (is_null(FreshRSS_Context::$user_conf->image_proxy_scheme_default)) { + FreshRSS_Context::$user_conf->image_proxy_scheme_default = self::SCHEME_DEFAULT; + $save = true; + } + if (is_null(FreshRSS_Context::$user_conf->image_proxy_scheme_include)) { + FreshRSS_Context::$user_conf->image_proxy_scheme_include = self::SCHEME_INCLUDE; + $save = true; + } + if (is_null(FreshRSS_Context::$user_conf->image_proxy_url_encode)) { + FreshRSS_Context::$user_conf->image_proxy_url_encode = self::URL_ENCODE; + $save = true; + } + if ($save) { + FreshRSS_Context::$user_conf->save(); } } - public static $proxy_url = 'https://images.weserv.nl/?url='; - public function handleConfigureAction() { $this->registerTranslates(); if (Minz_Request::isPost()) { - FreshRSS_Context::$user_conf->image_proxy_url = Minz_Request::param('image_proxy_url', ''); - FreshRSS_Context::$user_conf->image_proxy_force = Minz_Request::param('image_proxy_force', ''); + FreshRSS_Context::$user_conf->image_proxy_url = Minz_Request::param('image_proxy_url', self::PROXY_URL); + FreshRSS_Context::$user_conf->image_proxy_scheme_http = Minz_Request::param('image_proxy_scheme_http', ''); + FreshRSS_Context::$user_conf->image_proxy_scheme_https = Minz_Request::param('image_proxy_scheme_https', ''); + FreshRSS_Context::$user_conf->image_proxy_scheme_default = Minz_Request::param('image_proxy_scheme_default', self::SCHEME_DEFAULT); + FreshRSS_Context::$user_conf->image_proxy_scheme_include = Minz_Request::param('image_proxy_scheme_include', ''); + FreshRSS_Context::$user_conf->image_proxy_url_encode = Minz_Request::param('image_proxy_url_encode', ''); FreshRSS_Context::$user_conf->save(); } } public static function getProxyImageUri($url) { $parsed_url = parse_url($url); - if (isset($parsed_url['scheme']) && $parsed_url['scheme'] === 'http') { - $url = self::$proxy_url . rawurlencode(substr($url, strlen('http://'))); + $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] : null; + if ($scheme === 'http') { + if (!FreshRSS_Context::$user_conf->image_proxy_scheme_http) return $url; + if (!FreshRSS_Context::$user_conf->image_proxy_scheme_include) { + $url = substr($url, 7); // http:// + } } - // force proxy even with https, if set by the user - else if (isset($parsed_url['scheme']) && - $parsed_url['scheme'] === 'https' && - FreshRSS_Context::$user_conf->image_proxy_force) { - $url = self::$proxy_url . rawurlencode(substr($url, strlen('https://'))); + else if ($scheme === 'https') { + if (!FreshRSS_Context::$user_conf->image_proxy_scheme_https) return $url; + if (!FreshRSS_Context::$user_conf->image_proxy_scheme_include) { + $url = substr($url, 8); // https:// + } } - // oddly enough there are protocol-less IMG SRC attributes that don't actually work with HTTPS - // so I guess we should just run 'em all through the proxy - else if (empty($parsed_url['scheme'])) { - $url = self::$proxy_url . rawurlencode($url); + else if (empty($scheme)) { + if (substr(FreshRSS_Context::$user_conf->image_proxy_scheme_default,0, 4) !== 'http') return $url; + if (FreshRSS_Context::$user_conf->image_proxy_scheme_include) { + $url = FreshRSS_Context::$user_conf->image_proxy_scheme_default . '://' . $url; + } } - - return $url; + else { // unknown/unsupported (non-http) scheme + return $url; + } + if (FreshRSS_Context::$user_conf->image_proxy_url_encode) { + $url = rawurlencode($url); + } + return FreshRSS_Context::$user_conf->image_proxy_url . $url; } public static function getSrcSetUris($matches) { diff --git a/xExtension-ImageProxy/i18n/en/ext.php b/xExtension-ImageProxy/i18n/en/ext.php index a39c54d..1b7b041 100644 --- a/xExtension-ImageProxy/i18n/en/ext.php +++ b/xExtension-ImageProxy/i18n/en/ext.php @@ -3,7 +3,11 @@ return array( 'imageproxy' => array( 'proxy_url' => 'Proxy URL', - 'force' => 'Force proxying, even for https', + 'scheme_http' => 'Proxy HTTP', + 'scheme_https' => 'Proxy HTTPS', + 'scheme_default' => 'Proxy unspecified', + 'scheme_include' => 'Include http*:// in URL', + 'url_encode' => 'Encode the URL', 'true' => 'On', 'false' => 'Off', ), diff --git a/xExtension-ImageProxy/i18n/fr/ext.php b/xExtension-ImageProxy/i18n/fr/ext.php index 745b945..2b27caf 100644 --- a/xExtension-ImageProxy/i18n/fr/ext.php +++ b/xExtension-ImageProxy/i18n/fr/ext.php @@ -3,7 +3,11 @@ return array( 'imageproxy' => array( 'proxy_url' => 'URL du proxy', - 'force' => 'Toujours utiliser le proxy, même en https', + 'scheme_http' => 'Proxy HTTP', + 'scheme_https' => 'Proxy HTTPS', + 'scheme_default' => 'Proxy indéterminées', + 'scheme_include' => 'Inclure http*:// dans l\'URL', + 'url_encode' => 'Encoder l\'URL', 'true' => 'Oui', 'false' => 'Non', ), diff --git a/xExtension-ImageProxy/metadata.json b/xExtension-ImageProxy/metadata.json index 82aec32..0eb908a 100644 --- a/xExtension-ImageProxy/metadata.json +++ b/xExtension-ImageProxy/metadata.json @@ -2,7 +2,7 @@ "name": "Image Proxy", "author": "Frans de Jonge", "description": "No insecure content warnings or disappearing images.", - "version": 0.4, + "version": 0.5, "entrypoint": "ImageProxy", "type": "user" }