apache reverse proxy - how to hide internal network - apache

my scenario is this: I have a machine with Apache 2.2 configured as reverse proxy
and another machine on which there is Apache Tomcat7 listening on port 8080.
My objective is to make internet users accessing a resource "am" (deployed on Tomcat)
WITHOUT using IP address of the Tomcat machine but only contacting the reverse proxy.
So far I set httpd.conf of the reverse proxy:
ProxyPass /am http://tomcat_server.com:8080/am
ProxyPassReverse /am http://tomcat_server.com:8080/am
But the problem is that the reverse proxy tells the users to contact tomcat_server
but of course tomcat_server is a private IP and cannot be accessed by internet users.

In your Tomcat server.xml config file,
edit the http Connector to include attributes: proxyPort, proxyName - such that it resembles:
<Connector
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
proxyPort="80"
proxyName="url.domain.clients.use.for.your.webapp"
/>
proxyPort="80" -- makes Tomcat return data to your Apache proxy
proxyName="url.domain.clients.use.for.your.webapp" -- makes Tomcat return the url to Apache proxy that your user clients should process, instead of tomcat_server.com which they can't access
Here are some older Tomcat docs that mention it:
proxyName
If this Connector is being used in a proxy configuration, configure
this attribute to specify the server name to be returned for calls to
request.getServerName(). See Proxy Support for more information.
Proxy Support
The proxyName and proxyPort attributes can be used when Tomcat is run
behind a proxy server. These attributes modify the values returned to
web applications that call the request.getServerName() and
request.getServerPort() methods, which are often used to construct
absolute URLs for redirects. Without configuring these attributes, the
values returned would reflect the server name and port on which the
connection from the proxy server was received, rather than the server
name and port to whom the client directed the original request.
I worked through a similar need, with having Tomcat listen only on its localhost:
How can Tomcat 9 Connector listening 127.0.0.1 reverse proxy to Win. Apache 2.4 with private ServerName

If your problem is references to the origin server in HTML, check out mod_proxy_html or mod_substitute.

Related

Apache to Tomcat Cookie issue when using SSL termination through nginx

