You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Paul Klinkenberg <pa...@ongevraagdadvies.nl> on 2015/04/29 15:54:17 UTC

Finding the Apache httpd IP address when AJP is used

Hi Tomcat users!

I have been working on an update for a Tomcat valve called mod_cfml. The project aims to provide automatic web context creation in Tomcat, when coming from a frontend webserver.
The live code base can be found at https://github.com/utdream/mod_cfml <https://github.com/utdream/mod_cfml>

One of the features I wanted to add, is adding an IP restriction in the valve (see github <https://github.com/paulklinkenberg/mod_cfml/commit/dab058b7f38f98a6e7f076323e3d23be476e6de6>). 
While testing, I noticed that AJP works very well: it hides the IP address of the caller, which is the front-end Apache webserver, and instead returns the IP of the remote client / the client who called the frontend webserver.
I have been digging around quite a lot, but have not been able to find the Apache httpd IP address :-(

My question is hopefully simple to answer: can I retrieve the IP address which called the AJP connector, from within the valve?

My server.xml is:

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
            <Valve
                className="mod_cfml.core"
                loggingEnabled="true"
                waitForContext="10"
                maxContexts="9999"
                timeBetweenContexts="0"
                scanClassPaths="false"
                allowedIPs="127.0.0.1,192.168.1.52" />
      </Host>
    </Engine>
  </Service>
</Server>

Thanks in advance for your time!

Kind regards,

Paul Klinkenberg
The Netherlands

p.s. I asked this question, in other wording, on SackOverflow.com <http://sackoverflow.com/> as well. I hope I have better luck here ;-)
http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Paul,

On 4/30/15 11:27 AM, Paul Klinkenberg wrote:
> Hi Christopher,
> 
>> Paul,
>> 
>> On 4/29/15 10:18 PM, lwyd@bsoft.com.cn wrote:
>>> p.s. I asked this question, in other wording, on
>>> SackOverflow.com <http://sackoverflow.com/> as well. I hope I
>>> have better luck here ;-) 
>>> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apa
ch
>>
>>> 
e-httpd-server-ip-from-within-a-tomcat-valve-when-ajp
>>> <http://stackoverflow.com/questions/29858030/where-can-i-find-the-ap
ac
>>
>>> 
he-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>
>> 
>> It's more clear from this post that you just want to make sure
>> that the HTTP (or AJP) request is coming from localhost.
>> 
>> If that's all you want, then change the <Connector> configuration
>> so that it's only listening on localhost, like this:
>> 
>> <Connector address="127.0.0.1" ... />
>> 
>> This will prevent any incoming connections from the outside
>> world.
>> 
>> Does that solve your problem?
>> 
>> - -chris
> 
> On stackOverflow, I indeed said I (just) wanted to check for
> 127.0.0.1/localhost. That was a simplification of the case, to keep
> the focus on getting the AJP request's source IP address. In real
> life, there will also be setups where the source IP will be
> different. Sorry for any confusion this may have caused.
> 
> All in all, the SO question isn't really important anymore, since I
> now know that IP restriction wouldn't be the best way to accomplish
> the security I am looking for. Personally, I'd still like to know
> the answer, but that's only because I have spent multiple hours
> trying to find that IP address from inside the valve ;)

The only way to do this "properly" would be to set up an HTTPS channel
between your trust web servers and your application servers, and
require that the trusted web servers use SSL client certificates to
successfully connect to your application servers.

The client (web server) is configured to provide the client
certificate, and the server (app server) is configured to require a
recognized certificate. As long as your web servers are not
compromised, then only your web servers will provide trusted credentials
.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQlacAAoJEBzwKT+lPKRY5zcQAIEsv79WdddFzAZ9X3hxQSWB
Jir0b9hETpNIJ3SrZB3ofiz7MVjsquk0TrWewd3xTSWY7ELguhJLDlRxnDzE6Xsz
S5G1q/ViugIlbb/0fpZKt3B9LrJ1qUnxyej6+5tOpqoUco1fLZpMpSW/53xGq4my
xu3W+M++7eVRCZCVjAhEJqAIATjaCmoKc8iTRVCKq5eyubbRTND/JFHqNzACcZrd
jFiaYVnrOObw/Q1a8Fp/7kYFNFc7a49qcv3yUwTbpmyC3XR2vJmOrikH1bKXo/KB
EeQz3MefClE7nP+3dsoCF9n6Y0OR4cASEdAETTRScnAFGfZknPL5Wa6JfGx06RM1
pz9w3mMn3y5oGNuISOmR8td0zsEFpEEemdf00Rv/fL4/dGepKHoQVSMvvcAVePcK
sGFJPZGEQdeBe4h89jqvlZniRDVXvOQb0lJykDivnhqY9wgiG4TK28Y+LSrpxZhx
Emh3FifqYWpVlrGQ0ii0vbHtR7Y6/kQiC+9Q2jqAlJWADz9TQ8A91CxLa+UH7K/F
K0v7iS4yf+aQQvjo61wYHs34PeCvJDZ8DBHeCpmRPQmwkrm9aKW3emqubKrMgt0F
8NRq2gEulYUiI7ojM8gbrLzxKLI1nwCfh6ri0XLcOLiPgGOjvEKv9l3NbfD3A3GT
vYR/xSqoOBdaKe2d2mwc
=KMPh
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Paul Klinkenberg <pa...@ongevraagdadvies.nl>.
Hi Christopher,

> Paul,
> 
> On 4/29/15 10:18 PM, lwyd@bsoft.com.cn wrote:
>> p.s. I asked this question, in other wording, on SackOverflow.com
>> <http://sackoverflow.com/> as well. I hope I have better luck here
>> ;-) 
>> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apach
> e-httpd-server-ip-from-within-a-tomcat-valve-when-ajp
>> <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apac
> he-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>
> 
> It's more clear from this post that you just want to make sure that
> the HTTP (or AJP) request is coming from localhost.
> 
> If that's all you want, then change the <Connector> configuration so
> that it's only listening on localhost, like this:
> 
> <Connector address="127.0.0.1"
>     ...
>     />
> 
> This will prevent any incoming connections from the outside world.
> 
> Does that solve your problem?
> 
> - -chris

On stackOverflow, I indeed said I (just) wanted to check for 127.0.0.1/localhost. That was a simplification of the case, to keep the focus on getting the AJP request's source IP address.
In real life, there will also be setups where the source IP will be different. 
Sorry for any confusion this may have caused.

All in all, the SO question isn't really important anymore, since I now know that IP restriction wouldn't be the best way to accomplish the security I am looking for.
Personally, I'd still like to know the answer, but that's only because I have spent multiple hours trying to find that IP address from inside the valve ;)

Kind regards,

Paul Klinkenberg


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Paul,

On 4/29/15 10:18 PM, lwyd@bsoft.com.cn wrote:
> p.s. I asked this question, in other wording, on SackOverflow.com
> <http://sackoverflow.com/> as well. I hope I have better luck here
> ;-) 
> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apach
e-httpd-server-ip-from-within-a-tomcat-valve-when-ajp
> <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apac
he-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>

It's
> 
more clear from this post that you just want to make sure that
the HTTP (or AJP) request is coming from localhost.

If that's all you want, then change the <Connector> configuration so
that it's only listening on localhost, like this:

<Connector address="127.0.0.1"
     ...
     />

This will prevent any incoming connections from the outside world.

Does that solve your problem?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQjiaAAoJEBzwKT+lPKRYyD0QAIS4KmX2osUNxLAd/taX9NP6
cHNaJnMgekgVNpvh5QpuGRO2e1ivMmheyBSo3lFtnK8kF++VIBZBpDqAZO/PUX1H
ubSo62ip6QCSSoonVKeWzrSFvDCN8xAb9R4FNRu+GbIV+ubiGfghYct+J0R1HXq0
1Ncm4SOpXjsYoOZDGK/AwMfoJDoN0QemvSuKp7ftASD0SCV4EOhZya6JCxLKMQte
dCtv+rfd0Q/qjVizDGdmCT3qqLHUMQ5eLy6dhveHny9vU5KT8ORfOrTZ6REmxnHe
pkhWFIv6hUPeSZw+kW4SlVQhBweet2bDfnso8zDkp65un9YRbUW+edSMTi8VD1aG
Z/AwjTXWjQF83+g6SY7asV6bcpGOFbYeRIVWB8NI14Z1rLLlicDPjJaD9EHYCM0q
jaoPNXprcQGrjFhcSCHBXjMdp6trK9es83+E8PeFJF9i5UTnWii2+k4GL05/MSxx
pysLFMiV4V14BOwR8yq7iWcMMzNxf7d6bCyYna4oHhsGfiqlJEKgg3AFyTPc+Ebb
+HOEqm+MkPFtM0TIsXhQBDvPu13SR0yTB894J/ns1PHLE7XlmBtgZ7+lPuRFINbQ
0eEWPKPoQGttkaibLRT7u3alLRPBUG4gqWUl0Ux16aOBdyJpTLoJsMm+cLYNgj0t
cuPcHfwY7LAVKjaQTKrU
=AsyJ
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by "lwyd@bsoft.com.cn" <lw...@bsoft.com.cn>.
Hi,Nice to meet you.



