1 subdomain doesn't support HSTS - amazon-web-services

My website is hosted on AWS and I am using SEMRush to track any server and programming issues.
And my SEMRush found this error when I run it.
2 subdomains don't support HSTS.
Hence I put below code to solve this issue
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
Now 1 error resolved but still having one more subdomain having the same error.
As you can see rosterelf.com still doesn't support HSTS.
Further, I am redireting non www to www in my htaccess and this is how my .htaccess file looks like.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
RewriteEngine On
##
## You may need to uncomment the following line for some hosting environments,
## if you have installed to a subdirectory, enter the name here also.
##
# RewriteBase /
##
## Uncomment following lines to force HTTPS.
##
# RewriteCond %{HTTPS} off
# RewriteRule (.*) https://%{SERVER_NAME}/$1 [L,R=301]
# CONDITIONS FOR ONLY LIVE SITE STARTS
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# CONDITIONS FOR ONLY LIVE SITE ENDS
##
## Allow robots.txt
##
RewriteRule ^robots.txt - [L]
## 301 redirect for old support details page url to new one
## OLD URL https://www.rosterelf.com/support-detail/1903/how-can-employees-clock-inout-of-time-clock-different-slug
## NEW URL https://www.rosterelf.com/support-detail/how-can-employees-clock-inout-of-time-clock-different-slug
RewriteRule ^(support-detail)/\d+/([\w-]+)/?$ /$1/$2 [R=301,NC,L]
RewriteRule ^blog-detail/\d+/([\w-]+)/?$ /blog/$1 [R=301,NC,L]
##
## Black listed folders
##
RewriteRule ^bootstrap/.* index.php [L,NC]
RewriteRule ^config/.* index.php [L,NC]
RewriteRule ^vendor/.* index.php [L,NC]
RewriteRule ^storage/cms/.* index.php [L,NC]
RewriteRule ^storage/logs/.* index.php [L,NC]
RewriteRule ^storage/framework/.* index.php [L,NC]
RewriteRule ^storage/temp/protected/.* index.php [L,NC]
RewriteRule ^storage/app/uploads/protected/.* index.php [L,NC]
##
## White listed folders
##
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} !/.well-known/*
RewriteCond %{REQUEST_FILENAME} !/storage/app/uploads/public/.*
RewriteCond %{REQUEST_FILENAME} !/storage/app/media/.*
RewriteCond %{REQUEST_FILENAME} !/storage/app/resized/.*
RewriteCond %{REQUEST_FILENAME} !/storage/temp/public/.*
RewriteCond %{REQUEST_FILENAME} !/themes/.*/(assets|resources)/.*
RewriteCond %{REQUEST_FILENAME} !/plugins/.*/(assets|resources)/.*
RewriteCond %{REQUEST_FILENAME} !/modules/.*/(assets|resources)/.*
RewriteRule !^index.php index.php [L,NC]
##
## Block all PHP files, except index
##
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteRule !^index.php index.php [L,NC]
##
## Standard routes
##
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Do I need to put below code
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
Out side of <IfModule mod_rewrite.c> condition ? What should I do to solve this ?
Can someone please guide me ..
Thanks

Pretty sure you need always if you want a header to also be added to redirects so try this:
Header always set Strict-Transport-Security "max-age=31536000"

