Forwarded Tomcat through Apache uses wrong Context path - apache

Okay let me explain my problem really fast. I have a JEE Programm running on my tomcat server. The server has some user defined in the tomcat-users.xml When i test my programm on my local machine everything works fine.
However if i deploy the .war on my server and i want to access a Rest Endpoint i get a 401 unauthorized error. If i remove the users security check i can work fine with the program. So the URLs and server setup is correct.
I think that the problem is somehow related to the forwarding of tomcat through my apache.
So lets assume i have an apache running on http://myIp.de
then i forwarded tomcat with following apache config:
ProxyRequests off
ProxyPass /tomcat http://localhost:8181/ nocanon
ProxyPassReverse /tomcat http://localhost:8181/
so now i can reach tomcat through: http://myIp.de/tomcat
also i can "speak" to my app via: tomcat/myApp
But somehow the Authentizication now fails. And i think the problem is
somehow related to wrong context path. Because tomcat/manager
also fails to login.

Make your life easier by deploying your app under /tomcat on tomcat too. This way there's no path-translation required. Keep in mind that you'll get all the session cookies tied to a specific path and this path is not necessarily translated once forwarded to the client.
Also, sooner or later you might need
ProxyPreserveHost On
(look it up) or utilize mod_jk to preserve this header (and more information) automatically.
Edit: Following your comment, Basic Auth headers seem not to be forwarded to tomcat as well. I haven't attempted this myself, but all the places that I've looked up seem to imply that there'd be some duplication (e.g. second credentials file for Apache) - that doesn't look good. In this case I'd suggest to try out mod_jk rather than mod_proxy. You'll use the JkMount directive, rather than ProxyPass and need a workers.properties, but mod_jk is a lot better in keeping the full context of the request when forwarding to tomcat. I've had good experience with it so far and have only heard little complaints about it - largely in situations that were pretty huge and complex/complicated anyway. At least you should try if it solves your problems.

Related

How to configure Apache to connect parallel two Tomcat Versions via AJP

I was not able any suitable solution on the web and all my trials result in failure.
My goal is to set up Tomcat9(TC9) while Tomcat7 (TC7) is still running, so I can configure and test the applications without any interference for the users. After I finished the configuration I want to switch to TC9 so the URLs of the webapps do not change and the Users won't notice the change.
I set up successfully TC9 with an AJP Connector Port on 8010 and I used the existing config file of the httpd and copied the /etc/httpd/conf.modules.d/00-tomcat7.conf to /etc/httpd/conf.modules.d/00-tomcat9.conf and edited accordingly
ProxyPass / ajp://localhost:8010/
However the old pass does not work anymore
ProxyPass / ajp://localhost:8009/
There might be a problem with the URL as I implemented it like so:
https:////
I had several attempts with configuration of the ProxPass like
ProxyPass /<webappgroup1> ajp://localhost:8009/<webappgroup1>
ProxyPass /<webappgroup2> ajp://localhost:8010/<webappgroup2>
But how does the actual endpoint URL look like and do I need to deploy my webapps still as #.war?
however like this I always get the Browser Error This site could not be found.
I don't know in which logs i could find more Information what is going wrong.
An example for the ProxyPass config or input of any kind is very much appreciated.
Thanks in advance!

ProxyPass module configuration in apache tomcat

I found one documentation here to run multiple node application on single port using proxypass, I understood the concept, it just forward the request to node application port unsing ProxyPass. In that example, they used httpd, and I am using tomcat.
My question is, how can I do same configuration in tomcat?
simply I am expecting tomcat configuration for this httpd configuration.
ProxyPass /node http://host.xyz.com:3000
You really should consider using Apache httpd (or any other frontend) for this purpose. This is the software that handles the requirement best - and tomcat best serves application data.
Also, Apache httpd knows how to handle port 80 or 443, something that needs some extra work with tomcat (if you don't want to run it as root. And you actually don't want to run it as root)
It doesn't require so many extra resources, use the appropriate tool for the job. And, when you use mod_proxy, look up all the related options and understand what they're there for. You probably also want ProxyPreserveHost On, but I'll stop here.
I hope the document will be helpful.

What's a simple way to serve http://localhost as https://someOtherDomain?