lwyd@bsoft.com.cn
 
From: Paul Klinkenberg
Date: 2015-04-29 21:54
To: users@tomcat.apache.org
Subject: Finding the Apache httpd IP address when AJP is used
Hi Tomcat users!
 
I have been working on an update for a Tomcat valve called mod_cfml. The project aims to provide automatic web context creation in Tomcat, when coming from a frontend webserver.
The live code base can be found at https://github.com/utdream/mod_cfml <https://github.com/utdream/mod_cfml>
 
One of the features I wanted to add, is adding an IP restriction in the valve (see github <https://github.com/paulklinkenberg/mod_cfml/commit/dab058b7f38f98a6e7f076323e3d23be476e6de6>). 
While testing, I noticed that AJP works very well: it hides the IP address of the caller, which is the front-end Apache webserver, and instead returns the IP of the remote client / the client who called the frontend webserver.
I have been digging around quite a lot, but have not been able to find the Apache httpd IP address :-(
 
My question is hopefully simple to answer: can I retrieve the IP address which called the AJP connector, from within the valve?
 
My server.xml is:
 
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
            <Valve
                className="mod_cfml.core"
                loggingEnabled="true"
                waitForContext="10"
                maxContexts="9999"
                timeBetweenContexts="0"
                scanClassPaths="false"
                allowedIPs="127.0.0.1,192.168.1.52" />
      </Host>
    </Engine>
  </Service>
</Server>
 
Thanks in advance for your time!
 
Kind regards,
 
Paul Klinkenberg
The Netherlands
 
p.s. I asked this question, in other wording, on SackOverflow.com <http://sackoverflow.com/> as well. I hope I have better luck here ;-)
http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>
 

Re: Finding the Apache httpd IP address when AJP is used

Posted by André Warnier <aw...@ice-sa.com>.
As a P.S. :
Maybe you should also look at this, to see if it would fit your needs :
http://tomcat.apache.org/tomcat-8.0-doc/proxy-howto.html


André Warnier wrote:
> Paul Klinkenberg wrote:
>> Hi Tomcat users!
>>
>> I have been working on an update for a Tomcat valve called mod_cfml. 
>> The project aims to provide automatic web context creation in Tomcat, 
>> when coming from a frontend webserver.
>> The live code base can be found at https://github.com/utdream/mod_cfml 
>> <https://github.com/utdream/mod_cfml>
>>
>> One of the features I wanted to add, is adding an IP restriction in 
>> the valve (see github 
>> <https://github.com/paulklinkenberg/mod_cfml/commit/dab058b7f38f98a6e7f076323e3d23be476e6de6>). 
>> While testing, I noticed that AJP works very well: it hides the IP 
>> address of the caller, which is the front-end Apache webserver, and 
>> instead returns the IP of the remote client / the client who called 
>> the frontend webserver.
>> I have been digging around quite a lot, but have not been able to find 
>> the Apache httpd IP address :-(
>>
>> My question is hopefully simple to answer: can I retrieve the IP 
>> address which called the AJP connector, from within the valve?
>>
>> My server.xml is:
>>
>> <Server port="8005" shutdown="SHUTDOWN">
>>   <Listener 
>> className="org.apache.catalina.startup.VersionLoggerListener" />
>>   <Listener className="org.apache.catalina.core.AprLifecycleListener" 
>> SSLEngine="on" />
>>   <Listener 
>> className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
>>   <Listener 
>> className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" 
>> />
>>   <Listener 
>> className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
>>   <GlobalNamingResources>
>>     <Resource name="UserDatabase" auth="Container"
>>               type="org.apache.catalina.UserDatabase"
>>               description="User database that can be updated and saved"
>>               
>> factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
>>               pathname="conf/tomcat-users.xml" />
>>   </GlobalNamingResources>
>>   <Service name="Catalina">
>>     <Connector port="8080" protocol="HTTP/1.1"
>>                connectionTimeout="20000"
>>                redirectPort="8443" />
>>     <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
>>     <Engine name="Catalina" defaultHost="localhost">
>>       <Realm className="org.apache.catalina.realm.LockOutRealm">
>>         <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
>>                resourceName="UserDatabase"/>
>>       </Realm>
>>       <Host name="localhost" appBase="webapps" unpackWARs="true" 
>> autoDeploy="true">
>>             <Valve
>>                 className="mod_cfml.core"
>>                 loggingEnabled="true"
>>                 waitForContext="10"
>>                 maxContexts="9999"
>>                 timeBetweenContexts="0"
>>                 scanClassPaths="false"
>>                 allowedIPs="127.0.0.1,192.168.1.52" />
>>       </Host>
>>     </Engine>
>>   </Service>
>> </Server>
>>
>> Thanks in advance for your time!
>>
>> Kind regards,
>>
>> Paul Klinkenberg
>> The Netherlands
>>
>> p.s. I asked this question, in other wording, on SackOverflow.com 
>> <http://sackoverflow.com/> as well. I hope I have better luck here ;-)
>> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp 
>> <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp> 
>>
>>
>>
> Hi.
> With Apache httpd and mod_jk as front-end, you have (at least) 2 options :
> - set an additional HTTP request header at the Apache httpd level, 
> before the request is proxied to the back-end Tomcat
> - set a "JkEnvVar" value at the at the Apache httpd level, before the 
> request is proxied to Tomcat
> You can then retrieve these set values at the Tomcat level, either by 
> parsing the request headers, or by retrieving a "request attribute" 
> corresponding to the JkEnvVar.
> The JkEnvVar/attribute method is probably more efficient in a mod_jk 
> context; the HTTP header solution is more portable, since it does not 
> depend on specifically mod_jk being used as a connector.
> 
> Presumably, when at the Apache httpd level you decide to proxy a request 
> to a back-end Tomcat, you know through which interface you'll do it, and 
> what its IP address is, and you can put it into one of the things above.
> 
> Is that enough info to get you started ?
> 
> Caveat : one part I am not quite sure of, is what things you do have 
> easy access to, at the level of a Valve.  The above is what you'd do at 
> a webapp level, I hope it is also accessible at your Valve level.
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Re: Finding the Apache httpd IP address when AJP is used

Posted by "lwyd@bsoft.com.cn" <lw...@bsoft.com.cn>.
> Paul Klinkenberg wrote:
>> Hi Tomcat users!
>> I have been working on an update for a Tomcat valve called mod_cfml. The project aims to provide automatic web context creation in Tomcat, when coming from a frontend webserver.
>> The live code base can be found at https://github.com/utdream/mod_cfml <https://github.com/utdream/mod_cfml>
>> One of the features I wanted to add, is adding an IP restriction in the valve (see github <https://github.com/paulklinkenberg/mod_cfml/commit/dab058b7f38f98a6e7f076323e3d23be476e6de6>). While testing, I noticed that AJP works very well: it hides the IP address of the caller, which is the front-end Apache webserver, and instead returns the IP of the remote client / the client who called the frontend webserver.
>> I have been digging around quite a lot, but have not been able to find the Apache httpd IP address :-(
>> My question is hopefully simple to answer: can I retrieve the IP address which called the AJP connector, from within the valve?
>> My server.xml is:
>> <Server port="8005" shutdown="SHUTDOWN">
>>  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
>>  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
>>  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
>>  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
>>  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
>>  <GlobalNamingResources>
>>    <Resource name="UserDatabase" auth="Container"
>>              type="org.apache.catalina.UserDatabase"
>>              description="User database that can be updated and saved"
>>              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
>>              pathname="conf/tomcat-users.xml" />
>>  </GlobalNamingResources>
>>  <Service name="Catalina">
>>    <Connector port="8080" protocol="HTTP/1.1"
>>               connectionTimeout="20000"
>>               redirectPort="8443" />
>>    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
>>    <Engine name="Catalina" defaultHost="localhost">
>>      <Realm className="org.apache.catalina.realm.LockOutRealm">
>>        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
>>               resourceName="UserDatabase"/>
>>      </Realm>
>>      <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
>>            <Valve
>>                className="mod_cfml.core"
>>                loggingEnabled="true"
>>                waitForContext="10"
>>                maxContexts="9999"
>>                timeBetweenContexts="0"
>>                scanClassPaths="false"
>>                allowedIPs="127.0.0.1,192.168.1.52" />
>>      </Host>
>>    </Engine>
>>  </Service>
>> </Server>
>> Thanks in advance for your time!
>> Kind regards,
>> Paul Klinkenberg
>> The Netherlands
>> p.s. I asked this question, in other wording, on SackOverflow.com <http://sackoverflow.com/> as well. I hope I have better luck here ;-)
>> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>
> Hi.
> With Apache httpd and mod_jk as front-end, you have (at least) 2 options :
> - set an additional HTTP request header at the Apache httpd level, before the request is proxied to the back-end Tomcat
> - set a "JkEnvVar" value at the at the Apache httpd level, before the request is proxied to Tomcat
> You can then retrieve these set values at the Tomcat level, either by parsing the request headers, or by retrieving a "request attribute" corresponding to the JkEnvVar.
> The JkEnvVar/attribute method is probably more efficient in a mod_jk context; the HTTP header solution is more portable, since it does not depend on specifically mod_jk being used as a connector.
> 
> Presumably, when at the Apache httpd level you decide to proxy a request to a back-end Tomcat, you know through which interface you'll do it, and what its IP address is, and you can put it into one of the things above.
> 
> Is that enough info to get you started ?
> 
> Caveat : one part I am not quite sure of, is what things you do have easy access to, at the level of a Valve.  The above is what you'd do at a webapp level, I hope it is also accessible at your Valve level.
> 

Hi André,

Thanks for the response, much appreciated.
The reason I want to add the IP restriction in the valve, is to make 100% sure that the request (for creating a new Tomcat context) is indeed coming from the frontend webserver. This valve is a setup not just for me, where I could tweak server settings and such, but for anyone who uses the mod_cfml connector. It is installed by default by the Railo/Lucee installers (getrailo.org <http://getrailo.org/> / lucee.org <http://lucee.org/>)

Therefor, I cannot rely on an incoming header, as it could originate from anywhere.
Also, a remote system could call the AJP endpoint on the Tomcat server, with this JkEnvVar set to a spoofed value. (if the port is not firewalled off course)
So the problem with both options is, that they cannot be fully trusted.

If I am able to find out where the AJP request came from, then I can validate the caller.

Maybe you know which path to follow to get to the AJP request data?

Thanks,

Paul Klinkenberg

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org



Re: [OT] Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

André,

On 4/30/15 2:39 PM, André Warnier wrote:
> Christopher Schultz wrote:
>> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
>> 
>> Paul,
>> 
>> On 4/30/15 3:24 AM, Paul Klinkenberg wrote:
>>> 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?
>> 
>> The client can spoof the source IP in the packet headers.
>> 
> 
> This is not on-topic, but since the point has been raised, and
> since there are many smart people on this list..
> 
> I am probably not very clever in a hacking kind of way, but I have
> never been able to figure out how a client could make use of this
> to actually achieve something with TCP. Setting up a TCP connection
> requires a couple of packet exchanges *back and forth*. So, the
> client can indeed send a first SYN packet to a server, with a 
> spoofed origin IP address. But then the server would return the
> ACK packet to that spoofed IP address, which is presumably not the
> real client's one, wouldn't it ? What good would that be to the
> malevolent client ? Unless the point is only to flood a server's
> TCP stack with connection requests which never can get completed.. 
> If anyone has a clue as to how this can be really exploited, I'm
> eager to learn.

http://en.wikipedia.org/wiki/IP_address_spoofing

The "Background" section mentions your point.

Doing this with SSL is not really possible, unless the attacker
controls a part of the network through which all packets flow, and can
intercept packets regardless of their destination. If the attacker is
on your network, of course, it's already over.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQ5dhAAoJEBzwKT+lPKRYnRcQAJyJU/bX48esbAbOqZqcIY4C
QY2P7HqemcPjamBEIO1a4wH9o7C1TFy/+ZxY2pZrpP+67NWH7KgtzMFKcWvDkNrd
t5XqmNhuWhz2TesUk77wBrU5+ss5CxU5+Z+t9MSi3qPg61+szfMSHci1fW7rkm7A
JtfoQtkMFZavUDrfEia1sS11RQLWMVqHZecRL2S3VPdWmgJJgJHuusr06bAIcdno
WiN7+hquDS4YVbAinKlv6RzQVDbPTAWDKLvmRslz9QJTgxGDe64kk9P2r9y8MXzY
w8xwKUsMo+0qXPDlbHt+U2ejCnzU8bpl0/zAOKqQIOCht8PIlFZ8hhmXDeJP8GPg
mViGx3qW7f6du1K5WBLjcHWcrP3yJNaBPBNXT2sW7DD4bHNQABwkRcTHlA87DsY/
fqEW2X/oQJz/ThxTjhf1wsELyg1Sh4iWHXaQRpfSzEKjFS7yPJW/0Ef4i85voyGq
WiAmxcosxW2pr0t7I7wh6zx4XhK0vji5GyU/ZP0huwOVuVS6C+H0TWmitzswiQKs
joa7C9txTDvX1hPzvym9JCg/XQNaoEVmIMJ6Bui+tWAGcjnbSImRUAQI+W7+XBb4
6eKJlCTWinF9BG02/rStlD/imZUGAYETs/yg59xdV/VeNPhgU5ag1iJOV2m5+nnR
Z8qnngujiabvHF2W/yQI
=ze9i
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Finding the Apache httpd IP address when AJP is used

Posted by André Warnier <aw...@ice-sa.com>.
Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
> 
> Paul,
> 
> On 4/30/15 3:24 AM, Paul Klinkenberg wrote:
>> 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?
> 
> The client can spoof the source IP in the packet headers.
> 

This is not on-topic, but since the point has been raised, and since there are many smart 
people on this list..

I am probably not very clever in a hacking kind of way, but I have never been able to 
figure out how a client could make use of this to actually achieve something with TCP.
Setting up a TCP connection requires a couple of packet exchanges *back and forth*.
So, the client can indeed send a first SYN packet to a server, with a spoofed origin IP 
address. But then the server would return the ACK packet to that spoofed IP address, which 
is presumably not the real client's one, wouldn't it ?
What good would that be to the malevolent client ?
Unless the point is only to flood a server's TCP stack with connection requests which 
never can get completed..
If anyone has a clue as to how this can be really exploited, I'm eager to learn.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Paul,

On 4/30/15 3:24 AM, Paul Klinkenberg wrote:
> 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?

The client can spoof the source IP in the packet headers.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQjcQAAoJEBzwKT+lPKRY4HEP/30Lih3AbOBVh1fujyoB0fZd
tne7zc3bJnrhtwl3f5Je1YlLR+ij545HYlcRTeM6UFlh2k8N7rFTJIPdLlnbt4jC
62FPkmBYZQqtccgv/AP/E+jI75kstAW47LvL4UEOS0p/UwgW2phEN7Ko0SKvaHDk
YWj5/LrtCBfsZFLJeGqgcbU2c38BFdBZGS1zWgGgCuz53kH8y1LPKj7zgs0LuDOn
IHEFWVcXbUbHqcAS6Cfb6UV4kI1JiSTmtoufaqpcBOQtRG4lVMcrsK3660W8FMXC
DercNpofhYIX+E5B19FI1QlYl1dTd4Wz17QTMqsiK1T9qNG5JczYIHi3VX6KGwT9
oj5LO7K0v6E653gQBo+pcIJO6H44xOdg1J/U8rNuyTkfU2Vr+fMOA321kEchRYRj
Zb8J7DTtNuHAW5ncwH4YTqvEnbg2p9ZoF9tCB9330u3wdWsVCj/62WX6XT908ElD
hs2Z73qhdbm7REu8KPtk9WQkylNhptA6Uxe8ZPBD7jfxGPAR7KvpwwXPV2irhG/e
7Iq8SbmMK9zpI4W6oodjiv+olQmj8qo5tuSrpTbW264GSrioKVZ9jkclxfkzrtuf
utdotevKsCAOXQYzhtHcU6NkxUgvZZ76YOBmKBineEmb1ieXQzeQ0PgJdOHXVqpe
AYfiVawe60dkGrsKdr5R
=9bH5
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

André,

On 4/30/15 5:13 AM, André Warnier wrote:
> 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.

Not quite. You can bind to localhost, which only allows local
connections. Or you can bind to * (all interfaces), which allows
connections from anywhere. Or, you can bind to a specific interface
(IP address), which also allows connections from anywhere. There is no
interface to which you can bind that means "only the local network",
unless if course there is some other factor at work; such as an
interface that is only connected to a local network.

> 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.

+1

> 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.

+1

The best way to protect against unauthorized access is to require
authentication in some way that doesn't rely on some shaky and sloppy
checking, like IP address.

At some point, you have to trust your own web servers. If you don't
trust your own web servers, it means you are expecting MitM attacks.
Why not lock-down the connections between your web servers and your
application servers and then not have to distrust incoming connections
just in case they aren't coming from your web servers?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQjgBAAoJEBzwKT+lPKRYKEIP/1fAJwB2F99YVcgDbLPo9zky
aDRkX0Rvv73vVxJdWoOJsM1FsgGXBaPg83ZC383Ma9iKpI0E4+iLbSc3WNembMIr
PgV+6yG7BYV0p2v51OXOfzFNp3fDml6gc9RLEiQ+r8k5Dj7MscCHnKZzwaghxRyf
HBlSPy5k+TMrQsPEAIzx6mrM2r8VNVZjrisLXkatoviDGQG/9ji5q4OG6XVUv5pe
fSkWTpH04MZsEG/bRIqak1as0jQnjHckw+XH2aamApWRsIuH2HTV685BqSVOp3ZV
Cg1v0KXavJOjspWVPZpngDmTRaB4kvDt8pC2bbMUDxocZgw+SG/AwVY6IAvBpuPR
4oVB/vBGrY546lvjXxOvcr6RdNfs/+1pK6OFbaKcI5m4UxHVP1k8cRLCjRlcIKKX
MRWYraCwfx9CWd6t97Ax1FXge0fMgXPWobcgaGTRT7IKm0pSDAXbOvzwPPUxWFOP
aQ+nOIAp7He7kKsUEU/0DooV2Vzf+FVTNwW8z1rJMdPWd716OWS8ASUJi7yLVnOI
rH/O6TQ9gAhfUaAGY0nRtpAtPCCI05eUxWe91G+IFKIAvZ4O30Mi1AouwNo08CjZ
EBjpm7h67m5lkHQb/sVjCrMKcg70OnKEvjYbivgubf12HBrP89v1nTU/NE1fffD8
TuNP/MKIFBs6MzyrMh9H
=EBju
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Paul,

On 5/1/15 11:54 AM, Christopher Schultz wrote:
> Paul,
> 
> On 4/30/15 5:21 PM, Paul Klinkenberg wrote:
>> You were totally on your way to come to the point where my
>> original question was aimed at, and then suddenly, bam, a right
>> turn ;-) That happened when you write "getRemoteAddr() Returns
>> the Internet Protocol (IP) address of the client or last proxy
>> that sent the request." Yes, that is normally the case, but not
>> when using AJP. The missing link in the story is the
>> "translation" that AJP does: 
>> -------------------------------------------------------- 1)
>> browser --- HTTP --->  httpd front-end 2) httpd front-end --- AJP
>> ---> Tomcat-AJP 3) Tomcat-AJP   --- HTTP --->  Tomcat-HTTP (and
>> back off course:  ----> AJP ----> httpd ----> browser ) 
>> -------------------------------------------------------- I doubt 
>> whether the AJP connector really sets up an http connection,
>> which the arrow "---HTTP--->"  implies at position 3). I do know
>> that both the servletrequest and the valve present inside the
>> http connector, think it is a genuine http request coming from
>> the browser-client, not an ajp one. For example, debug results
>> show: request.getProtocol() : HTTP/1.1 request.getRemoteAddr() :
>> [ip of the browser-client] request.getLocalPort() : 80   <<< not
>> 8080! request.getCoyoteRequest().getWorkerThreadName() : 
>> ajp-nio-8009-exec-1   <<< The _only_ reference I could find to 
>> anything non-http, but this is a string... And I needed to use 
>> reflection to get to the coyote request.
> 
>> What I wanted to know, indeed out of intellectual interest, is 
>> what you described perfectly (even though it was hard to write): 
>> the ip address of the httpd front-end server.
> 
>> I really don't want to exhaust your time on a hunt for something
>>  that is just nice to know, but won't be used afterwards. But I 
>> (again!) much appreciate the time you took to dive into this
>> quest I gotten myself into ;)
> 
> I'm trying to figure out why I can't get these request attributes
> to show in my env environment, but you should be able to get a
> handful of variables from the request attributes:
> 
> https://tomcat.apache.org/connectors-doc/generic_howto/proxy.html#Fine
%2
>
> 
0Tuning
> 
> I can't seem to get those httpd environment variables to show up in
> my request attributes. Maybe I'm using the wrong names.

It may be because my httpd is on the same host as my Tomcat server
that I'm getting confused.

Check the value that you get from request.getLocalAddr. It may already
be the IP address of the web server, and you could use that as your
check criteria.

Of course, if you allow AJP connections from anywhere, then you are
vulnerable to a rogue AJP proxy merely telling you the IP address you
want to see.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQ6mLAAoJEBzwKT+lPKRYQe4QALU/h3zvTGT5IVLcrjH5IG6W
aPKFghkDdOeN0SU0w/Eg99qgoOhMKe1VTQk/LUjVf6HytT4CDgg+ziH7IndD47Z5
eSjUZDHpLs58yBk9QNBliTW4c/1wflJqdk2V+85yFZsQ3sCkwxGdEraF96KX0XYD
WGL62SOQKH5rIG/gYMEcwzVBbqYjSzInRB1IWK0m4B7n2Pr/ndg4Cg2SiV1XMC84
Ephe3gN5PMNEQHD7Ch7Bf1s6Ml4xU5OsLMVlXpaYpXBZXjLGZrWb3IcdBdQpmuDI
jaFzgB+J/p8hTYgmdDyU2qb5o3KlvWLBIq87eLTk+vyr/JhKMBZBMgSFyi8S5V8V
0IcGQTtmr7j6RXtRf9eef33NVb3Iok+SHWEpY+3mqD/GT9UGAbk0YVXtQGJSca0X
DppP9qIquc9RzzJUUQM255BhEgIvdh2ZNBtM/ehZLp2vvEuCqiEgMIWIY6qDGW2h
wQCbFeraxFGoYj83yrLv8h3/OPxsz1dpyfv/C3dvKX5EodppqNGEDDWpHPpLdtZu
QhOwTKVISfBGZdgnKC6AmoUDm82ils6DPl5iU0j3eBo35faHPEV2RnCoeFGzqfW5
Yipae/f+uSAlllLl/tfEKgWNKmf9s4vsLWRfmSqDLDJkBYSlsApiDNcxGyE/66+Q
tTv3MkL5YNyVD18n6+EZ
=lSN1
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Paul,

On 4/30/15 5:21 PM, Paul Klinkenberg wrote:
> You were totally on your way to come to the point where my original
> question was aimed at, and then suddenly, bam, a right turn ;-) 
> That happened when you write "getRemoteAddr() Returns the Internet
> Protocol (IP) address of the client or last proxy that sent the
> request." Yes, that is normally the case, but not when using AJP. 
> The missing link in the story is the "translation" that AJP does: 
> -------------------------------------------------------- 1) browser
> --- HTTP --->  httpd front-end 2) httpd front-end --- AJP --->
> Tomcat-AJP 3) Tomcat-AJP   --- HTTP --->  Tomcat-HTTP (and back off
> course:  ----> AJP ----> httpd ----> browser ) 
> -------------------------------------------------------- I doubt
> whether the AJP connector really sets up an http connection, which
> the arrow "---HTTP--->"  implies at position 3). I do know that
> both the servletrequest and the valve present inside the http
> connector, think it is a genuine http request coming from the
> browser-client, not an ajp one. For example, debug results show: 
> request.getProtocol() : HTTP/1.1 request.getRemoteAddr() : [ip of
> the browser-client] request.getLocalPort() : 80   <<< not 8080! 
> request.getCoyoteRequest().getWorkerThreadName() :
> ajp-nio-8009-exec-1   <<< The _only_ reference I could find to
> anything non-http, but this is a string... And I needed to use
> reflection to get to the coyote request.
> 
> What I wanted to know, indeed out of intellectual interest, is
> what you described perfectly (even though it was hard to write):
> the ip address of the httpd front-end server.
> 
> I really don't want to exhaust your time on a hunt for something 
> that is just nice to know, but won't be used afterwards. But I
> (again!) much appreciate the time you took to dive into this quest
> I gotten myself into ;)