I'm testing our app on a kubernetes cluster. So we have Nginx Controller which handles SSL termination and passes HTTP traffic to Apache server. Apache server handles static content and forwards all JSP related to tomcat.
For some reason the webapp doesn't work on the first try (website works fine though) when doing SSL termination but if I reload the page and try to use the app again then during this second attempt everything works fine (means it doesn't load some of the automatic functions on first attempt and can be reproduced by clearing the cache and logging in).
I spoke to dev they mentioned it could be cookie issues.
Current setup which is not working:
Nginx controller (SSL termination) -> Apache (HTTP port 80 ) -> Tomcat (HTTP port 8080).
Setup which works fine:
Nginx controller (SSL passthrough) -> Apache (HTTPS port 443) -> Tomcat (HTTPS port 8080).
I can't get rid of Apache in between and it is really needed for the app temporarily.
What settings are required to make this work? I've tired the following:
Disable port 443 on apache
Disable 8443 ports and all redirects to port 8443 and listen only 8080
Modified web.xml to set http-only to true and secure bit to true on tomcat server.
<session-config>
<session-timeout>60</session-timeout>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
Anything else that needs to be done? I've spent a day trying to troubleshooting this and couldn't figure it out yet.
Server.xml contains only these enabled lines, rest of them are commented out or defaults:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000" />
<Connector port="8009" maxThreads="2000"
enableLookups="false" redirectPort="80" protocol="AJP/1.3"/>
<Engine name="Catalina" defaultHost="localhost" jvmRoute="server001">
# Removed cluster config since they're all default
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Context path="" docBase="/usr/local/tomcat/webapps/ROOT.war" debug="0" distributable="true">
</Context>
http.conf - has nothing but default since SSL is disabled. So no virtual host. Only thing that's added to http.conf is
JkMount /* ajp13
Worker.properties is the following.
# - An ajp13 worker that connects to localhost:8009
worker.list=ajp13
#------ DEFAULT ajp13 WORKER DEFINITION ------------------------------
# Defining a worker named ajp13 and of type ajp13
worker.ajp13.port=8009
worker.ajp13.host=$(TOMCAT_SERVER)
worker.ajp13.type=ajp13
worker.ajp13.reply_timeout=15000
worker.ajp13.lbfactor=1
#worker.ajp13.cachesize
worker.loadbalancer.balanced_workers=ajp13
The webapp needs to communicate with Java TCP server through websocket so we have a webSocket server written in nodejs. It just forwards traffic from websocket to Java server TCP connection.
But it has its own SSL certs setup. Since by default Nginx controller on GCP doesn't deal with ssl termination for TCP services, I have configured NodeJS backend service to accept SSL traffic directly on port 1234 for example. This service runs on the tomcat server. Don't know if this is creating a conflict since they all connect to same domain name.
Your problem probably arises, because the application does not understand that the request came from a secure channel.
Servlet API applications understand that a request was sent through a secure channel based on the result of ServletRequest#isSecure(). For requests that came through HTTP, this value depends on whether SSL was enabled or not.
When you use the AJP connector, this information and many more are trasmitted by the Apache server. This works perfectly well in the "SSL passthrough" configuration. However when the SSL connection terminates at NGINX you are in the situation described by the Reverse Proxy HOW-TO:
In some situations this is not enough though. Assume there is another less clever reverse proxy in front of your web server, for instance an HTTP load balancer or similar device which also serves as an SSL accelerator.
Then you are sure that all your clients use HTTPS, but your web server doesn't know about that. All it can see is requests coming from the accelerator using plain HTTP.
If you wanted to keep this configuration for a long time, I would suggest following the aforementioned HOW-TO. For short-term usage there is a simpler solution: you need to hardcode in Tomcat's configuration that all AJP requests are secure:
<Connector port="8009"
maxThreads="2000"
enableLookups="false"
protocol="AJP/1.3"
secure="true"
scheme="https"/>
The scheme attribute tells Tomcat which scheme was used by the original client, the connector will still use AJP.

How to override scheme and is_ssl in apache HTTP Server for mod_proxy_ajp

We are running Tomcat 7 behind a load balancer that works also as SSL terminator, and an Apache HTTP Server 2.4. The Apache connects to the Tomcat via mod_proxy_ajp.
For the application it is important that Tomcat is aware that the request is coming in via HTTPS and is thus secure. As e.g. this article recommends, it is common to configure this on the Tomcat's Connector using the attributes secure="true" and possibly scheme="https" proxyPort="443". While this works, it is inconvenient since we are using HTTP for some purposes as well, and thus we would need to set up two Tomcat connectors for this purpose. And it has a smell, since this way we basically tell Tomcat to override the wrong information it gets from the Apache HTTP Server that the request is HTTPS instead of HTTP, instead of telling the Apache that it should send the correct information on the protocol and secure status.
So my question: is it somehow possible to configure the Apache HTTP Server itself that it passes the correct information via the AJP protocol: that the request is received via HTTPS and is secure? The problem is that it doesn't know it's HTTPS, since there is a SSL terminator before it and the requests arrives via HTTP, as far as it is concerned. Can I tell the Apache somehow that it's actually HTTPS?
A partial solution seems to be to set the protocol on a ServerName directive in the virtual host in the Apache HTTP server:
ServerName https://whatever
This way any Location: headers in redirects seem to be rewritten to https in the Apache, but the Tomcat is still passed the wrong information via AJP.
I always thought that AJP transfers this information automagically - but I'm not using mod_proxy_ajp, rather mod_jk. It's one of the reasons why I much prefer AJP over HTTP (and proxying).
Might be worth to change the module/connection

how set website and webservice on the same port (8080)?

In a server hosting a website address.com (managed with drupal) with an apache2 server (running on port 8080) I would like to install a webservice (tomcat7 / axis2) which runs on the same port 8080. Is there a way do it? There're also svn, trac running on that port. Unfortunately, due to security restrictions, that's the only port accessible externally.
Thank you
You can absolutely expose multiple services on the same port, as long as they all live in distinct URL namespaces. For example, you're already running Trac and svn on port 8080, so obviously you are already doing exactly what you're asking about.
To add Tomcat to the mix, you would typically:
Run Tomcat locally on another port, and then
Use ProxyPass and ProxyPassReverse to expose the Tomcat service via your webserver on port 8080.
For example, if you wanted to make your Tomcat instance visible at http://myserver:8080/tomcat, you might add something like this to your Apache configuration:
ProxyPass /tomcat/ http://localhost:8888/
ProxyPassReverse /tomcat/ http://localhost:8888/
You can read more about these directives here. Note that you may need to perform additional configuration of your Tomcat application to reflect the fact that it is externally visible at /tomcat/.
You can also potentially take advantage of virtual hosting, assuming that you control DNS for this system; in that case, you can have:
http://myserver-trac:8080/
Lead to a different VirtualHost configuration than:
http://myserver-tomcat:8080/
You can read more about name-based virtual hosting here.
When you install the webservice listening on another port (at localhost), you can use Apache as a proxy (using mod_proxy) to access that service.
Maybe usefull: How to rewrite / proxy an Apache URI to an application listening on a specific port / server?

How to keep apache as front and tomcat as back end?

Basically i want my tomcat to run on PORT 80 how do i do that because whenever i have to access something then i have to go for localhost:8080/resource but instead i want to use the link as only localhost/resource how do i achieve this?
Currently on my machine apache is running on 800 port and tomcat on 8080.
it seems you are looking for something called Reverse Proxy. Using Reverse Proxy, you will have
apache on 80 port
tomcat on 8080 port
so when access http://xxx.test.com/resource, the request first go though apache, apache then pass the request tomcat, tomcat do the corresponding things and return response to client.
have a look at:
http://www.apachetutor.org/admin/reverseproxies
mod_jk: http://tomcat.apache.org/download-connectors.cgi
Tomcat documentation has a HOWTO for this.
http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html
Its a good practice to never expose Tomcat directly internet. You can use Apache for serving static content and send only those requests to tomcat that need dynamic content.
In server.xml find the element that reads
Connector port="8080"
and change it to 80. Save and restart tomcat.
Just make sure that apache is running on port 800 otherwise it will now clash with tomcat.
To modify the HTTP port for Tomcat, modify the configuration file server.xml (located in Tomcat's conf directory). Find the HTTP connector element (that is currently configured to port 8080), change the port number to 80, and restart Tomcat.
Note that this is not going to work if any other running service is currently bound on port 80.

Apache & JBoss use port 80 at the same time

I have both Apache 2 and JBoss 4.2.3 on the same machine and would like both of them to use port 80. There are several ways I see people doing this mod_jk, mod_proxy, but I'm not sure which one is the best.
I don't need any load balancing, but I do need HTTPS.
You can't have two applications listening to the same tcp port (80) at the same time. You can use mod_jk to have http requests on port 80 routed from Apache server to the JBoss server. This is the method I am most familiar with and prefer. mod_proxy should also work, but I find that method a little more complicated.
Configuring https on Apache is probably best dealt with as a separate topic. There are issues with purchasing a ssl certificate, creating a self-signed certificate, etc.
There are two steps to accomplish configure mod_jk to route requests from the Apache server to the JBoss server:
Configure the Apache web server to forward some requests to the JBoss server.
The Apache configuration will vary depending on the distribution of Apache that you are using (windows, RHEL, debian, built from source, etc.) but the concepts should be similar for any Apache installation.
You need to download mod_jk for your platform from the tomcat web site:
http://tomcat.apache.org/download-connectors.cgi
Your OS vendor may provide a binary for you, so check there first. You may also compile mod_jk yourself if you prefer.
Copy the mod_jk binary (mod_jk.so for Linux/UNIX system, not sure about windows) into your Apache servers modules directory (this depends on the Apache distribution you are using).
Add the equivalent directive to your Apache configuration:
LoadModule jk\_module /usr/lib/apache2/modules/mod\_jk.so
You should add two configuration files to the Apache configuration directory: mod_jk.conf and workers.properties. You should include mod_jk.conf from the main Apache configuration file:
Include /etc/apache2/mod\_jk.conf
The workers.properties file is included by mod_jk.conf with the JkWorkersFile directive.
More detailed settings for mod_jk.conf can be found at the tomcat documentation page:
http://tomcat.apache.org/connectors-doc/reference/apache.html
The important directives are:
JkWorkersFile (specifies where the workers.properties file lives)
JkMount (mount point for mapping of URI to tomcat worker)
An example:
JkWorkersFile /etc/apache2/workers.properties<br>
JkMount /examples/* myworker<br>
JkMount /examples myworker
These directives map the /examples and /examples/ URI to the myworker tomcat worker.
Conceptually you can think of a worker as representing a tomcat or JBoss instance and the mount as a way of mapping a URI to a worker. This way of representing things allows one Apache server to be the front end for several tomcat or JBoss servers. This can be handy if you have only one IP address you can use but wish to run several application servers behind one Apache server.
The workers.properties files describes the tomcat or JBoss server(s) that the Apache server will connect to. Important entries in this file are:
worker.list=myworker<br>
worker.tomcat.type=ajp13<br>
worker.tomcat.host=localhost<br>
worker.tomcat.port=8009
There are other worker properties that can be found in the tomcat documentation page for the workers.properties file:
http://tomcat.apache.org/connectors-doc/reference/workers.html
Configure the JBoss server to accept connections from the Apache server
The JBoss server is configured to accept mod_jk connections on port 8009 (the default ajp port) out of the box, but it is good to know where to configure this in case you want to change any of this in the future.
The configuration is in the tomcat based portion of the JBoss server located in ${JBOSS_SERVER_CONFIGURATION}/deploy/jbossweb.sar/server.xml. This is for JBoss AS 5.1.0.GA, previous versions are in a similar location. The mod_jk connector is configured in the Connector section for the AJP 1.3 protocol and looks like:
<Connector protocol="AJP/1.3" port="8009" address="${jboss.bind.address}" redirectPort="8443" />
The most common reason to modify this section is if you have multiple tomcat or JBoss servers connecting to apache via the AJP protocol, you can adjust the port number that the AJP connector will listens on so there are no conflicts.