apache rewrite rule for http_host containing port - apache

In the local network, I have synology server with a number of services running in docker on different ports and accessible in-browser like that
192.168.1.2:8989 or server.spb.lan:8989
How to make a rewrite rule to convert them like that 192.168.1.2/servicename or server.spb.lan/servicename?
Like that
192.168.1.2:8989 -> 192.168.1.2/servicename
server.spb.lan:8989 -> server.spb.lan/servicename

Based on your shown samples, could you please try following. Please make sure you clear your browser cache after placing these rules in your htaccess file.
RewriteEngine ON
RewriteCond %{HTTP_HOST} 192\.168\.1\.2
RewriteCond %{REQUEST_URI} ^/servicename [NC]
RewriteRule ^ http://%{HTTP_HOST}:8989%{REQUEST_URI} [NE,L]
RewriteCond %{HTTP_HOST} server\.spb\.lan
RewriteCond %{REQUEST_URI} ^/servicename [NC]
RewriteRule ^ http://%{HTTP_HOST}:8989%{REQUEST_URI} [NE,L]

I assume, that those backend services operate based on the http protocol, since you did not specify anything else...
Easiest probably is to use the apache proxy module to expose those backend services. You can use it within the rewriting module which makes the approach pretty convenient:
RewriteEngine on
RewriteRule ^/?servicename(/.*)$ https://server.spb.lan:8989$1 [P]
An alternative to the rewriting module would be to implement a reverse proxy:
ProxyRequests off
ProxyPass /servicename https://server.spb.lan:8989
ProxyPassReverse /servicename https://server.spb.lan:8989
I suggest you read about the details in the apache documentation. As typical for OpenSource it is of excellent quality and comes with great examples.

I couldn't solve the issue with apache installed directly on Synology. So I deleted it, deleted web station. Then I install nginx in docker. Synology has integrated nginx running on port 80, which cannot be deleted and there is no access to its settings.
So I just mapped internal port 80 of nginx container to port 82 on Synology, make forward port 80 from router to port 82 on Synology.
And then in config of nginx container I did simply that for each of my app running in docker
server {
server_name sonarr.lan;
location / {
proxy_pass http://192.168.1.2:8989;
}
}

Related

Redirection https to https within same Apache

I have a requirement where I have to redirect my hostname to particular application which is again hosted on same Apache. Let's take an example, When I hit on host(https://domain1.example.com), It should internally redirect me to Apache Web Application (https://domain1.example.com/application1) without changing the browser URL.
I am not sure how to achieve SSL to SSL redirection. Thanks in Advance..!!!
This should work. This will redirect all incoming urls that are going to domain1.example.com/ to domain1.example.com/application1
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain1.example.com$
RewriteRule ^$ https://domain1.example.com/application1 [L,R=301]
If without changing browsing URL is your goal then PROXY is your way.
Put following in your apache vhost or global file,
ProxyPass https://domain1.example.com/ https://domain1.example.com/application1
ProxyPassReverse https://domain1.example.com/ https://domain1.example.com/application1
PS shibboleth has nothing to do with this, at least you have not mentioned any case.
EDIT
ProxyPass should come to virtural host not in location
Ideally all the location tag should be out of virtual host

Apache mod rewrite to direct from one server to another