I'm trying to figure out why I can't get these request attributes to
show in my env environment, but you should be able to get a handful of
variables from the request attributes:

https://tomcat.apache.org/connectors-doc/generic_howto/proxy.html#Fine%2
0Tuning

I can't seem to get those httpd environment variables to show up in my
request attributes. Maybe I'm using the wrong names.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQ6GiAAoJEBzwKT+lPKRYhpoP/jNyCdZ3eMz+UcnM1vHkL1ZB
yc0Xc1VWo8qNCF7Nezy2VAAEjiPCgw5HmKoNXmj7RDO1XaHprcDAsHNxuyzjFMvD
fbQ9KpD+swlIfLtFVetlcU1+xUGnZyXiIb12dly9czF7hTA4bTrkyogIa4Q68CJQ
SwFS2Bhnqvi/QFYuascCySXpttMVrgMf4GOC5zyuIv4Pz2AuSA27fsa/J3hXofSI
fMJ2qrs6tBXAE9Co/wM2HdLLjbbAplyXsd/Gzxl/kAC++eFmg8PSvQGUig0qKXOh
jZWa+xRnRL0gOW+lJ/56jhlgD21y/X1L73f74C+Eavph+WtCyFJ8lbM/HEOumC/Z
ARtZJ5p0v/JzmKRLmClG9JJkMydgLzIjZKOB5i/lkbQJQe6ZAbouH7CihLP3yD2i
Gy1CnuVDCDWGVjReMV2zksLWFIxqHRu450wrn7ZWb514krRrUxpj+En6Y+u5EOxW
DTgATrLdMZyH0pfYBIYUw4aEmQ9O2YmE0OxwwffTMRdeKLewqGTmu25G0OQB89hS
4llNp1ZkNcHHTMnQNE7ewBFJkQjuC9brHqTJCz9AD7qqLC7p9BiuiDLhsBloIWAb
dekhwt8Jy4jrfmyK48JpWKqBXjsg8c6S+dqE8etEzSe4U1RUv11nNDChA/MyvyLF
2o5anqRN3ez7vlY8x3B/
=lzjD
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Paul Klinkenberg <pa...@ongevraagdadvies.nl>.
Hi André,
> Paul Klinkenberg wrote:
>> Hi André,
>>> 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.
>> You were totally on your way to come to the point where my original question was aimed at, and then suddenly, bam, a right turn ;-)
>> That happened when you write "getRemoteAddr() Returns the Internet Protocol (IP) address of the client or last proxy that sent the request."
>> Yes, that is normally the case, but not when using AJP.
>> The missing link in the story is the "translation" that AJP does:
>> --------------------------------------------------------
>> 1) browser --- HTTP --->  httpd front-end
>> 2) httpd front-end --- AJP --->    Tomcat-AJP
>> 3) Tomcat-AJP   --- HTTP --->  Tomcat-HTTP
> 
> That is kind of wrong.
> A more accurate schema would be :
> 3) Tomcat-AJP (Connector) --> HttpServletRequest --> Valve --> webapps
> and similarly
>   Tomcat-HTTPS (Connector) --> HttpServletRequest --> Valve --> webapps
>   Tomcat-HTTP (Connector) --> HttpServletRequest --> Valve --> webapps
> 
> 
>> (and back off course:  ----> AJP ----> httpd ----> browser )
>> --------------------------------------------------------
>> I doubt whether the AJP connector really sets up an http connection, which the arrow "---HTTP--->"  implies at position 3).
> 
> It doesn't. But who ever said that ? I did not imply that in my simplistic schema.
> 
> I do know that both the servletrequest and the valve present inside the http connector,
> 
> The Valve is not really "inside the http connector".  The Valve happens "after" any Connector has done its job.  The Connector (whichever one it is through which the request came in), translates the request from whatever format it was on the wire, into a standard HttpServletRequest representation.  That is what the Valve sees, and whatever webapp comes after the Valve.
> 
> think it is a genuine http request coming from the browser-client, not an ajp one.
> 
> I believe that this is a misunderstanding on your part, of what AJP is.  There is no such thing, properly speaking, as an "AJP request".  See below.
> 
> For example, debug results show:
>> request.getProtocol() : HTTP/1.1
> 
> That is expected. AJP really "transports" normal HTTP requests. It just encodes them differently "on the wire", than what standard HTTP does.  But by the time your Valve gets the request, it will look just like a normal HTTP request.
> (It is much the same with HTTPS : on the wire, a request will look very different from a pure HTTP request; but what is transported is a normal HTTP request.)
> (If you are (intellectually) curious about the way in which AJP transports a HTTP request, see this : http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html)
> 
>> request.getRemoteAddr() : [ip of the browser-client]
> 
> That is not the default, and it /is/ due to a specific configuration of your Apache httpd.
> Wanna bet ?
> 
>> request.getLocalPort() : 80   <<< not 8080! 
> 
> See http://tomcat.apache.org/connectors-doc/generic_howto/proxy.html :
> 
> "local port: getLocalPort() This is also equal to getServerPort(), unless a Host header is contained in the request. In this case the server port is taken from that header if it contains an explicit port, or is equal to the default port of the scheme used."
> 
> This being a HTTP/1.1 request, it contains a Host header (without a port).
> The scheme used being HTTP, getLocalPort() thus returns 80 (the default port for HTTP).
> 
> If you want something which returns the real Connector port on which the request came in, use request.getServerPort().
> 
>> request.getCoyoteRequest().getWorkerThreadName() : ajp-nio-8009-exec-1   <<< The _only_ reference I could find to anything non-http, but this is a string... And I needed to use reflection to get to the coyote request.
> 
> That is just basically a "coincidence".  Connectors start Threads to process incoming requests. When they do so, they also have to provide a unique name for the Thread.  The AJP NIO Connector happens to build such names as per the scheme shown above.
> It is not something which you should rely on.
> In fact, if the goal is protecting the Valve against unwanted access, the Valve should not care through which Connector the request came in.  No matter through which Connector it came in, it can potentially be from an unwanted client.
> 
>> What I wanted to know, indeed out of intellectual interest, is what you described perfectly (even though it was hard to write): the ip address of the httpd front-end server. I really don't want to exhaust your time on a hunt for something that is just nice to know, but won't be used afterwards. But I (again!) much appreciate the time you took to dive into this quest I gotten myself into ;)
> 
> This being a list manned by volunteers, and being one of them, I only answer when I feel like it, so no trouble at all. But for the sake of the list archives which people may consult later, I felt it was useful to provide the above notes.

