Force HTTPS / Mod-rewrite behind reverse proxy (with WordPress) - apache

Forgive my lack of knowledge in this area.
First, our situation: We have a reverse proxy setup where we have http://www.xxx.ca/x and sometimes http://www.xxx.ca/x/y is forwarded to http://xxx1a.xxx.ca/x or http://xxx1a.xxx.ca/x/y
We have been trying to create a generic .htaccess where we do not have to define any subdirectories specifically. Basically, we can use this .htaccess on 100's of sites without modifying the file on a site by site basis.
We have gotten this part working. However, we are unable to force https. Every example I see uses HTTP_HOST, which returns the value of the proxied server - not the original request.
Perhaps there is a completely different solution to what we have setup, but my knowledge of apache is limited. Below is what we currently have - which solves the generic sub-folder issue, but not the HTTPS issue.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{ENV:URI} ^$
RewriteRule ^(.*)$ - [ENV=URI:$1]
RewriteCond %{ENV:BASE} ^$
RewriteCond %{ENV:URI}::%{REQUEST_URI} ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=BASE:%2]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . %{ENV:BASE}index.php [L,QSA]
</IfModule>
I am completely willing to change 100% of this if there is a better solution.

I'm not sure I have understood when you have to redirect the user to https. Anyway, when you have to switch to https, you could just check SERVER_PORT server internal variable and if is not 80 then redirect:
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{ENV:URI}/$1 [L,R=301]

Related

Redirect domain to other domains subdirectory but show first domain in address bar?

I'd like to redirect "abc.com" to "xyz.com/abc" but still, show "abc.com" in the browser's address bar. As far as I understand you'd be using rewrite rules to achieve this.
I own both domains and both pages are on the same server.
Its an ionos webserver. The website itself is located in
/clickandbuilds/mywebsite (lets say this is "xyz.com")
Now there is a subpage on this website ("xyz.com/my-landing-page")
that is also accessible over its own domain (lets say "abc.com")
Right now im using a simple http redirect and all requests to "abc.com get redirected to "xyz.com/my-landing-page". This is the exact thing that I want but I do not want to show the url of the landing-page but the top-level-domain (xyz.
How would this condition look like?
htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
AddHandler x-mapp-php5.5 .php
# BEGIN rlrssslReallySimpleSSL rsssl_version[3.3.5]
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !=on [NC]
RewriteCond %{REQUEST_URI} !wp-content\/cache\/(all|wpfc-mobile-cache)
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
You have two obvious options, which one is better for you depends a bit on the specific situation:
an internal rewriting strategy:
You need to take care that the rewriting module is actually loaded into the http server. Then you can implement that rule:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^abc\.com$
RewriteCond %{REQUEST_URI} !^/abc
RewriteRule ^ /abc%{REQUEST_URI} [QSA,END]
This approach can be implemented in the actual http server's host configuration (which should be preferred) or in a distributed configuration file (".htaccess") in case you do not have access to the real configuration (read: if you are using a cheap hosting provider).
an internal proxy strategy:
Instead of using the rewriting module you could directly use the proxy module:
ProxyPass / https://example.com/abc/
ProxyPassReverse / https://example.com/abc/
This needs to be implemented in the actual http server's host configuration, however. So you'd need access to that.
The same could be achieved using the rewriting module (which uses the proxy module internally). This would allow to use distributed configuration file (".htaccess") for this approach too:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^abc\.com$
RewriteCond %{REQUEST_URI} !^/abc
RewriteRule ^ https://example.com/abc%{REQUEST_URI} [P]
Both proxy based options share the disadvantage that performance is an issue due to the fact that you need a full additional internal http request for each and every incoming request.
In general the first approach makes more sense, out of performance reasons. This has to be supported by your application logic however: this will only work if your application uses relative references ("links"). If it uses absolute URLs instead and you cannot change that you will need to dive into the second approach.

htacess redirect subsomains to root domain and force www

Hi I have an annoying issue that I am trying to redirect all subdomains to root domain and force www. At the moment it forces www as needed but if I go to sub.example.dom I am able to and this is what I am trying to prevent. Here is my htaccess file.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
RewriteRule ^service-description/([+a-zA-Z0-9]+)/([+a-zA-Z0-9]+)\.html$ /location.php?city=$1&process=$2 [L]
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
The direct approach is to add another rewriting rule that redirects all requests to host names not starting with www:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule ^/?(.*)$ https://www.example.com/$1 [R=301]
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteCond %{HTTP_HOST} ^.*\.example\.com$
RewriteRule ^/?(.*)$ https://www.example.com/$1 [R=301]
You can actually simplify this if your http server does not answer to other second level domains or if you want to redirect all requests regardless of which host name they target:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteRule ^/?(.*)$ https://www.example.com/$1 [R=301]
Those rule sets will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and in case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

.htaccess file not redirecting http://www. to https://www

