Apache: Redirect requests where ServerName doesn't match - apache

I'm relatively new to Apache rewrite rules. What I need to do I think should be relatively easy, but I could use a bit of help.
I have a number of name based virtual hosts defined in my Apache configs, for developers to test new feature branches, and I have a wildcard DNS CNAME setup to direct traffic.
Everything works as it should when a request matches the ServerName in one of the virtual hosts. However if the hostname in the request doesn't match any explicitly defined virtual hosts, it automatically uses the first virtual host.
This is quite confusing, as a developer may think they're accessing the correct virtual host, when in fact they're not.
What I'd like to do, is define a rewrite rule in the first virtual host, so that if the hostname in the request doesn't exactly match the defined "ServerName", it will redirect it.
For example...
If I have 2 virtual hosts defined like so...
<VirtualHost *:443>
ServerName default.mydomain.com
...
</VirtualHost>
<VirtualHost *:443>
ServerName my-feature-1.mydomain.com
...
</VirtualHost>
and a developer is trying to request the site for their new feature, but spell it incorrectly, i.e.
https://feature-1.mydomain.com
The first virtualhost will silently serve the request, and they may be none the wiser, and wonder why their new feature code appears not to be working.
What I would like it to do instead. I'd like to redirect them to...
https://default.mydomain.com
so that it's obvious they've misstyped the URL.

I've got it to work with the following rewrite rule in the first virtual host...
RewriteCond %{HTTP_HOST} "!^default\.mydomain\.com" [NC]
RewriteRule ^/(.*) https://default.mydomain.com [L,NE,R=301]
This works as the default for any request not explicitly matched by the subsequent dynamic virtual hosts but also redirects to the preferred default URL. I don't want to actually serve any content on undefined URL's.
The only thing that would improve it slightly would be to not have to duplicate the domain name in the rules.

Related

redirect any link on any subdomain-url to another domain

I registered a expired domain to forward all incoming links to another domain. The problem is: many inlinks are placed on subdomains, for example: axa-art.cdn.contento-v41.eu/axa-art/0eee9cec-58cb-45b2-a4e2-b5f73920068e_091216_axa+art_classic+car+study_de_rz.pdf
I am looking for a 301 redirect rule in htaccess that forward any url (no matter on main domain or subdomain) to "new-url.tld"
axa-art.cdn.contento-v41.eu
axa-art.cdn.contento-v41.eu/slug
any-subdomain.contento-v41.eu
any-subdomain.contento-v41.eu/slug
all of this example above should
forward to this exact URL: new-domain.tld
Question 1:
Is it possible to create a "general" rule and place it into htaccess of the main directory?
Question 2:
Or do i have to write a specific rule for each subdomain?
Question 3:
Do I have to create a sub-directory and create a separate htaccess in every sub-directory for each subdomain I want to add redirection-rules?
Help or suggestions are highly appreciated. Thank you very much for your help in advance.
This isn't just a .htaccess question. In order for your server to receive requests to <any-subdomain>.example.com the necessary DNS and server config directives need to be in place. If the request doesn't reach your server then you can't implement a redirect in .htaccess.
So, I suspect that these subdomains are not even resolving?
You either need to create the necessary DNS A records and ServerAlias directives one by one for each hostname (ie. subdomain) or create a "wildcard" DNS A record (and ServerAlias *.example.com directive in the vHost). But then you still have an issue with these hostnames being covered by an SSL cert if you need to redirect from HTTPS.
You can then create the necessary redirect in .htaccess. Although, since you need access to the server config (or a using a control panel that does this for you) to implement the directives above, you should also implement this redirect in the server config also.
For example, at the top of your .htaccess file, before the existing directives (or in your vHost):
RewriteEngine On
RewriteCond %{HTTP_HOST} !^new\.example$
RewriteRule ^ https://new.example%{REQUEST_URI} [R=301,L]
The above states... for any request that is not for new.example then 301 redirect to https://new.example/<same-url>.
However, if you have access to the server config and this other domain is configured in its own vHost container then the redirect can be simplified:
Redirect 301 / https://new.example/
UPDATE#1:
this rule does forward any URL form the main domain to the new domain.
# Permanent URL redirect- by netgrade
RewriteEngine on
RewriteCond %{REQUEST_URI} !https://www.marco-mahling.de/$
RewriteRule $ https://www.marco-mahling.de/ [R=302,L]
The rule I posted above should probably replace your existing rule entirely.
Yes, your rule does redirect every URL to the root of the new domain, but it is arguably incorrect. The RewriteCond directive is superflous and isn't actually doing anything. The REQUEST_URI server variable contains the URL-path, it never contains the scheme + hostname. So, the RewriteCond directive you've posted will always be successful.
If that is the rule you currently have then it would already redirect everything. In which case your problem would seem to the necessary DNS and server config directives as mentioned above.
From your directives, I assume that the other domain actually points to a different server (or different vHost on the same server). Otherwise, this would have resulted in a redirect-loop. In which case, you only need the much simpler Redirect directive that I posted above.
UPDATE#2: That works fine BUT the incoming links are still not forwarded cuz of a "%" in the url: https://axa-art.cdn.contento-v41.eu/axa-art%2F0eee9cec-58cb-45b2-a4e2-b5f73920068e_091216_axa+art_classic+car+study_de_rz.pdf
It's actually because of the %2F - an encoded slash (/) in the URL-path. By default, Apache will reject such URLs with a 404 (for security reasons).
To allow encoded slashes in the URL you would need to set AllowEncodedSlashes On in the server config (or vHost container). You cannot set this in .htaccess. (The server generated 404 occurs before .htaccess is even processed.)
However, I would express caution about enabling this feature. (Is there a specific requirement here? Are you recreating these documents on the new server?)
If this request was intended to map directly to a PDF file on disk then this actually looks like an incorrectly URL encoded request, since a slash / is not a permitted filename character on either Windows or Linux.
If you enable AllowEncodedSlashes then the above RewriteRule will redirect the request to /axa-art/0eee9cec....pdf - note the %-decoded / in the resulting URL. You would need to take additional steps to maintain the URL-encoding (if that was required), but as I say, that looks like a mistake to begin with.