Well, I guess I have shown by now that I do not have real knowledge about the inner working of the Tomcat Connectors :-/  Thanks for the explanation!

Regarding my understanding that the AJP connector manipulates the remote_addr / getRemoteAddr(), see the https://tomcat.apache.org/connectors-doc/generic_howto/proxy.html <https://tomcat.apache.org/connectors-doc/generic_howto/proxy.html> :
-------------------------------------
Typical Problems
[...]
    Another example is the client IP address, which for the web server is the source IP of the incoming connection, whereas for the backend the connection always comes from the web server. This can be a problem, when the client IP is used by the backend application e.g. for security reasons.

AJP as a Solution
    Most of these problems are automatically handled by the AJP protocol and the AJP connectors of the backend. The AJP protocol transports this communication metadata and the backend connector presents this metadata whenever the application asks for it using Servlet API methods. 
-------------------------------------

Meanwhile, I have already updated the project I was working on, and am ready to move on to new adventures ;)

Thanks a lot, kind regards,

Paul Klinkenberg


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org



Re: Finding the Apache httpd IP address when AJP is used

Posted by André Warnier <aw...@ice-sa.com>.
Paul Klinkenberg wrote:
> Hi André,
> 
>> 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.
> 
> You were totally on your way to come to the point where my original question was aimed at, and then suddenly, bam, a right turn ;-)
> That happened when you write "getRemoteAddr() Returns the Internet Protocol (IP) address of the client or last proxy that sent the request."
> Yes, that is normally the case, but not when using AJP.
> The missing link in the story is the "translation" that AJP does:
> --------------------------------------------------------
> 1) browser --- HTTP --->  httpd front-end
> 2) httpd front-end --- AJP --->    Tomcat-AJP
> 3) Tomcat-AJP   --- HTTP --->  Tomcat-HTTP

