How to filter requests so that apache handles them and not tomcat? - apache

For various reasons I want to shutdown my server after a certain period of idle time. I am running Tomcat 8.5.29 and Apache2 (not sure the version) on Debian 4.9.88. I wrote a script to look at the last time Tomcat had an access. I only have one app on the server and it is at "http://hostname/source/". My problem is that there are number of webserver vulnerabilities out there and I am getting a constant flow of requests to:
"GET / HTTP/1.1"
"POST /GponForm/diag_Form?images/ HTTP/1.1"
"GET /jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system%3Aservice%3DMainDeployer HTTP/1.1"
"POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1"
What I would like to do is stop anything that doesn't begin with "/source" from even getting to tomcat. I presume that a rewrite or something in Apache can do it, but I am not sure how the requests get to Tomcat in the first place.
Any ideas?

There are two possible ways for requests to reach Tomcat:
The probes send requests directly to the Tomcat port (typically port 8080). You can fix this by restricting Tomcat's listening address to the loopback address, by adding the attribute address="127.0.0.1" to the corresponding Connector element in conf/server.xml. Or you can just block port 8080 in your firewall.
The requests are forwarded from Apache to Tomcat via a reverse proxy configuration in Apache. This means there is a line such as the following in one of the Apache configuration files:
ProxyPass / http://127.0.0.1:8080/
If you add an explicit path prefix to both arguments, you can restrict which requests are passed to Tomcat:
ProxyPass /source http://127.0.0.1:8080/source
This ensures that only requests that begin with "/source" are forwarded to Tomcat.
Some Apache configurations use the AJP protocol instead of HTTP for proxying, but the same reasoning applies.

Related

Apache web server not working on https port work on http

Good day,
I have a apache web server (10.8.112.65), I configure ProxyPass to direct it to my app server, the ProxyPass code is as follow in the httpd.conf:
ProxyPass "/mfp" "http://101.7.2.63:9080/mfp"
ProxyPassReverse "/mfp" "http://101.7.2.63:9080/mfp"
And its listen to port 80
Listen 80
This is working fine, From my device, I fire a http url request to 10.8.112.65, it will direct to http://101.7.2.63:9080/mfp to process. For example:
Fire http://10.8.112.65/mfp/api/adapters/MyAdapter/public/init/
It will direct to http://101.7.2.63:9080/mfp/api/adapters/MyAdapter/public/init/ , this is good.
However, From my device, I need to fire a https url request instead of http. Thus, I change the Listen port to 443, and I try to fire https request as follow:
Fire https://10.8.112.65:443/mfp/api/adapters/MyAdapter/public/init/
This one could not reach to my app server, and from the web server access log, I saw it print out
10.3.131.36 - - [13/Feb/2020:18:58:01 +0800] "\x16\x03\x01\x02" 400 226 "-" "-"
10.3.131.36 - - [13/Feb/2020:18:58:01 +0800] "\x16\x03\x01\x02" 400 226 "-" "-"
Where 10.3.131.36 is my device ip address.
I try to search google for this, but didnt get any result that I understand.
Any ideas on this?

How to use Apache to redirect requests for Node-Red?

I'm running in AWS a Ubuntu with a docker server (managed by Portainer) with this two running containers:
1 - NodeRed (Serving my APIs)
2 - Apache (Hosts the site that consumes the APIs from NodeRed above)
I've configured a domain to this server and setted apache to work with SSL. The apache is running ok with my site through HTTPS, but the problem is that the NodeRed (that runs in port 1080) is not configured to run in SSL. This causes a malfunction in my website since that my API endpoints are being running under HTTP and being blocked by the browser due security reasons.
The question is: is there a way to create some kind of "mapping" in apache that receives the request from HTTPS and redirect to the NodeRed in HTTP (the two are running in same server)?
My idea is to create a subdomain like https://api.mysite.com that sends the request for apache and then apache redirects it to my NodeRed. Is that possible?
There is no need to expose the API to the outside world if you don't want to. Since your apache is running correctly and both containers are running on the same host, just use proxy to forward API requests to the API container.
You can achive this by add two lines to your apache config i.e.
ProxyPass /api/ http://127.0.0.1:1080/
ProxyPassReverse /api/ http://127.0.0.1:1080/