I run a local development web server for testing out code changes.
Often I have to test my local changes with remote services that can only connect securely to another domain.
e.g. https://external1.com will only talk to https://someOtherDomain.com, but I've got to test integration of my new code changes with https://external1.com
While I've got a setup configured that works, it seems complex, and took a bit to get setup right. It seems to me that many developers would want to do this same thing, so my question is this:
Is there an easy way to proxy my local webserver as https://someOtherDomain.com ?
EDIT: So maybe this should be asked this way - Does a command line or GUI tool exist that you can pass a local port and a domain name, and it serves your local port securely over https://someOtherDomain.com - no config or SSL cert creation required? Of course it'd be nice if the SSL cert could be replaced through configuration if need be, but by default, it'd work automatically, by using a precanned SSL cert. And even though I'm using Apache, I'm looking for a solution that actually doesnt use Apache - it uses something else. Why? Because I want this solution to work well with any other webserver that's being used by people on our team - as we all run different stacks, and I'd like to be able to let any of us securely serve our sites without having to configure each webserver individually.
Here's my current setup for taking my local webserver and serving it up at https://www.someOtherDomain.com
To test this locally, I've been:
editing my hosts file, and adding an entry to make www.someOtherDomain.com point to my local machine, which of course is running my dev server. This makes it so my local site is now available at http://www.someOtherDomain.com
127.0.0.1 www.someOtherDomain.com
Running Apache with a SSL Cert setup and mod_proxy to redirect all https requests to my local http server, thus making my site available at https://www.someOtherDomain.com. Here's my Apache config for this:
ServerName www.someOtherDomain.com
<Location /balancer-manager>
SetHandler balancer-manager
</Location>
ProxyPass /balancer-manager !
ProxyPass / balancer://mycluster/
<Proxy balancer://mycluster>
BalancerMember http://localhost route=1
</Proxy>
ProxyPass / balancer://mycluster
ProxyPassReverse / balancer://mycluster
SSLHonorCipherOrder On
SSLProtocol -ALL +SSLv3 +TLSv1
SSLCipherSuite RC4-SHA:HIGH:!ADH
# Rewrite all http requests to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
I run this on a mac, but am interested in solutions for linux as well. I've seen various Man in the Middle proxy's that sound like they'd work with some configuration... but I'm looking for something really simple to install and run - not just for me, but something I can tell team members about too, as we may all have to do this a lot in the future.
IMPORTANT NOTE: My local webserver isn't running on Port 80, though I've put it this way in the above example, to keep it simple. I understand port 80 on a mac is a bit special, but am very happy with solutions that work fine on all ports but port 80.
I think mitmproxy can do this for you, as least on linux and os-x. I haven't tried it myself but this question seems to show how it is done. It's still not a trivial program though.
There are however other approaches, which I have used:
The first one is the most pretty simple one, create a DNS entry for develop.mydomain.com which points to 127.0.0.1 and a single certificate for a (sub)domain where you control the DNS. Spread that certificate to all your developers. They'll still need to setup SSL themself but they don't need to generate certificates anymore. It has the added benefit that everybody is developing against https://develop.mydomain.com which allows them to share the configuration.
For bonus points, create a DNS entry for *.develop.mydomain.com and a wildcard certificate and your developers can have different sites (e.g. https://project1.develop.mydomain.com and https://project2.develop.mydomain.com) on there local machine. (Contrary to what the internet sometimes tells you, name based virtual hosting works fine with SSL as long as the certificate is valid for all the named hosts). Since the domain is the same for everybody you can consider getting a valid wildcard certificate to get rid of the warnings.
Unlike the solutions below this works even outside of the office network, which may be relevant when people are working from home or at the customer.
Building on this you could also create DNS entries for the internal IP's of the developer machines (if those are fixed). This does add some work, but it means the ongoing work of a developer can be reached by others in the local network, which can be very convenient for demo's, testing on mobile devices, etc.
An other option is to configure a single machine to proxy for all your developers. Create a DNS entry pointing to the internal IP of this box on something like *.develop.mydomain.com, a matching wildcard certificate and configure that box once with the correct certificate. Now you can create a virtual host for each proxied server, and again, all sites will be reachable throughout the local network, but it does require the developer to have fixed ip addresses (or hostnames added to DNS through DHCP).
Combined with the ability of apache to include all files in a directory in it's configuration makes it trivial to create a script which adds a new site based on a template. All it has to do is write a new file based on the requested subdomain plus the destination and reload the apache config. This means something like a simple PHP script can do what you want the application to do.
If you want to expose your web on your local machine to the internet try Runscope Passageway, it's easy to setup and "just works" (from experience).
Another alternative is ngrok which I also used, but it didn't always work for me.

apache reverse proxy: how to forward proxy server's HTTP_HOST

Our local development setup requires a box in the DMZ, and each developer has a line in its apache config for proxying. Looks something like:
ProxyPreserveHost on
ProxyPass /user1/ {user1's IP}
ProxyPassReverse /user1/ {user1's IP}
ProxyPass /user2/ {user2's IP}
ProxyPassReverse /user2/ {user2's IP}
#etc
Our public URLs become {DMZ server}/user1, {DMZ server}/user2, etc. The problem is that on the dev's boxes, the value of $_SERVER['HTTP_HOST'] is just {DMZ server}, without the user's subdirectory. The desired behavior is to have /user%/ as the real host name.
I've tried overriding the HOST var, and some rewrite rules, but nothing has worked.
Creating subdomains is not an option.
thank you for any help!
http://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypreservehost seems to be the answer.
Im going to take a stab and suggest this:
SetEnvIf Host (.*) custom_host=$1
RequestHeader set X-Custom-Host-Header "%{custom_host}e/%{REQUEST_URI}e/%{QUERY_STRING}e"
That should hopefully set a request header called X-Custom-Host-Header that you can then pickup in PHP. If you want, you can try to override the Host Header, but I'm not sure on the implications of that. The Host header is a special HTTP header and generally only contains the host portion of an HTTP request, not the full request url.
Untested unfortunately, but it would help if you could clarify in a bit more detail what you are looking for.
EDIT, THIRD ANSWER:
Looks like Apache has heard this complaint before and the solution is mod_substitute. You need to use it to rewrite all the URLs returned in the document to insert /user1/.
EDIT, SECOND ANSWER:
Based on the additional information in your comments, I'd say your Apache config on your DMZ server is correct. What you are asking for is to have the developer machines generate URLs that include their context path (which is the J2EE term for something analogous to your /user1/ bit). I don't have any experience with PHP so I don't know if it has such a facility, but a quick search suggests it does not.
Otherwise, you'd have to roll your own function that converts a relative URL to an absolute URL, make that configurable so you can have it add something to the host name, and then force everyone to use that function exclusively for generating URLs. See, for some guidance, "Making your application location independent" in this old (outdated?) PHP best practices article for a solution to the related problem of finding local files.
PREVIOUS ANSWER: (doesn't work, causes redirect loop)
I'm still not clear what you are trying to do or what you mean by "Running on the dev apps are apache and PHP mainly, for hosting various applications", but as an educated guess, have you tried:
ProxyPass /user1/ {user1's IP}/user1/
ProxyPassReverse /user1/ {user1's IP}/user1/
If I were setting up the sort of environment you seem to be wanting to have, I'd want $_SERVER['HTTP_HOST'] to be {DMZ server} on every dev machine so that the dev machine's environment looks just like (or at least more like) production to the code running on it.

apach proxy requests to multiple different subdomains

I have a web app at domain1.com which needs to be able to make requests to many different sites, too many to add specific vhost information for each site, what I'd like to be able to do is make a request with the web app to its hosting apache server like this
/domain1.com/some/path
/domain2.com/some/path
and for it to be send to
https://domain1.com/some/path
https://domain2.com/some/path
I've tried different settings using apaches ProxyPass but with no success
How do I do this?
That should be able to work with these directives:
ProxyPass /domain1.com/ https://domain1.com/
ProxyPass /domain2.com/ https://domain2.com/
A request to https://yourproxy.com/domain1.com/some/path should then be forwarded on to https://domain1.com/some/path. It is also possible you may need to use some of the SSLProxy* directives from mod_ssl.
Edit Based on the comment, you might try this:
ProxyPass / http://
I just now tried that, and http://myproxy.com:port1/myserver.com:port2/some/path was sent on to (and returned from) http://myserver.com:port2/some/path.
However, this seems like a bad idea from a security standpoint. I suppose it does allow the proxy to sit on one side of a firewall and allow the backends to be behind the firewall. I am certainly no web expert, but it just feels a bit sketchy.