That is kind of wrong.
A more accurate schema would be :
3) Tomcat-AJP (Connector) --> HttpServletRequest --> Valve --> webapps
and similarly
    Tomcat-HTTPS (Connector) --> HttpServletRequest --> Valve --> webapps
    Tomcat-HTTP (Connector) --> HttpServletRequest --> Valve --> webapps


> (and back off course:  ----> AJP ----> httpd ----> browser )
> --------------------------------------------------------
> I doubt whether the AJP connector really sets up an http connection, which the arrow "---HTTP--->"  implies at position 3).

It doesn't. But who ever said that ? I did not imply that in my simplistic schema.

  I do know that both the servletrequest and the valve present inside the http connector,

The Valve is not really "inside the http connector".  The Valve happens "after" any 
Connector has done its job.  The Connector (whichever one it is through which the request 
came in), translates the request from whatever format it was on the wire, into a standard 
HttpServletRequest representation.  That is what the Valve sees, and whatever webapp comes 
after the Valve.

  think it is a genuine http request coming from the browser-client, not an ajp one.

I believe that this is a misunderstanding on your part, of what AJP is.  There is no such 
thing, properly speaking, as an "AJP request".  See below.

  For example, debug results show:
> request.getProtocol() : HTTP/1.1

That is expected. AJP really "transports" normal HTTP requests. It just encodes them 
differently "on the wire", than what standard HTTP does.  But by the time your Valve gets 
the request, it will look just like a normal HTTP request.
(It is much the same with HTTPS : on the wire, a request will look very different from a 
pure HTTP request; but what is transported is a normal HTTP request.)
(If you are (intellectually) curious about the way in which AJP transports a HTTP request, 
see this : http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html)

> request.getRemoteAddr() : [ip of the browser-client]

That is not the default, and it /is/ due to a specific configuration of your Apache httpd.
Wanna bet ?

> request.getLocalPort() : 80   <<< not 8080! 

See http://tomcat.apache.org/connectors-doc/generic_howto/proxy.html :

"local port: getLocalPort() This is also equal to getServerPort(), unless a Host header is 
contained in the request. In this case the server port is taken from that header if it 
contains an explicit port, or is equal to the default port of the scheme used."

This being a HTTP/1.1 request, it contains a Host header (without a port).
The scheme used being HTTP, getLocalPort() thus returns 80 (the default port for HTTP).

If you want something which returns the real Connector port on which the request came in, 
use request.getServerPort().

> request.getCoyoteRequest().getWorkerThreadName() : ajp-nio-8009-exec-1   <<< The _only_ reference I could find to anything non-http, but this is a string... And I needed to use reflection to get to the coyote request.
> 

That is just basically a "coincidence".  Connectors start Threads to process incoming 
requests. When they do so, they also have to provide a unique name for the Thread.  The 
AJP NIO Connector happens to build such names as per the scheme shown above.
It is not something which you should rely on.
In fact, if the goal is protecting the Valve against unwanted access, the Valve should not 
care through which Connector the request came in.  No matter through which Connector it 
came in, it can potentially be from an unwanted client.

> What I wanted to know, indeed out of intellectual interest, is what you described perfectly (even though it was hard to write): the ip address of the httpd front-end server. 
> 
> I really don't want to exhaust your time on a hunt for something that is just nice to know, but won't be used afterwards. But I (again!) much appreciate the time you took to dive into this quest I gotten myself into ;)
> 