I've got to apache web servers running. One on port 80 and another on port 8077.
I'm wanting to try and redirect all the traffic through the port 80 version if possible.
What I'm ideally wanting is to be able to go to http://translate.example.com
and the traffic get directed to http://www.example.com:8077
I've already got a lot of mod_rewrite going on at the main port 80 server, but I'm not sure which of the servers needs configuration or whether both do.
I'm wanting to make sure that translate.example.com/img (or any other subdirectory) actually points to the 8087/images directory.
update
I've now got the following:
RewriteCond %{HTTP_HOST} example[NC]
RewriteCond %{REQUEST_URI} ^/glot$ [NC]
RewriteRule ^(.*)$ http://www.example.com:8077/$1 [P]
ProxyPassReverse / http://www.example.com/
I'm getting to see the other servers new pages, but I'm finding all the resources aren't found like images, css etc
Doing a view source all the resources in the installed product are set with leading slash
For example
/img/glotpress-logo.png
So I'm not sure how to get the resources loaded up.
Note I'm happy enough if the original starting point is www.example.com/glot instead of glot.example.com as in the original question
You can remap your resources to another server but having the other server on non-default port might prevent some of your visitors from viewing them as they might be block (firewalled) from accessing the port. If you're not worry about the port being block you can use mod_rewrite Remapping Resources. method.
RewriteEngine On
RewriteRule ^/images/(.+) http://www.example.com:8077/images/$1 [R,L]
If you want to make sure that everyone is able to view the external resources, you need to use proxy where apache will tunnel the visitor connection to example.com:8077 transparently. You can read more about mod_rewrite for Proxying at apache website.
RewriteEngine on
RewriteBase /images/
RewriteRule ^images/(.*)$ http://example.com:8077/images/$1 [P]
ProxyPassReverse /images/ http://example.com/images/
UPDATE
Have you tried to remove
RewriteCond %{HTTP_HOST} example[NC]
This line basically tells that it will only process if the HTTP_POST is example.com if its coming from www.example.com this rule is not applicable. I'm hoping that "example[NC]" is a typo.
In the end it probably looks like
RewriteRule ^/glot/(.*)$ http://www.example.com:8077/glot/$1 [P]
ProxyPassReverse /glot/ http://www.example.com:8077/glot/
You need to do the configuration at the port 80 server to make it act as a proxy for the 8077 server.
The Apache document is here: http://httpd.apache.org/docs/trunk/rewrite/proxy.html

Rewrite rule to hide port from URL of Rails server?

I have a rails server running on URL "http://example.com:1234"
I want to provide the URL of this application to an user as "http://example.com/myapp" so that Apache (or Rack or whatever you suggest that works) can redirect request for "/myapp" to port 3333 of that domain.
Take a look at setting up a Reverse Proxy under apache.
Apache, listening to port 80 on example.com, would reverse proxy to port 1234. Then requests for http://example.com/myapp would be internally proxied to http://example.com:1234/myapp (or however you setup your ProxyPass target).
If you don't have access to server config, you can use mod_rewrite's Proxy flag and setup some rules inside an .htaccess file. Something along the lines of:
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^myapp(.*) http://example.com:1234/$1 [P,L]
Somethimes it loose it css style. You can use only:
RewriteRule ^myapp(.*) http://example.com:1234 [L,R]

Apache mod_rewrite RewriteRule incorrectly adding in port AWS

I have an issue where we are running two systems on the same EC2 instances and using AWS Elastic Load Balancer to send request for one systems to port 81.
So for example we have www.example.com and bookings.example.com where the AWS Elastic Load Balancer sends requests for bookings. though to our EC2 boxes on port 80 and request for www. get sent though on port 81.
The customer connects to www.example.com on port 80 but then gets from the load balancer to the server on port 81.
When we add this rule for example to the .htaccess for the www site we have an issues with port 81 appearing.
RewriteRule ^index.html / [R=301,L,QSA] !-s
#Results in customer being sent to http://www.example.com:81/
How can I make sure the port 81 is not pushed back to the customer?
I have come up with this alternative:
RewriteRule ^index.html http://%{HTTP_HOST}/ [R=301,L,QSA] !-s
But in this example http is hard coded and I would need to make that variable so it can be https when needed. I also have more then just this index.html rule that redirect back to / I have about 30 rules and feel there should be a one liner to fix this passing port 81 back to the customer.
Your alternative will work and could be extended for ssl support, but it's probably not necessary. Apache follows a specific order when creating self referencing URL's. UseCanonicalName, and UseCanonicalPhysicalPort control how they are created regardless of the module (mod_rewrite, mod_alias, etc).
Without knowing more of your configuration, I would suggest starting with these directives in the appropriate VirtualHost.
UseCanonicalName On
ServerName www.example.com:80
EDIT: If you don't want to do this for whatever reason, here's how you fix your rewrite to support ssl.
RewriteCond %{HTTPS} =on
RewriteRule - - [env=req_scheme=http,S=1]
RewriteRule - - [env=req_scheme=https]
RewriteRule ^index.html %{ENV:req_scheme}://%{HTTP_HOST}/ [R=301,L,QSA]

How to force https on amazon elastic beanstalk without failing the health check [duplicate]