my SEMRush found this error when I run it.
Just to clarify, that's not strictly an "error", unless you are explicitly trying to implement HSTS. (It doesn't look as if you were?) HSTS is a recommendation.
but still having one more subdomain having the same error.
SEMRush's identification is curious; that's not a subdomain, that's the "domain apex" (ie. no subdomain).
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
When implementing HSTS you need to first redirect from HTTP to HTTPS on the "same hostname", before you canonicalise the hostname, ie. before you redirect from no-www (the domain apex) to www.
This means you can't do what you are doing here... redirecting from HTTP and no-www to HTTPS and www in a single redirect. (The currently commented out HTTP to HTTPS redirect is what you need to be using instead.)
However, your current rule is also incomplete as it fails to canonicalise the hostname when requesting HTTPS. ie. It does not redirect https://example.com/ to https://www.example.com/. The first condition that checks that HTTPS is off ensures the rule is only processed for HTTP requests.
When implementing HSTS your redirects need to be written like this:
# 1. Redirect HTTP to HTTPS on the same host
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# 2. Redirect non-www to www
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
The second redirect to canonicalise the hostname does assume that you have no other subdomains that should be accessible since it redirects anything that is "not www".
Yes, this does (unfortunately) mean that users will experience two redirects when requesting http://example.com/ the very first time. But this is the nature of HSTS. And it is only the very first time that user visits HTTP on the non-canonical hostname.
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
This sets the STS header on HTTPS "success" responses. However, it is also a requirement of HSTS that you set this header on the HTTPS canonical redirect from no-www to www. Currently, the above directive is only setting the header on onsuccess (200 Ok) responses (the default). To set the header on the 301 redirect you need the always condition, as #BarryPollard has already pointed out in his answer:
# Set the STS header on redirects as well as 200 OK responses.
Header always set Strict-Transport-Security "max-age=31536000"
Just to add, not only will the always condition set the header on 3xx responses, but also other 4xx responses as well etc.
The <If> expression itself is also a bit dubious. You should only check the X-Forwarded-Proto header if your application server is behind a front-end proxy that manages the secure connection. However, if you are behind a proxy then you don't need to check the REQUEST_SCHEME server variable. (It looks like this expression is intended to be a generic "catch-all".) The issue with the above expression is that if you are not behind a proxy then a malicious request could inject the X-Forwarded-Proto HTTP request header and fool your server into sending the header.
From your HTTP to HTTPS redirect (that checks the HTTPS server variable) it looks like you are not behind a front-end proxy. Although, maybe you are and we'll need to modify the above HTTP to HTTPS redirect?
So, if you are not behind a front-end proxy then the following <If> expression is preferable:
<If "%{REQUEST_SCHEME} == 'https'>
Or,
<If "%{HTTPS} == 'on'>
And if using Apache 2.2 (or Apache 2.4) you could do the following instead of using an <If> expression:
# Set HSTS env var only if HTTPS
RewriteCond %{HTTPS} on
RewriteRule ^ - [E=HSTS:1]
# Set STS header only when the HSTS env var is set (including redirects)
Header always set Strict-Transport-Security "max-age=31536000" env=HSTS
Out side of `<IfModule mod_rewrite.c>` condition ?
Placing the directive inside or outside the <IfModule> containers makes no difference in this instance (since mod_rewrite and mod_headers are presumably installed). In fact, strictly speaking, the <IfModule> wrappers should probably be removed altogether.
See my answer to the following question on the Webmasters stack for more info on this:
https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

Related

Apache rewrite rules for maintenance, htaccess not allowing my IP address through

I'm working on a template to use for site maintenance. Took a while to figure out that Apache wanted absolute paths, but now everything is working, short of the IP.
I'm trying to allow my IP and the IP of the server (domain) when maintenance is activated, so the maintenance page will only be served to guests. However, I'm also getting served the maintenance page. I suck at regex, so it might be a simple error.
Here are my Apache directives.
## Maintenance
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# local ip
RewriteCond %{REMOTE_ADDR} !^111\.111\.33\.44
# server ip
RewriteCond %{REMOTE_ADDR} !^222\.222\.333\.444
# maintenance folder
RewriteCond %{REQUEST_URI} ^/maintenance/
RewriteRule .+ - [L]
# maintenance files
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif|css|woff|woff2|eot|ttf|svg) [NC]
RewriteCond %{REQUEST_URI} !^/maintenance/maintenance\.html$
RewriteRule ^(.*) https://example.com/maintenance/maintenance.html [R=307,L]
</IfModule>
ErrorDocument 503 /maintenance/maintenance.html
ErrorDocument 307 /maintenance/maintenance.html
<IfModule mod_headers.c>
#do not cache
Header Set Cache-Control "max-age=0, no-store"
</IfModule>
## End Maintenance
# Force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.*)$ [NC]
RewriteRule (.*) https://%1%{REQUEST_URI} [L,R=301]
# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php74” package as the default “PHP” programming language.
<IfModule mime_module>
AddHandler application/x-httpd-ea-php74 .php .php7 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit
I managed to figure this out, so in case anyone else who's as bad at regex as I am comes across this, it may help them.
I had two unneeded lines of directives and the ^ was unnecessary or causing problems. $ after IP is to make sure a similar longer IP can't get through. I also switched to a 302 error since it is a temporary redirect for maintenance.
Make sure your folder and html file path is set correctly and uses absolute paths. If you aren't using a folder, the path directly to the html should work. I used a folder because I have images and fonts also loading and like to keep things tidy.
<IfModule mod_rewrite.c>
RewriteEngine On
# local ip
RewriteCond %{REMOTE_HOST} !^111\.111\.22\.33$
# server ip
RewriteCond %{REMOTE_ADDR} !^222\.222\.333\.444$
# maintenance folder
RewriteCond %{REQUEST_URI} !^/maintenance/(.)*$
# maintenance files
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif|css|woff|woff2|eot|ttf|svg) [NC]
RewriteCond %{REQUEST_URI} !/maintenance/maintenance\.html$ [NC]
RewriteRule .* /maintenance/maintenance.html [R=302,L]
</IfModule>
<IfModule mod_headers.c>
#do not cache
Header Set Cache-Control "max-age=0, no-store"
</IfModule>

