I see many on the web referring to the use of ProxyPreserveHost On to make sure that a proxied backend receives the original caller's host name. I am using this to tighten my web application's security (Java, Tomcat) whereas it would also be nice if my logs would show where users are actually at. My Tomcat logs now show this – pretty useless:
127.0.0.1 - - [17/Mar/2013:06:32:13 +0100] "GET /webapp/frontend/app/partials/welcome.html HTTP/1.1" 200 54
This is my configuration that does clearly not work as expected:
"/etc/apache2/sites-enabled/000-default"
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass /webapp http://localhost:8080/webapp
ProxyPassReverse /webapp http://localhost:8080/webapp
RewriteEngine On
RewriteRule ^/$ /webapp/frontend/app/ [proxy]
RewriteRule ^/webapp/$ /webapp/frontend/app/ [redirect]
RewriteRule ^/webapp/app/$ /webapp/frontend/app/ [redirect]
(from here on default stuff that was in the 000-default)
Enabled modules:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod rewrite
This is Ubuntu 12.10 running Apache HTTPD 2.2.22.
Your help would be much appreciated.
I assume your concern is that your access log still contains 127.0.0.1 in the client field. This isn't affected by ProxyPreserveHost; this is the IP address of the network end point that connected to Apache. For proxied connections from another server, this is going to always be localhost.
Also, ProxyPreserveHost is about preserving the Host header sent by the client, not about preserving the original IP of the client. In other words, it's about information going the wrong direction for your purposes; it's preserving the name of your server as sent by the client, not the client's IP.
I think your question is the same as this question. I'd add the additional note that you can log the X-Forwarded-For header in your logs using %{X-Forwarded-For}i in your CustomLog configuration.
Related
Couldn't find a question that had this specific setup, so was having trouble making some of the other answers work in my situation.
I have a CentOS server running a PHP-based website with Apache as the web server (working fine). I'm trying to now deploy a Flask-based app (using Gunicorn proxied through Apache) on a different port.
In my main httpd.conf file I have:
<IfModule proxy_module>
# Include the proxy information for VMS Flask Application
Include conf/extra/httpd-foo.conf
</IfModule>
And in my httpd-foo.conf file I have:
ProxyPreserveHost On
ProxyPass /foo http://localhost:8000/
ProxyPassReverse /foo http://localhost:8000/
Timeout 2400
ProxyTimeout 240
PHP website runs at: https://myphpwebsite.com
I'd like the Flask app to run at: https://myphpwebsite.com/foo
The problem I'm encountering is when I visit the Flask URL, is I encounter 2 issues. First, if I don't include a trailing slash after "foo", I get a 404 (because that directory doesn't actually exist in the real web directory. The second issue is that all my Flask routes assume "/" is "root", which it is not now. I don't know how to tell Flask that all routes should have "/foo" pre-pended to them.
Is this possible?
-- Some additional info --
I've tried running the gunicorn command with the "-E" option to tell it the SCRIPT_NAME which seemed to help only for the main page:
gunicorn app:app -b 0.0.0.0:8000 -t 180 -e SCRIPT_NAME=/foo -w 4
Currently, if I visit https://myphpwebsite.com/foo/ it results in a 500 Internal Server Error. I can see that my "not logged in" redirect appears to work and takes me to https://myphpwebsite.com/foo/login properly, but again it's just resulting in a 500 error.
I have kind of the same setup (apache, php, gunicorn, flask), and what works for me is to use VirtualHost and embed the ProxyPass in a Location-directive. So my conf-file looks something like
<VirtualHost *:80>
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPreserveHost On
<Location "/foo">
ProxyPass "http://127.0.0.1:8000/"
ProxyPassReverse "http://127.0.0.1:8000/"
</Location>
</VirtualHost>
This way, calls to https://mydomein.com/ are managed by Apache (managing php als always), and all the requests done to https://mydomein.com/foo are being delegated to GUnicorn (listening on port 8000).
I am trying to manage 2 domains with one server (running proxmox with several CT), I am using reverse proxy but seems to be wrong.. here's my configuration:
Let's say we have the main server running proxmox where I managed IPTables to redirect port 80 to the port 80 of my first container (CT01) and port 8109 to port 80 of my second container (CT02).
While using the port in my browser, everything is working well, and I am able to reach each container.
I bought 2 domain names, one for my private server (CT01) and another one for a business server (CT02). I associated both of the domain to my server address, and while typing one or another of them I am redirected to CT01 (normal, browser is running the address to the default port).
So now I tried to use reverse proxy in order to redirect to the desired server (DomainA -> CT01, DomainB -> CT02), I created 2 files in /var/apache2/sites-available/ :
/var/apache2/sites-available/domainA.com:
<VirtualHost *:80>
ServerName domainA.com
DocumentRoot /var/www/
</VirtualHost>
/var/apache2/sites-available/domainB.com:
<VirtualHost *:80>
ServerName domainB.com
ProxyPreserveHost On
ProxyRequests On
ProxyPass / http://x.y.z.h:8109/
ProxyPassReverse / http://x.y.z.h:8109/
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
Then I runned a2ensite domainA.com and a2ensite domainB.com. I restarted my apache service.
But nothing have changed: both my domainA and domainB redirect me to the same container (CT01).
Any idea?
What i may suggest is doing a new CT just to host a proxy (nginx for example) that will route the requests to one or the other site depending of the Host: field value of the HTTP request. This may be a little bit overkill if it's just for two sites, but when you want to have more, it can be very useful. Plus the NGinx can be used to cache, etc.
Let me know if you are interested. I know a tutorial that you may follow, but it's in french : http://blog.ganbaranai.fr/2013/08/il-etait-une-fois-proxmox-derriere-une-ip-unique/
Hope it helps.
Regards,
What I'm basically trying to accomplish is having my main website running a CMS written in Go. This will be located at www.example.com.
I also have applications written in PHP located in directories, such as www.example.com/clients/
How can I serve example.com/clients using Apache/PHP while serving example.com using Go built-in web server?
Via mod_proxy in Apache2, you can proxy different paths into different destinations at localhost or anywhere else accessible by your server, including within your local network (if your server can access it).
For this you would use ProxyPass (Apache2 Docs for ProxyPass, which is very useful reading) like the example below:
<VirtualHost *:80>
ServerName some.example.host.xyz
DocumentRoot /var/www/your-document-root
Alias /clients/ /var/www/clients/
ProxyPass /clients/ !
ScriptAlias /something-using-cgi/ /var/www/cgi-stuff/
ProxyPass /something-using-cgi/ !
ProxyPreserveHost On
ProxyPass / http://localhost:9876/
ProxyPassReverse / http://localhost:9876/
ProxyPass /elsewhere/ http://elsewhere.example.host.xyz:1234/
ProxyPassReverse /elsewhere/ http://elsewhere.example.host.xyz:1234/
</VirtualHost>
You'll want to be sure that you set your proxy security such that external users can't use your reverse proxy as a forward proxy, too. You can do that via ProxyRequests as described in the official Apache2 docs. The way I did this on a server is to put this in your server-wide config (you should verify on your own that this is secure enough):
# disables forward proxy
ProxyRequests Off
Andrew Gerrand has a good blog post about this for nginx but the principle is the same for Apache.
You want to set up Apache as a reverse proxy for requests coming in for the Go application.
For Apache you want to look at mod_proxy
They say that Apache's mod_rewrite is the swiss-army knife of URL manipulation, but can it do this?
Lets say I want to add a new application to my Apache webserver, where the only configurable option of the app is a port number.
I want to use & give out URLs of the form "http://hostname.example.com/app" rather than "http://hostname.example.com:8080". This would ensure that clients would be getting through the institution's firewall as well, and it's generally tidier.
My application includes absolute URIs in php, javascript and css, so I want to prepend my own root location to the URI in the applications internal links. I have no access to DNS records and so can't create another name-based virtual server.
Using Apache's mod_rewrite and mod_proxy modules, I can transparently redirect a client to the correct home-page of the application. But links within that homepage don't point a client to links relative to the new base URL.
So, what's the best way of proxying a request to an application that is listening on a specific port?
For example, if I had an application listening on port 8080, I could put this in my Apache configuration:-
<VirtualHost *:80>
SSLProxyEngine On
ServerName myhost.example.com
RewriteEngine On
UseCanonicalName On
ProxyVia On
<Location "/application">
RewriteRule ^/application/?(.*) http://localhost:8080/$1 [P,L]
</Location>
</VirtualHost>
This would work fine if the application didn't use absolute URLs, but it does. What I need to do is rewrite URLs that are returned by the application's css, javascript and php.
I've looked at the ProxyPass and ReverseProxyPass documentation, but I don't think these would work..?
I've also come across Nick Kew's mod_proxy_html, but this isn't included in the standard Apache Distribution, and my institution's webserver seems to have been fine for years without it.. Other than trawling manually (or using a grep -r | sed type expression) through the application's source code, or using this 3rd party add-on, are there any other ways to go about this?
Could I perhaps use some of the internal server variables in a mod_rewrite rule? For example a rewrite rule based on ’HTTP_REFERER'?
Using mod_proxy would work just fine. For instance, I mapped https://localhost/yalla/ to point to a subdirectory of my webserver:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from localhost
</Proxy>
ProxyPass /yalla/ http://yalla.ynfonatic.de/tmp/
If you implement this, you'll note that the pictues of the directory-listing aren't visible; this is because they're below the /tmp/ directory on the remote server, hence not visible.
So, in your case you'd do:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from localhost # Or whatever your network is if you need an ACL
</Proxy>
ProxyPass /app/ http://hostname.example.com:8080/
Like with everything in Apache configuration, watch those trailing slashes when referring to directories.
Good luck!
Alex.
We are using ProxyPass to redirect all "/r" requests to jboss on port 18080 as follows:
ProxyPreserveHost on
ProxyPass /r http://localhost:18080/redirectService/
ProxyPassReverse /r http://localhost:18080/redirectService/
But, that causes the IP address logged in jboss's access log as "127.0.0.1". Does somebody know how can we preserve the original IP from where the request came in HttpServletRequest? We want to acesss it from jboss servlet request in doGet()
You can get the original host from X-Forwarded-For header field.
The answer of JasonW is fine. But since apache httpd 2.4.6 there is a alternative: mod_remoteip
All what you must do is:
May be you must install the mod_remoteip package
Enable the module:
LoadModule remoteip_module modules/mod_remoteip.so
Add the following to your apache httpd config. Note that you must add this line not into the configuration of the proxy server. You must add this to the configuration of the proxy target httpd server (the server behind the proxy):
RemoteIPHeader X-Forwarded-For
# replace IP with the remote server you trust
RemoteIPInternalProxy 10.123.123.1/24
See at http://httpd.apache.org/docs/trunk/mod/mod_remoteip.html for more information and more options.
Security warning! Only do this for proxies you trust. Otherwise someone can fake their IP.
This has a more elegant explanation and more than one possible solutions. http://kasunh.wordpress.com/2011/10/11/preserving-remote-iphost-while-proxying/
The post describes how to use one popular and one lesser known Apache modules to preserve host/ip while in a setup involving proxying.
Use mod_rpaf module, install and enable it in the backend server and add following directives in the module’s configuration.
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
(2017 edit) Current location of mod_rpaf: https://github.com/gnif/mod_rpaf
If you have the capability to do so, I would recommend using either mod-jk or mod-proxy-ajp to pass requests from Apache to JBoss. The AJP protocol is much more efficient compared to using HTTP proxy requests and as a benefit, JBoss will see the request as coming from the original client and not Apache.
If you are using Apache reverse proxy for serving an app running on a localhost port you must add a location to your vhost.
<Location />
ProxyPass http://localhost:1339/ retry=0
ProxyPassReverse http://localhost:1339/
ProxyPreserveHost On
ProxyErrorOverride Off
</Location>
To get the IP address have following options
console.log(">>>", req.ip);// this works fine for me returned a valid ip address
console.log(">>>", req.headers['x-forwarded-for'] );// returned a valid IP address
console.log(">>>", req.headers['X-Real-IP'] ); // did not work returned undefined
console.log(">>>", req.connection.remoteAddress );// returned the loopback IP address
So either use req.ip or req.headers['x-forwarded-for']