Monit only using HTTP for HTTPS website

I'm trying to monitor a VHost on the local Apache instance via Monit. The same domain accepts both http and https traffic, so I wanted to monitor both.
Also, the IP that the domain resolves to goes to a server that load balances the traffic between the current Apache instance and another server running Apache. I need Monit to monitor the local instance, and I was hoping to avoid adding any records in the /etc/hosts file, so I was thinking that Monits config setting with http headers [] would suffice, and I think it is (Just monitoring localhost, but setting the headers Host to the vhost domain).
Anyways, the main problem I seem to be running into, is even though I configure Monit to monitor the host via both http and https protocols, it monitors both hosts via just http, however the port is set to 443 for the one I need using https protocol.
The Monit config file for Apache is:
check process httpd with pidfile /var/run/httpd/httpd.pid
start program = "/bin/systemctl restart httpd.service" with timeout 60 seconds
stop program = "/bin/systemctl stop httpd.service"
check host localhost with address localhost
if failed
port 80
protocol http
with http headers [Host: www.domain.com, Cache-Control: no-cache]
and request / with content = "www.domain.com"
then restart
if failed
port 443
protocol https
with http headers [Host: www.domain.com, Cache-Control: no-cache]
and request / with content = "www.domain.com"
then restart
if 5 restarts within 5 cycles
then timeout
And here's the Monit status for that check:
[root#server enabled-monitors]# monit status localhost
The Monit daemon 5.14 uptime: 14m
Remote Host 'localhost'
status Connection failed
monitoring status Monitored
port response time FAILED to [localhost]:443/ type TCPSSL/IP protocol HTTP
port response time 0.001s to [localhost]:80/ type TCP/IP protocol HTTP
data collected Tue, 26 Apr 2016 10:44:32
So it's fairly obvious to me that the https is failing because its still trying to use port HTTP, even though I have protocol https in the configuration.
Any input would be much appreciated. I have a feeling this may be a bug, and ill create an issue in the Monit Github repo, but I wan't to make sure it's not something silly that I overlooked.
Thank you!
Late reply here, but I thought I would still post for readers who stumbled upon the same issue.
The problem seems to be not with Monit using port HTTP despite check configured for HTTPS. It always reports HTTP protocol in status (a display bug).
The real issue is likely with Monit not supporting SNI for SSL, so it ignores the with http headers [Host: www.domain.com ... in your https check. Thus the check fails because Monit is actually testing https://localhost.
I've filed bug with Monit developers here.

reverse proxy apache to localhost server

I've got a web app running on localhost:3000. I also have an apache server. I would like to reverse proxy the apache server so that requests to /mywebapp get forwarded to the server running on localhost:3000.
I currently have the following config at the bottom of my httpd.conf file, but I'm getting a server error when I try to access it:
ProxyPass /mywebapp http://localhost:3000
ProxyPassReverse /mywebapp http://localhost:3000
Edit - further details:
I'm running a jetty server with java -jar myapp.jar. I'd like to forward requests to an apache server listening on :80 to the jetty server.
I've got mod_proxy_http.so and mod_proxy.so enabled.
I can tell the server is running on localhost - it responds to curl with the appropriate http response. So I'm pretty sure the issue is with my apache setup, but I can't think what the problem would be.
Apache conf file in conf.d for reference: http://pastebin.com/vhXwjbQe
And I've got this in my httpd.conf:
Include conf.d/*.conf
It's hard to give a generic answer because every situation is different so here are some debugging questions to ask yourself:
if the protocol and port correct on the internal service, http and 3000.
Is the service actually listening for connections from localhost? is it running in a docker container etc that would require it to be listening on a different interface? You can check for this by looking at the output from mywebapp's logs and see if the request are making it through the proxy.
Do the paths on the internal service include the prefix that is being passed to Apache or does apache need to strip these off. if for instance mywebapp expects the path "/foo/bar" and apache's reverse proxy is sending it with the context path included "/mywebapp/foo/bar" then it will not match any path in mywebapp.

Long URLs in combination with Apache httpd and Tomcat

I'm currently in the process of configuring Apache httpd to direct all traffic for '/api/foo' to a specific Tomcat instance via AJP (using mod_proxy_ajp). For this purpose I have the following ProxyPass rule in my httpd configuration file:
ProxyPass /api/foo ajp://localhost:9999/api/foo connectiontimeout=300 timeout=300 retry=3
This Tomcat instance has the following connector defined in its server.xml:
<Connector port="9999" protocol="AJP/1.3" redirectPort="9443"/>
With this configuration I reach my Tomcat instance correctly when visiting /api/foo. However, when the URL becomes bigger than 300 characters I can't seem to reach my Tomcat instance, sometimes.
The first hour it could be that I get a timeouts and the other hour it could be that everything comes through just fine.
When I get timeouts, I see the following errors in my httpd error log:
[error] (70007)The timeout specified has expired: ajp_ilink_receive() can't receive header
[error] ajp_read_header: ajp_ilink_receive failed
[error] (70007)The timeout specified has expired: proxy: read response failed from 127.0.0.1:9999 (localhost)
And the following result in my httpd access log:
"GET /api/foo/barrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr HTTP/1.1" 503 323 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:33.0) Gecko/20100101 Firefox/33.0"
The strange thing is that this request doesn't seem to reach my Tomcat instance. I don't see anything reaching my application logging, and I also don't see the request in my Tomcat access log.
Does anyone have an idea what could be the cause of this problem? The timeout is set to more than 1 minute, so I'd expect the request to at least reach my Tomcat instance...
As a last note, I've tried setting the AJP connector's packageSize to 65536 and Apache httpd's LimitRequestFieldSize and ProxyIOBufferSize to 65536. This didn't solve the problem.
In the absence of a better answer I though I would share my experience with a similar and possibly the same problem and give you a recommendation to change the connector you are using.
I have also received the same ajp_read_header: ajp_ilink_receive failed errors while using mod_proxy_ajp in slightly different environments using apache 2.2 & tomcat 6.
I've tried many various and recommended fixes including the connector timeout and other connector settings when we encountered our issue.
From what I've read, some of these will work in different scenarios and the error ajp_ilink_receive failed message seems to be quite generic. In your case this occurs when the URL is longer than 300 characters - well sometimes at least..
After trying many of the different connector properties both from within the tomcat server.xml and the apache ProxyPass settings appended after the ajp:// URI I pretty much gave up going down this path. Since then I have tried mod_proxy and mod_jk which both seem fix the issue or at the very least there is no more ajp error. But this wouldn't happen with mod_proxy anyway because it doesnt connect with ajp.
So I suggest to change your tomcat connector to either mod_proxy or mod_jk. There are various write ups on the differences but the pages here and here on tomcat expect are a reasonably good source of information. You;ll want to choose between mod_proxy and mod_jk based on your setup. mod_jk, while different, is actually not too hard to set up (but you may have to build the mod_jk.so for apache).
Summarising the different connectors;
mod_jk: highest recommendation. ajp connector. purpose designed. different configuration setup that resides outside apache. difficult to configure when connecting a webapp with a certian name to a different url name.
mod_proxy: http connector. reportedly more stable than mod_proxy_ajp. problems with passing ssl variables?
mod_proxy_ajp: least recommended but most common. ajp connector. extension of mod_proxy. easy implementation.
If this doesn't work for some reason. Others have had success looking into problems on the tomcat side such as long running queries.