I have made a .htaccess file to redirect all website traffic to https://www..
This is my complete .htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
The below redirects work exactly as expected:
http://example.com -> https://www.example.com
https://example.com -> https://www.example.com
https://www.example.com -> https://www.example.com
Except:
http://www.example.com -> http://www.example.com
As shown above, if you go to http://www. it doesn't redirect to the HTTPS version.
Can anyone help me understand why the other redirects are working fine, but that one is not?
Additional Notes: I have looked at a number of posts on StackOverflow, but most of their solutions end in redirect loop errors.
After contacting 123-Reg (my hosting provider), they submitted this solution, which works perfectly:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301,NC]
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
Basically they have set the script to do two tasks: Change domain to WWW, if it isn't already, THEN change to HTTPS. Also, they used ENV:HTTPS, which is different to what was found in their documentation (ENV:SSL).
Glad to have to this sorted, and maybe this will help out others using 123-Reg Hosting.
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
As you have found, this won't redirect when requesting the canonical hostname (ie. www.example.com) regardless of whether it is HTTP or HTTPS.
You need to change this to something like:
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
This will trigger a redirect to the canonical URL if HTTPS is "off" or it's not the canonical hostname.
...but most of their solutions end in redirect loop errors.
If you are behind a proxy (eg. CloudFlare) that is managing your SSL cert then this could still result in a redirect loop because the connection between you and the proxy might be HTTP, not HTTPS. This would mean that your server only serves content over HTTP, not HTTPS. If this is the case then there are additional headers that can be checked on the request (eg. X-Forwarded-Proto) or set a "page rule" in the case of CloudFlare (Flexible SSL - free service).
UPDATE#1: 123-Reg provide a help document regarding SSL. It seems they set an SSL environment variable when "the connection is SSL-secured". This would mean that you could potentially do something like the following instead:
RewriteCond %{ENV:SSL} ^$ [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
This is, however, non-standard and "unique" to 123-Reg. (Aside: The PHP code suggestion in the 123-Reg linked document is not the recommended way to check the environment variable, as this would result in an E_NOTICE if the variable is not set!?)
You should also ensure your browser cache is cleared before testing.
UPDATE#2: To help with debugging... to find out what values are being returned, you could assign some Apache values to environment variables and check the values of these in your server-side script (eg. PHP?). For example:
RewriteCond %{HTTPS} (.*)
RewriteRule ^ - [E=APACHE_HTTPS:%1]
# You don't really need this, but for completeness...
RewriteCond %{ENV:SSL} (.*)
RewriteRule ^ - [E=APACHE_SSL:%1]
RewriteCond %{HTTP:X-Forwarded-Proto} (.*)
RewriteRule ^ - [E=APACHE_PROTO:%1]
Then check the environment variables APACHE_HTTPS, APACHE_SSL and APACHE_PROTO in your server-side script. (eg. in PHP, use the getenv() function.)
After lots of issues with 123 Reg and redirecting all versions of pages to single relevant https page with Wordpress, this is what has worked for me across multiple sites now and has proven effective in terms of SEO. Hope it helps!
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Redirect One Directory from https to http

For some reason, I'm seeing one directory's contents showing up on Google with https URLs. Since this breaks some page elements, I need to check for that particular directory for https requests and redirect to http. Https is used within several other directories, so I don't want to make a blanket redirect.
Use that in your root .htaccess:
RewriteEngine on
RewriteCond %{HTTPS} on
RewriteRule ^particularDirectory/? http://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
Or that in your particularDirectory/.htaccess:
RewriteEngine on
RewriteCond %{HTTPS} on
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
There are many sample script for this. And if you understand rewrite rules it's not that hard. I found this one at ServerFault that should work for you. Don't forget to alter it for you specific directory (if you don't want everything to be rewritten to https).
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule ^.*$ https://%1/$1 [R=301,L]

override apache rewrite rules with htaccess

working on a server that hosts multiple domains.
Somewhere in apache config is a rewrite rule that is set for ALL domains.
What happens is if a user goes to example.com/foo they are supposed to get redirected to example.com/foo_bar
However, in one domain, I want to override this behavior so that the url stays at example.com/foo and does not redirect. I've been searching and trying various rules and conditions to no avail. I don't have access to the apache config, but I am using .htaccess for some rewrite rules on this domain.
here's my rewrite rules in .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
# this isn't working
# RewriteRule ^(foo)($|/) - [L]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1
# this didn't work either
# RewriteRule ^/foo index.php?/$1 [L]
</IfModule>
Try redirecting /foo_bar back to /foo.
When Apache processes the rewrite rules it runs through them multiple times, which you can see when you turn on debugging. I think what's happening in your case is that you're trying to match the URI in the first pass, but Apache has already modified it to /foo_bar.
Also, as a matter of debugging, you should try to recreate the problem in an environment you control. Ask your sysadmin for a copy of the global configuration and mirror the set up you're constrained to.
You can create exception for one domain:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} !^(?:www\.)?domain\.com$ [NC]
RewriteRule ^foo(/.*)?$ /foo_bar$1 [L,R=302]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]