This question already has answers here:
How to force https on elastic beanstalk?
(23 answers)
Closed 5 years ago.
I have configured my Elastic Beanstalk environment to redirect all pages to https, redirection works, however, the instance fails the health check and gets terminated, any ideas how to configure the rewrite rules?
My configuration:
NameVirtualHost *:80
<VirtualHost *:80>
.
.
.
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule !/_hostmanager/healthcheck https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</VirtualHost>
There's multiple hostmananger URLs that Elastic Beanstalk needs to access besides the health check. Grepping /var/log/httpd/elasticbeanstalk-access_log, I see requests to /_hostmanager/tasks and /_hostmanager/healthcheck.
Here are the rules that I added to /etc/httpd/sites/elasticbeanstalk on my EC2 instances:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/status$
RewriteCond %{REQUEST_URI} !^/version$
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule . https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
Note that I'm also allowing non-https traffic to my /status and /version pages. I'm actually using /status as the actual healthcheck lookup URL, so having that traffic skip the rewrite will avoid the redirect and make the status lookup faster (I'm assuming).
I think that some of the other answers on here may not be based on whatever the arbitrary User-Agent AWS is currently setting. When I watch the Apache logs, I see this User-Agent:
ELB-HealthChecker/1.0
As of writing this, the following mod_rewrite rule is working for me:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker.*
RewriteRule . https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
As of 2016, none of these answers works for me, but this worked:
1 Retrieve /etc/httpd/conf.d/wsgi.conf
2 Add the following to the virtual host: (Note that the third line prevents an issue where the setup script /opt/elasticbeanstalk/hooks/config.py waits 5 minutes failing to load the path /.)
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP_HOST} !localhost
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker.*
RewriteRule . https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]
3 Put the file in your repository, and add the following container command:
06_https:
command: "cp wsgi.conf /opt/python/ondeck/wsgi.conf"
This file is then copied automatically by the setup script into /etc/httpd/conf.d.
It looks like the AWS Health Checker uses the user agent 'AWSHealthCheck'.
I got round this by avoiding the redirect if the request came from the Health Checker User Agent.
SOmething like:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{USER_AGENT} !^AWSHealthCheck$
RewriteRule . https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
You can configure ELB to use a specific path for health checks, such as /ping. You can then explicitly tell apache not to redirect that URL, rather than relying on the UserAgent string.
You can also tell ELB to use HTTPS for the health check and then redirect all HTTP URLs to HTTPS, including the health check.
Both these settings can be changed in the EC2 Console in the Load Balancer section.
If you are trying to do this in Wordpress or PHP, you can setup your .htaccess as follows without having to modify anything through .ebextensions:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/status\.html$
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
</IfModule>
# 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
Remember to change status.html to whatever path you are using to do your Elastic Beanstalk health check
For more info see my response here.
This answer assumes you have already enabled https in the load balancer security group, added the SSL certificate to the load balancer, added 443 to the ports forwarded by the load balancer, and pointed your domain name at the Elastic Beanstalk environment with Route 53 (or equivalent DNS service).
Amazon Linux 2
Most AWS Linux version 2 based platforms have the option to pick Apache as your proxy host. This can be done by going to "Configuration" > "Software" >
"Container Options" and setting "Proxy Server" to "Apache", or adding the following to one of your .config files in .ebextensions:
option_settings:
aws:elasticbeanstalk:environment:proxy:
ProxyServer: apache
Having done that, add a configuration file named .platform/httpd/conf.d/ssl_rewrite.conf to your codebase (relevant AWS docs) with the following contents:
RewriteEngine On
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</If>
Amazon Linux 1
All you need to do is add the following to one of your [.config files in the .ebextensions directory of your project][2]:
files:
"/etc/httpd/conf.d/ssl_rewrite.conf":
mode: "000644"
owner: root
group: root
content: |
RewriteEngine On
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</If>
Explanation
This is moderately straight forward outside of Elastic Beanstalk. One usually adds an Apache rewrite rule like the following:
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
Or, if behind a load balancer, like we are in this case:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
However, these configurations only work within a <VirtualHost> block. Changing the RewriteCond to an <If> block allows it to work properly outside of a <VirtualHost> block, allowing us to put in in a standalone Apache config file. Note that standard Apache setup on CentOS (including the setup on ElasticBeanstalk) inculdes all files matching /etc/httpd/conf.d/*.conf, which matches the file path where we are storing this file.
The -n '%{HTTP:X-Forwarded-Proto}' part of the condition prevents it from redirecting if you are not behind a load balancer, allowing you to have shared configuration between a production evironment with a load balancer and https, and a staging environment that is single instance and does not have https. This is not necessary if you are using load balancers and https on all of your environments, but it doesn't hurt to have it.
Bad solutions I have seen
I have seen a lot of bad solutions to this problem, and it is worth going through them to understand why this solution is necessary.
Use Cloudfront: Some people suggest using non-cached Cloudfront setup in front of Elastic Beanstalk to do the HTTP to HTTPS redirect. This adds a whole new service (thus adding complexity) that isn't exactly appropriate (Cloudfront is a CDN; it's not the right tool for forcing HTTPS on inherantly dynamic content). Apache config is the normal solution to this problem and Elastic Beanstalk uses Apache, so that's the way we should go.
SSH into the server and...: This is completely antithetical to the point of Elastic Beanstalk and has so many problems. Any new instances created by autoscaling won't have the modified configuration. Any cloned environments won't have the configuration. Any number of a reasonable set of environment changes will wipe out the configuration. This is just such a bad idea.
Overwrite the Apache config with a new file: This is getting into the right realm of solution but leaves you with a maintenance nightmare if Elastic Beanstalk changes aspects of the server setup (which they very well may do). Also see the problems in the next item.
Dynamically edit the Apache config file to add a few lines: This is a decent idea. The problems with this is that it won't work if Elastic Beanstalk ever changes the name of their default Apache config file, and that this file can get overwritten when you least expect: https://forums.aws.amazon.com/thread.jspa?threadID=163369
Create a static health.html. If possible, as a configuration Template.
this is an easy solution
ssh into your EC2 instance
copy the contents of /etc/httpd/conf.d/wsgi.conf into a local file called wsgi.conf which will be placed in the base folder of your application
Edit the local version of wsgi.conf and add the following redirect rules within the < VirtualHost> < /VirtualHost> tags
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]
Change the “/status” to whatever page you are using as a health check page.
Save the file
Edit your < app>.conf file inside your .ebextensions directory to add a container command to copy this version of wsgi.conf over Amazon’s version
container_commands:
01_syncdb:
command: "django-admin.py syncdb --noinput" leader_only: true
02_collectstatic:
command: "django-admin.py collectstatic --noinput"
03_wsgireplace:
command: 'cp wsgi.conf ../wsgi.conf'
...
Deploy the code.
The deployed version of wsg.conf at /etc/httd/conf.d/wsgi.conf will now include the necessary redirect rules.
It should work and the file will be properly updated for each deployment. The only thing to watch for is if Amazon changes their base wsgi.conf file contents in the future, then your copy may no longer work.
Autor rickchristianson
For me, copying the wsgi.conf into place never worked. Either EB would fail to deploy, or the file would be overwritten.
The only answer I found that worked was here. Essentially, he used sed to insert the necessary rewrite rules into the wsgi.conf. He says the container command to add is
container_commands:
01_http_to_https_redirect:
command:
sed -i '/\<VirtualHost \*:80\>/a RewriteEngine On\nRewriteCond %{HTTP:X-Forwarded-Proto} !https\nRewriteRule \!/robots.txt https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]' /opt/python/ondeck/wsgi.conf
Don't forget to change your health check endpoint from robots.txt.
As a general strategy what has worked for us, with both Apache and Nginx EC2 instances behind an AWS secured Load Balancer, is:
At the load balancer, forward port 80 to port 80 on the instances
forward port 443 to port 8080 (for example) on the instances
In the web server, listen on both ports (80 and 8080)
redirect port 80 to port 443
Add environment variable "HTTPS", with value "on" to the EC2's, e.g. using the Elastic Beanstalk Software Configuration
Step 1 ensures that AWS internal traffic is treated "naturally".
Step 2 allows only secure external traffic to reach our code
Step 5 tells the web server and what's behind it (Laravel, in our case) that generated URL's should be given the https: scheme. Other frameworks may need some other environment variables set in order to trigger that behavior.