This being a list manned by volunteers, and being one of them, I only answer when I feel 
like it, so no trouble at all. But for the sake of the list archives which people may 
consult later, I felt it was useful to provide the above notes.



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Paul Klinkenberg <pa...@ongevraagdadvies.nl>.
Hi André,

> 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.

You were totally on your way to come to the point where my original question was aimed at, and then suddenly, bam, a right turn ;-)
That happened when you write "getRemoteAddr() Returns the Internet Protocol (IP) address of the client or last proxy that sent the request."
Yes, that is normally the case, but not when using AJP.
The missing link in the story is the "translation" that AJP does:
--------------------------------------------------------
1) browser --- HTTP --->  httpd front-end
2) httpd front-end --- AJP --->    Tomcat-AJP
3) Tomcat-AJP   --- HTTP --->  Tomcat-HTTP
(and back off course:  ----> AJP ----> httpd ----> browser )
--------------------------------------------------------
I doubt whether the AJP connector really sets up an http connection, which the arrow "---HTTP--->"  implies at position 3). I do know that both the servletrequest and the valve present inside the http connector, think it is a genuine http request coming from the browser-client, not an ajp one. For example, debug results show:
request.getProtocol() : HTTP/1.1
request.getRemoteAddr() : [ip of the browser-client]
request.getLocalPort() : 80   <<< not 8080!
request.getCoyoteRequest().getWorkerThreadName() : ajp-nio-8009-exec-1   <<< The _only_ reference I could find to anything non-http, but this is a string... And I needed to use reflection to get to the coyote request.

What I wanted to know, indeed out of intellectual interest, is what you described perfectly (even though it was hard to write): the ip address of the httpd front-end server. 

I really don't want to exhaust your time on a hunt for something that is just nice to know, but won't be used afterwards. But I (again!) much appreciate the time you took to dive into this quest I gotten myself into ;)

Thanks, kind regards,

Paul Klinkenberg

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by André Warnier <aw...@ice-sa.com>.
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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Paul Klinkenberg <pa...@ongevraagdadvies.nl>.
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. 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?

Kind regards,

Paul Klinkenberg