.htacces: RewriteMatch all traffic EXCEPT for two URLs

I'm currently using the below method to redirect users on my site from the root directory to a subdirectory as followed:
RewriteEngine on
############################################
## Forcing https
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://website.com/$1 [R,L]
############################################
## Capturing all traffic and redirecting it to necessary subdirectory
RedirectMatch ^/$ /subdirectory/
This works well and I can still get to one of my exceptions which is /admin (Full URL: /index.php/admin) no problem. I didn't have to specify any exception - it just worked.
Now I am trying to access my API URL and it manages to redirect it to /subdirectory instead of allowing it. The URL: http://website.com/index.php/api/action
I see there is a way of excluding directories with the RewriteRule method but does this apply for the RedirectMatch method as well?
RewriteEngine on
RewriteRule !^uploads($|/) http://example.com%{REQUEST_URI} [L,R=301]
Better to stick with mod_rewrite instead of using mod_alias based rules here:
RewriteEngine on
############################################
## Forcing https
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://website.com/$1 [R,L]
############################################
## Capturing all traffic and redirecting it to necessary subdirectory
RewriteCond %{THE_REQUEST} !\s/+(index\.php/)?(api|admin) [NC]
RewriteRule ^/?$ /subdirectory/ [L,R]

SetEnvIfNoCase redirection

Hi all ive been learning wildcard methods using SetEnvIfNoCase User-Agent and wildcards,
But using the example below.only serves a 403 error page if a useragent matches the wildcards.
but what i want is to redirect the "user-agent" to another website such as a black hole or spam page.
using something like RewriteRule ^(.*)$ http://send junk to here/
SetEnvIfNoCase User-agent "(B2|Bac|Bad|Bag|Bai|Bast|Batch|Bing|Bite|Bla|Blex)" bad_bot=yes
#
Order Allow,Deny
Allow from All
Deny from env=bad_bot
what can i replace the Deny from env=bad_bot with to make it redirect to the wanted website instead of serving the 403 error page.
Have your rewrite rule like this in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} B2|Bac|Bad|Bag|Bai|Bast|Batch|Bing|Bite|Bla|Blex [NC]
RewriteRule !^spam/ http://officeofstrategicinfluence.com/spam/ [L,NC,R=302]
UPDATE:: In response this comment by OP
1- adding a new line of filters do i need to change the [NC] ? and 2- if i wanted to add a single word by itself do i still use RewriteCond %{HTTP_USER_AGENT} ^word [NC]? with the ^
Try this code:
RewriteCond %{HTTP_USER_AGENT} B2|Bac|Bad|Bag|Bai|Bast|Batch|Bing|Bite|Bla|Blex [NC,OR]
RewriteCond %{HTTP_USER_AGENT} foo|bar|etc [NC]
RewriteRule !^spam/ http://officeofstrategicinfluence.com/spam/ [L,NC,R=302]
The RewriteCond directive can filter by server variables, including environment variables like your bad_bot. Syntax is:
%{ENV:variable}, where variable can be any environment variable, is
also available. This is looked-up via internal Apache httpd structures
and (if not found there) via getenv() from the Apache httpd server
process.
But it can also filter by HTTP headers as well so you don't need your env variable:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla
RewriteRule ^/$ /homepage.max.html [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx
RewriteRule ^/$ /homepage.min.html [L]
RewriteRule ^/$ /homepage.std.html [L]

301 redirect to new domain and redirect individual old pages at the same time

I hope you can help me with this 301 issue.
Introduction
I've just published a re-design of a website with new clean urls. The old webpage had urls like this: www.domain.dk/Default.aspx?ID=66. And the new website urls look like this: www.domain.com/contact
So I wan't to redirect all these old urls to the new ones, and therefor i'm not keeping the old urls and no general rule can be applied.
That's just simple 301 redirects, but at the same time the old domain points to a new domain, and this is where things get dirty, I think. The old domain was www.domain.dk, but i wan't to 301 all traffic to the new domain www.domain.com and at the same time I wan't to make all the individual 301 redirects.
The problem
When I click on the link www.domain.dk/Default.aspx?ID=66 in Google I get this URL in my browser: www.domain.comindex.php/?ID=66.
On other links I get www.domain.comdefault.aspx/?ID=2
So the redirecting to the new domain works fine? But the individual redirects doesn't apply at all.
The code
This code is pasted as is from my .htaccess file on the server running apache.
The first bit is auto-generated by Concrete5 CMS to make pretty URLs.
# -- concrete5 urls start --
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]
</IfModule>
# -- concrete5 urls end --
This is the code I found to 301 redirect all traffic to urls that is not using www.esvagt.com to www.esvagt.com
## --- 301 Redirects --- ##
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
This is just one of the manual 301 redirects.
## General - Redirects ##
redirect 301 /Default.aspx?ID=66 http://www.domain.com/contact/contact-us
Thanks in advance. If you need more information I'll gladly provide that.
I have zero knowledge about writing code in .htaccess, so I'm pretty clueless. I hope you can help. :)
Avoid mixing mod_rewrite and mod_alias rules.
Ordering of rules is also very important so have 301 rules first and then have your catch all controller rule
Use this code for 301 redirect:
## --- 301 Redirects --- ##
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.dk$ [NC]
RewriteRule ^ http://www.domain.com%{REQUEST_URI} [R=301,L]
## General - Redirects ##
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+Default\.aspx\?ID=66[&\s] [NC]
RewriteRule ^ http://www.domain.com/contact/contact-us? [R=301,L]
# -- concrete5 urls start --
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]
</IfModule>
# -- concrete5 urls end --
RewriteRule www.domain.dk/Default.aspx?ID=66 domain.com/contact/contact-us [R=301,L]
If you want to redirect all posts automatically:
RewriteRule /Artical.aspx?ID=(.+?) domain.com/article-title-$1.html [R=301,L]
or
RewriteRule /Artical.aspx?ID=(.+?) domain.com/Post.aspx?ID=$1 [R=301,L]
Then the dynamic url Artical.aspx?ID=20 will be redirect to http://www.domain.com/article-title-30.html,
I successfully apply this method for my blog http://downloadapp.info