Does the Redirect directive override configured Aliases

I'm setting up apache 2.4 (docker) as a reverse-proxy to distribute different subdomains to different docker services. I redirect http-requests to https using the Redirect directive. One specific URL-path (the part after the domain), however, should not be redicted to https, but served with files from a specific directory. I'm trying to accomplish this using the Alias directive, which does not work.
I'm assuming that Redirect overrides Alias. Is that true?
And how could I accomplish my goal if this is the case?
<VirtualHost *:80>
ServerName service.example.com
Alias /exception/ /var/www/exception
Redirect permanent / https://service.example.com/
</VirtualHost>
I expected this to work, but it does not.
From mod_alias docs:
First, all Redirects are processed before Aliases are processed, and
therefore a request that matches a Redirect or RedirectMatch will
never have Aliases applied. Second, the Aliases and Redirects are
processed in the order they appear in the configuration files, with
the first match taking precedence.
To make sure that /exception/ is not matched, use RedirectMatch which allows regex patterns:
RedirectMatch permanent "^/(?!exception/)(.*)" "https://service.example.com/$1"

How can I write the Apache configuration two different sites?

How can I write the Apache configuration to make two different sites on the same domain through a slash
Example:
site.ru - 1 site,
site.ru/app - 2 site
In Apache configuration, you should specify full URL without the part which goes after the slash, i.e.:
ServerName "site.ru:80"
It is not possible to define site.ru/app as a separate virtual host.
However, you can simply move the content of the second website to a subdirectory of the first one. For example, if:
ServerName "site.ru:80"
DocumentRoot "/var/www/httpdocs"
Then /var/www/httpdocs/app will be the directory with the content of the second website.
Another option is to create two virtual hosts, and then to add a rewrite rule to the first domain configuration.
Let's take two domains: site.ru and siteapp.ru. Requests to site.ru/app can be redirected to siteapp.ru using the following on site.ru:
RedirectMatch 301 ^/app/(.*)$ http://siteapp.ru/$1

Apache Conditional Redirect Rule not forwarding header values