>> Op 29 apr. 2015, om 17:48 heeft Christopher Schultz <ch...@christopherschultz.net> het volgende geschreven:
>> 
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA256
>> 
>> Paul,
>> 
>> On 4/29/15 11:17 AM, Paul Klinkenberg wrote:
>>> The reason I want to add the IP restriction in the valve, is to
>>> make 100% sure that the request (for creating a new Tomcat context)
>>> is indeed coming from the frontend webserver.
>> I think there are better ways to do this. Among them:
>> 
>> 1. Firewall rule that only allows access to the AJP port from a
>> certain IP address/range.
>> 
>> 2. Use of the "secret" configuration parameter for mod_jk/AJP connector
>> 
>> In production, we tunnel AJP from our web servers to our application
>> servers using stunnel, and stunnel connections are only allowed from
>> the range of IPs used by our web servers. Then, we actually have the
>> AJP connector listen on ::1 so nobody from the outside can connect to
>> us, except through such a tunnel.
>> 
>>> This valve is a setup not just for me, where I could tweak server settings and such, but for anyone who uses the mod_cfml connector.
>>> It is installed by default by the Railo/Lucee installers
>>> (getrailo.org <http://getrailo.org/> / lucee.org
>>> <http://lucee.org/>)
>> It seems a little fragile, because it requires configuration beyond
>> what an installer can auto-configure for you (i.e. it has no idea what
>> the IP address of the web server(s) is(are)).
>> 
>>> Therefor, I cannot rely on an incoming header, as it could
>>> originate from anywhere. Also, a remote system could call the AJP
>>> endpoint on the Tomcat server, with this JkEnvVar set to a spoofed
>>> value. (if the port is not firewalled off course) So the problem
>>> with both options is, that they cannot be fully trusted.
>> If you are that paranoid, you also can't trust the source IP address
>> in the IP header, so you are back to square 1: you can't trust
>> anything, so don't build your security around this lack-of-trust.
>> 
>>> If I am able to find out where the AJP request came from, then I
>>> can validate the caller.
>> 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.
>> 
>> If you don't trust mod_jk to send you the right values, then you also
>> can't trust the REMOTE_ADDR value that is pointing to the "real"
>> client. Basically, it comes down to this: you either trust mod_jk or
>> not. If you don't, then all bets are off.
>> 
>> If you *can* trust mod_jk, then just forward an environment variable
>> using JkEnvVar: that technique can't be modified by the client
>> injecting an HTTP header or anything like that. But of course, you
>> still have to trust mod_jk and the connection the request came from.
>> This is what the firewall should be used for, IMO.
>> 
>> - -chris
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v2
>> Comment: GPGTools - http://gpgtools.org
>> 
>> iQIcBAEBCAAGBQJVQP1VAAoJEBzwKT+lPKRYkcwQAKEJ4L4xqd7h2TRoA0TaAZYk
>> MsnpJy9fKSOB+18jAgN8d1vcctV9+zabgRqT+BhK6rArc3RcaO4puLgNe2k3IduH
>> AMHXQARLyYFSH42q7cAFyiRV5jVhDdTKr+pEhKTNbXdwdoOxPQMknTpfK01ESPkA
>> kVAKWnT2GdLq9eo3nSGlTXyKJrBLNPa2LhHHQXmc/VaSIO6wFR3pEP/DkoOdU430
>> QVmDinvruNEvSSNf0ef8UTeBhLOYFb099GfIOFq57r46B5s63469yQCwRrCKK7c9
>> g89Xm8j44TI445nj1J7BpbHfwLZxFsKRVwln2MZ0RKxX7ow/Zs/teQj7FpG6pbr2
>> 7RGPi7jn0bo5GVe15S8cQMhPt7144FwuO97dhzPPUD+Dqv6hXuuNO92uJbDjllCl
>> GW5pzhHqKZ7BJ54q6RZsreArz/PRE+Cih/fs+MhjmHy6W/Aj5HeOVF8aJmn4/KvZ
>> T+Ran+gsMCP6yJoT/kBUgUEF0UG2tCgMhS30x3g2y/aGokbeqOX4QND2PtEyz2Mh
>> 9sX9wAfCDNmAtgZU5tGOVh4rKvA0CvZz8JUteOTL/ohgNBwUfkc4zYpYHbX6qwoV
>> N1BxwxRWA+gC931vmJFSrmwwBjbmaBoCVYwpyi+Yh6HPhOKWU+78S63qgXE15sqw
>> OCfKtYQalTmKga46o2gI
>> =Ee12
>> -----END PGP SIGNATURE-----
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by André Warnier <aw...@ice-sa.com>.
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.






> 
> 
>> Op 29 apr. 2015, om 17:48 heeft Christopher Schultz <ch...@christopherschultz.net> het volgende geschreven:
>>
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA256
>>
>> Paul,
>>
>> On 4/29/15 11:17 AM, Paul Klinkenberg wrote:
>>> The reason I want to add the IP restriction in the valve, is to
>>> make 100% sure that the request (for creating a new Tomcat context)
>>> is indeed coming from the frontend webserver.
>> I think there are better ways to do this. Among them:
>>
>> 1. Firewall rule that only allows access to the AJP port from a
>> certain IP address/range.
>>
>> 2. Use of the "secret" configuration parameter for mod_jk/AJP connector
>>
>> In production, we tunnel AJP from our web servers to our application
>> servers using stunnel, and stunnel connections are only allowed from
>> the range of IPs used by our web servers. Then, we actually have the
>> AJP connector listen on ::1 so nobody from the outside can connect to
>> us, except through such a tunnel.
>>
>>> This valve is a setup not just for me, where I could tweak server 
>>> settings and such, but for anyone who uses the mod_cfml connector.
>>> It is installed by default by the Railo/Lucee installers
>>> (getrailo.org <http://getrailo.org/> / lucee.org
>>> <http://lucee.org/>)
>> It seems a little fragile, because it requires configuration beyond
>> what an installer can auto-configure for you (i.e. it has no idea what
>> the IP address of the web server(s) is(are)).
>>
>>> Therefor, I cannot rely on an incoming header, as it could
>>> originate from anywhere. Also, a remote system could call the AJP
>>> endpoint on the Tomcat server, with this JkEnvVar set to a spoofed
>>> value. (if the port is not firewalled off course) So the problem
>>> with both options is, that they cannot be fully trusted.
>> If you are that paranoid, you also can't trust the source IP address
>> in the IP header, so you are back to square 1: you can't trust
>> anything, so don't build your security around this lack-of-trust.
>>
>>> If I am able to find out where the AJP request came from, then I
>>> can validate the caller.
>> 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.
>>
>> If you don't trust mod_jk to send you the right values, then you also
>> can't trust the REMOTE_ADDR value that is pointing to the "real"
>> client. Basically, it comes down to this: you either trust mod_jk or
>> not. If you don't, then all bets are off.
>>
>> If you *can* trust mod_jk, then just forward an environment variable
>> using JkEnvVar: that technique can't be modified by the client
>> injecting an HTTP header or anything like that. But of course, you
>> still have to trust mod_jk and the connection the request came from.
>> This is what the firewall should be used for, IMO.
>>
>> - -chris
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v2
>> Comment: GPGTools - http://gpgtools.org
>>
>> iQIcBAEBCAAGBQJVQP1VAAoJEBzwKT+lPKRYkcwQAKEJ4L4xqd7h2TRoA0TaAZYk
>> MsnpJy9fKSOB+18jAgN8d1vcctV9+zabgRqT+BhK6rArc3RcaO4puLgNe2k3IduH
>> AMHXQARLyYFSH42q7cAFyiRV5jVhDdTKr+pEhKTNbXdwdoOxPQMknTpfK01ESPkA
>> kVAKWnT2GdLq9eo3nSGlTXyKJrBLNPa2LhHHQXmc/VaSIO6wFR3pEP/DkoOdU430
>> QVmDinvruNEvSSNf0ef8UTeBhLOYFb099GfIOFq57r46B5s63469yQCwRrCKK7c9
>> g89Xm8j44TI445nj1J7BpbHfwLZxFsKRVwln2MZ0RKxX7ow/Zs/teQj7FpG6pbr2
>> 7RGPi7jn0bo5GVe15S8cQMhPt7144FwuO97dhzPPUD+Dqv6hXuuNO92uJbDjllCl
>> GW5pzhHqKZ7BJ54q6RZsreArz/PRE+Cih/fs+MhjmHy6W/Aj5HeOVF8aJmn4/KvZ
>> T+Ran+gsMCP6yJoT/kBUgUEF0UG2tCgMhS30x3g2y/aGokbeqOX4QND2PtEyz2Mh
>> 9sX9wAfCDNmAtgZU5tGOVh4rKvA0CvZz8JUteOTL/ohgNBwUfkc4zYpYHbX6qwoV
>> N1BxwxRWA+gC931vmJFSrmwwBjbmaBoCVYwpyi+Yh6HPhOKWU+78S63qgXE15sqw
>> OCfKtYQalTmKga46o2gI
>> =Ee12
>> -----END PGP SIGNATURE-----
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Paul Klinkenberg <pa...@ongevraagdadvies.nl>.
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



> Op 29 apr. 2015, om 17:48 heeft Christopher Schultz <ch...@christopherschultz.net> het volgende geschreven:
> 
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
> 
> Paul,
> 
> On 4/29/15 11:17 AM, Paul Klinkenberg wrote:
>> The reason I want to add the IP restriction in the valve, is to
>> make 100% sure that the request (for creating a new Tomcat context)
>> is indeed coming from the frontend webserver.
> 
> I think there are better ways to do this. Among them:
> 
> 1. Firewall rule that only allows access to the AJP port from a
> certain IP address/range.
> 
> 2. Use of the "secret" configuration parameter for mod_jk/AJP connector
> 
> In production, we tunnel AJP from our web servers to our application
> servers using stunnel, and stunnel connections are only allowed from
> the range of IPs used by our web servers. Then, we actually have the
> AJP connector listen on ::1 so nobody from the outside can connect to
> us, except through such a tunnel.
> 
>> This valve is a setup not just for me, where I could tweak server 
>> settings and such, but for anyone who uses the mod_cfml connector.
>> It is installed by default by the Railo/Lucee installers
>> (getrailo.org <http://getrailo.org/> / lucee.org
>> <http://lucee.org/>)
> 
> It seems a little fragile, because it requires configuration beyond
> what an installer can auto-configure for you (i.e. it has no idea what
> the IP address of the web server(s) is(are)).
> 
>> Therefor, I cannot rely on an incoming header, as it could
>> originate from anywhere. Also, a remote system could call the AJP
>> endpoint on the Tomcat server, with this JkEnvVar set to a spoofed
>> value. (if the port is not firewalled off course) So the problem
>> with both options is, that they cannot be fully trusted.
> 
> If you are that paranoid, you also can't trust the source IP address
> in the IP header, so you are back to square 1: you can't trust
> anything, so don't build your security around this lack-of-trust.
> 
>> If I am able to find out where the AJP request came from, then I
>> can validate the caller.
> 
> 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.
> 
> If you don't trust mod_jk to send you the right values, then you also
> can't trust the REMOTE_ADDR value that is pointing to the "real"
> client. Basically, it comes down to this: you either trust mod_jk or
> not. If you don't, then all bets are off.
> 
> If you *can* trust mod_jk, then just forward an environment variable
> using JkEnvVar: that technique can't be modified by the client
> injecting an HTTP header or anything like that. But of course, you
> still have to trust mod_jk and the connection the request came from.
> This is what the firewall should be used for, IMO.
> 
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v2
> Comment: GPGTools - http://gpgtools.org
> 
> iQIcBAEBCAAGBQJVQP1VAAoJEBzwKT+lPKRYkcwQAKEJ4L4xqd7h2TRoA0TaAZYk
> MsnpJy9fKSOB+18jAgN8d1vcctV9+zabgRqT+BhK6rArc3RcaO4puLgNe2k3IduH
> AMHXQARLyYFSH42q7cAFyiRV5jVhDdTKr+pEhKTNbXdwdoOxPQMknTpfK01ESPkA
> kVAKWnT2GdLq9eo3nSGlTXyKJrBLNPa2LhHHQXmc/VaSIO6wFR3pEP/DkoOdU430
> QVmDinvruNEvSSNf0ef8UTeBhLOYFb099GfIOFq57r46B5s63469yQCwRrCKK7c9
> g89Xm8j44TI445nj1J7BpbHfwLZxFsKRVwln2MZ0RKxX7ow/Zs/teQj7FpG6pbr2
> 7RGPi7jn0bo5GVe15S8cQMhPt7144FwuO97dhzPPUD+Dqv6hXuuNO92uJbDjllCl
> GW5pzhHqKZ7BJ54q6RZsreArz/PRE+Cih/fs+MhjmHy6W/Aj5HeOVF8aJmn4/KvZ
> T+Ran+gsMCP6yJoT/kBUgUEF0UG2tCgMhS30x3g2y/aGokbeqOX4QND2PtEyz2Mh
> 9sX9wAfCDNmAtgZU5tGOVh4rKvA0CvZz8JUteOTL/ohgNBwUfkc4zYpYHbX6qwoV
> N1BxwxRWA+gC931vmJFSrmwwBjbmaBoCVYwpyi+Yh6HPhOKWU+78S63qgXE15sqw
> OCfKtYQalTmKga46o2gI
> =Ee12
> -----END PGP SIGNATURE-----


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Paul,

On 4/29/15 11:17 AM, Paul Klinkenberg wrote:
> The reason I want to add the IP restriction in the valve, is to
> make 100% sure that the request (for creating a new Tomcat context)
> is indeed coming from the frontend webserver.

I think there are better ways to do this. Among them:

1. Firewall rule that only allows access to the AJP port from a
certain IP address/range.

2. Use of the "secret" configuration parameter for mod_jk/AJP connector

In production, we tunnel AJP from our web servers to our application
servers using stunnel, and stunnel connections are only allowed from
the range of IPs used by our web servers. Then, we actually have the
AJP connector listen on ::1 so nobody from the outside can connect to
us, except through such a tunnel.

> This valve is a setup not just for me, where I could tweak server 
> settings and such, but for anyone who uses the mod_cfml connector.
> It is installed by default by the Railo/Lucee installers
> (getrailo.org <http://getrailo.org/> / lucee.org
> <http://lucee.org/>)

It seems a little fragile, because it requires configuration beyond
what an installer can auto-configure for you (i.e. it has no idea what
the IP address of the web server(s) is(are)).

> Therefor, I cannot rely on an incoming header, as it could
> originate from anywhere. Also, a remote system could call the AJP
> endpoint on the Tomcat server, with this JkEnvVar set to a spoofed
> value. (if the port is not firewalled off course) So the problem
> with both options is, that they cannot be fully trusted.

If you are that paranoid, you also can't trust the source IP address
in the IP header, so you are back to square 1: you can't trust
anything, so don't build your security around this lack-of-trust.

> If I am able to find out where the AJP request came from, then I
> can validate the caller.

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.

If you don't trust mod_jk to send you the right values, then you also
can't trust the REMOTE_ADDR value that is pointing to the "real"
client. Basically, it comes down to this: you either trust mod_jk or
not. If you don't, then all bets are off.

If you *can* trust mod_jk, then just forward an environment variable
using JkEnvVar: that technique can't be modified by the client
injecting an HTTP header or anything like that. But of course, you
still have to trust mod_jk and the connection the request came from.
This is what the firewall should be used for, IMO.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVQP1VAAoJEBzwKT+lPKRYkcwQAKEJ4L4xqd7h2TRoA0TaAZYk
MsnpJy9fKSOB+18jAgN8d1vcctV9+zabgRqT+BhK6rArc3RcaO4puLgNe2k3IduH
AMHXQARLyYFSH42q7cAFyiRV5jVhDdTKr+pEhKTNbXdwdoOxPQMknTpfK01ESPkA
kVAKWnT2GdLq9eo3nSGlTXyKJrBLNPa2LhHHQXmc/VaSIO6wFR3pEP/DkoOdU430
QVmDinvruNEvSSNf0ef8UTeBhLOYFb099GfIOFq57r46B5s63469yQCwRrCKK7c9
g89Xm8j44TI445nj1J7BpbHfwLZxFsKRVwln2MZ0RKxX7ow/Zs/teQj7FpG6pbr2
7RGPi7jn0bo5GVe15S8cQMhPt7144FwuO97dhzPPUD+Dqv6hXuuNO92uJbDjllCl
GW5pzhHqKZ7BJ54q6RZsreArz/PRE+Cih/fs+MhjmHy6W/Aj5HeOVF8aJmn4/KvZ
T+Ran+gsMCP6yJoT/kBUgUEF0UG2tCgMhS30x3g2y/aGokbeqOX4QND2PtEyz2Mh
9sX9wAfCDNmAtgZU5tGOVh4rKvA0CvZz8JUteOTL/ohgNBwUfkc4zYpYHbX6qwoV
N1BxwxRWA+gC931vmJFSrmwwBjbmaBoCVYwpyi+Yh6HPhOKWU+78S63qgXE15sqw
OCfKtYQalTmKga46o2gI
=Ee12
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Finding the Apache httpd IP address when AJP is used

Posted by Paul Klinkenberg <pa...@ongevraagdadvies.nl>.
> Paul Klinkenberg wrote:
>> Hi Tomcat users!
>> I have been working on an update for a Tomcat valve called mod_cfml. The project aims to provide automatic web context creation in Tomcat, when coming from a frontend webserver.
>> The live code base can be found at https://github.com/utdream/mod_cfml <https://github.com/utdream/mod_cfml>
>> One of the features I wanted to add, is adding an IP restriction in the valve (see github <https://github.com/paulklinkenberg/mod_cfml/commit/dab058b7f38f98a6e7f076323e3d23be476e6de6>). While testing, I noticed that AJP works very well: it hides the IP address of the caller, which is the front-end Apache webserver, and instead returns the IP of the remote client / the client who called the frontend webserver.
>> I have been digging around quite a lot, but have not been able to find the Apache httpd IP address :-(
>> My question is hopefully simple to answer: can I retrieve the IP address which called the AJP connector, from within the valve?
>> My server.xml is:
>> <Server port="8005" shutdown="SHUTDOWN">
>>  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
>>  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
>>  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
>>  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
>>  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
>>  <GlobalNamingResources>
>>    <Resource name="UserDatabase" auth="Container"
>>              type="org.apache.catalina.UserDatabase"
>>              description="User database that can be updated and saved"
>>              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
>>              pathname="conf/tomcat-users.xml" />
>>  </GlobalNamingResources>
>>  <Service name="Catalina">
>>    <Connector port="8080" protocol="HTTP/1.1"
>>               connectionTimeout="20000"
>>               redirectPort="8443" />
>>    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
>>    <Engine name="Catalina" defaultHost="localhost">
>>      <Realm className="org.apache.catalina.realm.LockOutRealm">
>>        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
>>               resourceName="UserDatabase"/>
>>      </Realm>
>>      <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
>>            <Valve
>>                className="mod_cfml.core"
>>                loggingEnabled="true"
>>                waitForContext="10"
>>                maxContexts="9999"
>>                timeBetweenContexts="0"
>>                scanClassPaths="false"
>>                allowedIPs="127.0.0.1,192.168.1.52" />
>>      </Host>
>>    </Engine>
>>  </Service>
>> </Server>
>> Thanks in advance for your time!
>> Kind regards,
>> Paul Klinkenberg
>> The Netherlands
>> p.s. I asked this question, in other wording, on SackOverflow.com <http://sackoverflow.com/> as well. I hope I have better luck here ;-)
>> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>
> Hi.
> With Apache httpd and mod_jk as front-end, you have (at least) 2 options :
> - set an additional HTTP request header at the Apache httpd level, before the request is proxied to the back-end Tomcat
> - set a "JkEnvVar" value at the at the Apache httpd level, before the request is proxied to Tomcat
> You can then retrieve these set values at the Tomcat level, either by parsing the request headers, or by retrieving a "request attribute" corresponding to the JkEnvVar.
> The JkEnvVar/attribute method is probably more efficient in a mod_jk context; the HTTP header solution is more portable, since it does not depend on specifically mod_jk being used as a connector.
> 
> Presumably, when at the Apache httpd level you decide to proxy a request to a back-end Tomcat, you know through which interface you'll do it, and what its IP address is, and you can put it into one of the things above.
> 
> Is that enough info to get you started ?
> 
> Caveat : one part I am not quite sure of, is what things you do have easy access to, at the level of a Valve.  The above is what you'd do at a webapp level, I hope it is also accessible at your Valve level.
> 

Hi André,

Thanks for the response, much appreciated.
The reason I want to add the IP restriction in the valve, is to make 100% sure that the request (for creating a new Tomcat context) is indeed coming from the frontend webserver. This valve is a setup not just for me, where I could tweak server settings and such, but for anyone who uses the mod_cfml connector. It is installed by default by the Railo/Lucee installers (getrailo.org <http://getrailo.org/> / lucee.org <http://lucee.org/>)

Therefor, I cannot rely on an incoming header, as it could originate from anywhere.
Also, a remote system could call the AJP endpoint on the Tomcat server, with this JkEnvVar set to a spoofed value. (if the port is not firewalled off course)
So the problem with both options is, that they cannot be fully trusted.

If I am able to find out where the AJP request came from, then I can validate the caller.

Maybe you know which path to follow to get to the AJP request data?

Thanks,

Paul Klinkenberg

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org



Re: Finding the Apache httpd IP address when AJP is used

Posted by André Warnier <aw...@ice-sa.com>.
Paul Klinkenberg wrote:
> Hi Tomcat users!
> 
> I have been working on an update for a Tomcat valve called mod_cfml. The project aims to provide automatic web context creation in Tomcat, when coming from a frontend webserver.
> The live code base can be found at https://github.com/utdream/mod_cfml <https://github.com/utdream/mod_cfml>
> 
> One of the features I wanted to add, is adding an IP restriction in the valve (see github <https://github.com/paulklinkenberg/mod_cfml/commit/dab058b7f38f98a6e7f076323e3d23be476e6de6>). 
> While testing, I noticed that AJP works very well: it hides the IP address of the caller, which is the front-end Apache webserver, and instead returns the IP of the remote client / the client who called the frontend webserver.
> I have been digging around quite a lot, but have not been able to find the Apache httpd IP address :-(
> 
> My question is hopefully simple to answer: can I retrieve the IP address which called the AJP connector, from within the valve?
> 
> My server.xml is:
> 
> <Server port="8005" shutdown="SHUTDOWN">
>   <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
>   <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
>   <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
>   <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
>   <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
>   <GlobalNamingResources>
>     <Resource name="UserDatabase" auth="Container"
>               type="org.apache.catalina.UserDatabase"
>               description="User database that can be updated and saved"
>               factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
>               pathname="conf/tomcat-users.xml" />
>   </GlobalNamingResources>
>   <Service name="Catalina">
>     <Connector port="8080" protocol="HTTP/1.1"
>                connectionTimeout="20000"
>                redirectPort="8443" />
>     <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
>     <Engine name="Catalina" defaultHost="localhost">
>       <Realm className="org.apache.catalina.realm.LockOutRealm">
>         <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
>                resourceName="UserDatabase"/>
>       </Realm>
>       <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
>             <Valve
>                 className="mod_cfml.core"
>                 loggingEnabled="true"
>                 waitForContext="10"
>                 maxContexts="9999"
>                 timeBetweenContexts="0"
>                 scanClassPaths="false"
>                 allowedIPs="127.0.0.1,192.168.1.52" />
>       </Host>
>     </Engine>
>   </Service>
> </Server>
> 
> Thanks in advance for your time!
> 
> Kind regards,
> 
> Paul Klinkenberg
> The Netherlands
> 
> p.s. I asked this question, in other wording, on SackOverflow.com <http://sackoverflow.com/> as well. I hope I have better luck here ;-)
> http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp <http://stackoverflow.com/questions/29858030/where-can-i-find-the-apache-httpd-server-ip-from-within-a-tomcat-valve-when-ajp>
> 
> 
Hi.
With Apache httpd and mod_jk as front-end, you have (at least) 2 options :
- set an additional HTTP request header at the Apache httpd level, before the request is 
proxied to the back-end Tomcat
- set a "JkEnvVar" value at the at the Apache httpd level, before the request is proxied 
to Tomcat
You can then retrieve these set values at the Tomcat level, either by parsing the request 
headers, or by retrieving a "request attribute" corresponding to the JkEnvVar.
The JkEnvVar/attribute method is probably more efficient in a mod_jk context; the HTTP 
header solution is more portable, since it does not depend on specifically mod_jk being 
used as a connector.

Presumably, when at the Apache httpd level you decide to proxy a request to a back-end 
Tomcat, you know through which interface you'll do it, and what its IP address is, and you 
can put it into one of the things above.

Is that enough info to get you started ?

Caveat : one part I am not quite sure of, is what things you do have easy access to, at 
the level of a Valve.  The above is what you'd do at a webapp level, I hope it is also 
accessible at your Valve level.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org