.htaccess issue with ExpressionEngine and YOURLS

I have a primary site running ExpressionEngine and I am trying to get YOURLS running in a subfolder called "work", ie: http://foo.com/work/ for short urls and EE is running at the root, ie: http://foo.com/. Please note there is no 'www'.
The problem I am having is that when I use a short URL and a user adds "www" to the URI, such as http://www.foo.com/work/123 I get a redirect chain that looks like this:
http://www.foo.com/work/123 302 redirects to
http://www.foo.com/work 301 redirects to
http://www.foo.com/work/ which returns 200
Everything works fine if you omit the 'www' from the URI. YOURLS is set up to use the non-www but the worry is that some users might habitually type the 'www' as these URIs are being placed on printed ads.
The root .htaccess file looks like this:
SetOutputFilter DEFLATE
DirectoryIndex index.php index.html
# BEGIN ExpressionEngine Rewrite
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www.foo.com [NC]
RewriteRule ^(.*)$ http://foo.com/$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteRule ^(.*)$ /index.php?$1 [NC,L]
</IfModule>
# END ExpressionEngine Rewrite
The /work/ (YOURLS) .htaccess looks like this:
# BEGIN YOURLS
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /work/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /work/yourls-loader.php [L]
</IfModule>
# END YOURLS
How can I get the 'www' URIs to work like the non-www URIs do without completely hosing EE? :)
I faced a similar issue. Some end users or people publishing the short urls tend to append them with www while the short url was bought with the intention of using it without www.
I also installed the YOURLS redirect index plugin to forward homepage visitors to our regular homepage.
So I had a few different types of urls:
short domain homepage, should lead to the regular https homepage
short domain YOURLS admin panel, should lead to the https admin panel
short domain shortened urls, should lead to the long url
I wanted all urls to work with or without www and make sure http was forwarded to https.
My solution was to start .htaccess with these lines:
# Force HTTPS (because of passwords via /admin) and use clean domain (non www)
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www.examp.le [NC]
RewriteRule ^(.*)$ https://examp.le/$1 [L,R=301]