Paul Klinkenberg wrote:
Hi André,
Paul Klinkenberg wrote:
Hi Christopher,
Thanks for taking the time to respond; again much appreciated.
Your point, and André's, is understood. Security should not be done based on
incoming IP address.
With this current project, we off course want to deliver software which is
secure by default. Now, if someone would install Tomcat, then add the mod_cfml
valve, and then doesn't lock port 8080 or 8009, the server would become
vulnerable in the same way as if the /host-manager would not have
password-protection.
Currently, I am discussing with the main mod_cfml developers Jordan Michaels and Bilal Soylu how to
implement security, since I now won't be implementing IP restriction. We'll probably go with using
the "secret" configuration parameter for ajp like you suggested. Or maybe using a shared
"secret" key between the frontend server and the Tomcat valve. In this last case, we
would also have tackled security when remote attackers try to contact Tomcat on http-8080 directly,
instead of using the ajp connector.
I never knew the remote_addr could not be trusted, but I believe you at once
when you say so.
I thought it was taken from the actual socket connection. With the exception of
ajp by the way, where it is programmatically changed to reflect the remote
client while handling the http call. Out of curiosity, could you shed some
light as to why the remote_addr is not to be trusted in a regular http request?
Thanks again for your time and effort!
Kind regards,
Paul Klinkenberg
On Tomcat, you can set the AJP Connector to only listen on the local IP address of the Tomcat
server host. That means that only "local LAN" clients (including the httpd
front-end, presumably) can connect to that <Connector>.
So this already stops any external client (be it workstation or server) from
even connecting to Tomcat using AJP.
It also, presumably, insures that only your internal httpd front-ends can
potentially connect to Tomcat via AJP.
Now if you do not even trust your internal servers/clients, /then/ you need additional
measures. But in such a case, whether you use a "secret" which the front-end
must provide, or whether you use an additional header or Jk variable, is only a choice;
but any of those requires some setup on the front-ends.
The same is for the other Connectors, like HTTP/HTTPS. If you do not want
people to connect through these, disable them or have them also only listen on
a local IP address.
Thanks for these tips. I see there are quite a few options to secure the AJP
connector, which is great.
For the project I am currently working on, I have to take into consideration that the
user might already have Tomcat installed, and then probably with the default
configuration. That would mean the AJP connector is available, and http connector as
well. When someone now wants to add the mod_cfml valve to their setup, I will warn them
in the install/config notes to lock down their tomcat server, if they haven't done so
already. Next to this, I would like to be able to make the valve "secure by
default", without having to rely on external settings.
For this "secure by default", a required shared secret key seems like a
solution to me.
Note : to check. I am not sure if the HTTP/HTTPS Connectors provide this "shared secret"
thing. This may well be an AJP Connector feature only.
Remote users accessing either the http connector or ajp connector (only possible if the
server is not firewalled), would need to have that key in order to get the valve to create
a new context.
I _do_ trust the internal servers/clients, I just want to make sure that if a mod_cfml user was too lame to secure it's server, then mod_cfml isn't the weakest link to be able to hack the server.
I hope that makes sense?
Ok, so at this point, you only want to know, by intellectual curiosity, *how you could*
theoretically, in your Valve, obtain the IP address and port of the front-end proxy server
who is forwarding the original client request to your Tomcat.
Oof, that was hard to write, and I hope it is correct.
Actually, Christopher already provided the answer to that, in a previous post :
>>> The only way to check the caller would be to get ahold of the Socket
>>> that Tomcat is using to communicate. That's not easily done, since
>>> Tomcat wants to protect its sockets from code messing-around with the
>>> state of those Sockets."
That's a clue, but not a very helpful one for you, is it ?
I believe that the main issue here is that there is no such standard functionality
dictated by the Servlet Specification, so there is no obligation for any Servlet Engine to
provide this, and apparently thus Tomcat does not provide a way to obtain this information
easily, because it doesn't have to.
And according to Christopher, there may even be a deliberate attempt from the Tomcat code
to prevent one being able to do such things easily, because it could potentially mess up
things pretty badly if one went about playing with the underlying socket objects which
Tomcat's Connectors use behind the scenes. (And it would in any case not be portable to
another Servlet Engine; but you already have that issue with your Valve anyway, so you
probably don't care.)
Another way of saying the above, is that Tomcat works very hard at "abstracting" all this
underlying connection stuff, because it isn't really any of a Valve's or a Webapp's
business to know any of this stuff and potentially create code which is not portable
between specification-observing Servlet Engines.
But then, after having said all that, and consulted the useful on-line documentation for
HttpServletRequest -> ServletRequest
(at https://tomcat.apache.org/tomcat-8.0-doc/servletapi/index.html)
I see :
getRemoteAddr()
Returns the Internet Protocol (IP) address of the client or last proxy that
sent the request.
So it would seem that, in the case where the request was proxied (such as via
httpd+mod_jk), getRemoteAddr() should return the IP address of the proxy. Isn't that what
you wanted in the first place ?
And as far as I can see from other documentation (such as
http://tomcat.apache.org/connectors-doc/generic_howto/proxy.html), it is if you want this
call to return the actual original client's IP (the one which connects to the front-end
httpd), that you have to do something special at the httpd proxy level.
So now I am a bit confused, because as I recall (maybe wrongly), you wanted the IP of the
httpd+mod_jk front-end, didn't you ?
And in the opposite case, there is anyway this immanent truth : if you consider a schema
like this :
browser <-- HTTP --> httpd front-end <-- AJP --> Tomcat
(1) (2)
Connection (1) is basically a matter only between the client and the front-end, and Tomcat
has nothing to do with it. Tomcat only knows about connection (2), because for that one,
it is one of the connected parties.
Tomcat (and whatever code in it) would basically never know *anything* about the
connection (1) above, unless the httpd front-end decides to pass information about it to
Tomcat, over connection (2). And the only way to have this happen, is to configure the
front-end specifically to do so.
Another way to say this : no matter how deep you would dig into the objects and methods
available in Tomcat to your Valve, there is no way you could ever find any information
about connection (1), because there isn't any, other than what you can get from the HTTP
headers or the Jk variables which the front-end adds to the HTTP request that it forwards
to Tomcat.
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org