Goal:
To perform conditional redirect/forward from Site1 to Site2 based on specific header (HTTP_SM_USER) value of the request (in Site1) and ensure all the current custom header data is forwarded as part of the redirect/forward to Site2. The user can see the url change in the browser window after the redirect.
Flow:
User accesses Site 1 --> External Application Sets few custom headers in addition to default HTTP headers based on certain criteria --> Web-server looks for specific header value and if matches redirect all the headers to Site 2.
Apache Web server Config:
<VirtualHost *.443>
ServerName site1.com
ServerAdmin ashish#test.com
UseCanonicalName on
DocumentRoot /var/www/html
#
# SSL Config comes here
#
ErrorLog /path/to/error/log
TransferLog /path/to/access/log
LogLevel warn
RewriteEngine On
RewriteCond %{HTTP:SM_USER} ^USER1$ [NC]
RewriteRule .* https://site2.com/$1 [R=301, L]
<Location /page1>
.
.
</Location>
.
.
.
</VirtualHost>
Question: The Conditional Redirect happens but the headers are lost. What should I do to ensure the HTTP headers are forwarded as well ? I tried to see into apache mod_proxy but wasn't sure how in this scenario to use it. Experts please help. Any alternative suggestions are welcome too.
Solution:
I finally got it to work (with mod_proxy) after a lot of troubleshooting using the below flags and proxy rules. All Rewrite rules were removed.
ProxyRequests Off
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass "/" "https://site2.com/" Keepalive=On
ProxyPassReverse "/" "https://site2.com/"
Note: User accesses Site 1 -> External app sets headers and apache immediately proxies to Site 2. Headers are now available on Site2.
You can't have the redirect "forward" headers, because it is up to the client what it sends to the next server after it has been issued a redirect. It may choose not to follow the redirect at all! Unlikely but just to make it clear what the situation is.
If you want the URL to change in the browser, then you need to do this on the application side. Have your application handle directing to the next server, and just issue a 200 response with an instruction for it to do so. Then it can send the custom headers as it did with the first request.
If that is not acceptable, then using mod_proxy could work as you said, but it would not change the URL in the browser, because the first server would be proxying the request to the second, so the browser would still see it as being the first.
In summary, you cannot do what you want to do, because HTTP does not work that way, so you are going to have to compromise in some way, either by not changing the URL in the browser, or by updating the application to take care of it.

HTTP Post request to aws ec2 directory /opt/lampp/htdocs/donate/ denied

I am trying to make a post request to http://localhost/donate/payment.php".
It works fine when I run the application locally
However when I change the URL to
"http://ec2-xx-xxx-xx-xxx.ap-southeast-2.compute.amazonaws.com/opt/lampp/htdocs/donate/payment.php"
I get page not found error. I can guarantee that the file is present in the location.
I have tried several things like changing the permission of the the /opt file recursively to 777. Also tried changing the apache server port default port from 80.
I even tried placing a .htacces file inside the donate folder to access the server. the contents are
RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain.com
RewriteRule (.*) http://www.yourdomain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.yourdomain\.com$
RewriteCond %{REQUEST_URI} !^/WebProjectFolder/
RewriteRule (.*) /WebProjectFolder/$1
All attempts have failed. Is there anything else I am missing here. I have installed bitnami parse server and I am able to access that by http in the browser. It is present in the folder /apps in the root folder.
Does AWS override any security permissions?
Assuming /opt/lampp/htdocs/is your document root, shouldn't the URL be http://ec2-xx-xxx-xx-xxx.ap-southeast-2.compute.amazonaws.com/donate/payment.php?
You might also want to verify a couple of things:
Make sure your security policy has its inbound port 80 open to the public (or where you'll be visiting from)
Assuming you're using Apache httpd, make sure it accepts connections on the external interface or all interfaces (e.g. Listen 80, Listen 0.0.0.0:80, etc)
First, if you actually get an error from your Apache server, the issue has nothing to do with AWS. If there were misconfigured security groups or NACL, you'd never reach port 80 (http).
Second, never ever chmod -R 777, not only can you break your app behavior, but also, especially with PHP, you just opened security risks. Yes, this doesn't matter until your instance becomes part of a botnet and starts sending spam.
At a glance, I would say your Apache configuration lacks something, like a VirtualHost "any":
# from https://httpd.apache.org/docs/2.4/vhosts/examples.html
<VirtualHost *:80>
DocumentRoot "/www/example1"
ServerName www.example.com
# Other directives here
</VirtualHost>
It seems like your default location points to another directory, possibly the default one.