Bug 41263 - servletRequest.getRemotePort() returns incorrect value when behind mod_jk
Summary: servletRequest.getRemotePort() returns incorrect value when behind mod_jk
Status: RESOLVED FIXED
Alias: None
Product: Tomcat Connectors
Classification: Unclassified
Component: Common (show other bugs)
Version: unspecified
Hardware: Other All
: P2 enhancement (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-12-29 15:41 UTC by Chris Lamprecht
Modified: 2011-03-07 15:45 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Lamprecht 2006-12-29 15:41:28 UTC
Access the following short test JSP running on a tomcat behind mod_jk and Apache:


<% out.println("Your IP is "+request.getRemoteAddr()+", your port is
"+request.getRemotePort()); %>


It returns either 0 or -1 for the remote port.  It seems to return 0 the first
time, and -1 for any subsequent request which is on the same underlying
keepalive connection.  

The desired behaviour would be that it returns the actual remote port that the
client connected from (on the client's machine), when available.  In other
words, it should behave the same as when you access the JSP through tomcat
directly through an HTTP connector (via port 8080 on a default tomcat install,
for instance).

I understand this information will not always be available, for instance, when
running behind a proxy.  But in the case of running behind mod_jk, shouldn't
this information be available, since the remote IP number is already available?
Comment 1 Rainer Jung 2006-12-30 06:04:32 UTC
Unfortunately the remote port is not part of the information passed along via
the ajp13 protocol. On the page

http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html

you can find under the heading "Request Packet Structure":

AJP13_FORWARD_REQUEST :=
    prefix_code      (byte) 0x02 = JK_AJP13_FORWARD_REQUEST
    method           (byte)
    protocol         (string)
    req_uri          (string)
    remote_addr      (string)
    remote_host      (string)
    server_name      (string)
    server_port      (integer)
    is_ssl           (boolean)
    num_headers      (integer)
    request_headers *(req_header_name req_header_value)
    attributes      *(attribut_name attribute_value)
    request_terminator (byte) OxFF

So I'm marking this as an enhancement request.
It's unclear though, if and when we will resolve this.
Thanks for the report.
Comment 2 Rainer Jung 2006-12-30 06:12:34 UTC
Implementation hint: if we want to stay compatible with ajp13 we could use
another request attribute (in the ajp13 sense, e.g. SC_A_REMOTE_PORT = 14).
Unknown attributes are ignored on the tomcat side.
Comment 3 Rainer Jung 2006-12-30 09:43:15 UTC
Unfortunately ignoring unknown attributes does not really happen. It's only what
the code comments claim to happen.

Instead unknown bytes are simply dropped, but if we introduce a new attribute
with a new indicator byte, the indicator gets dropped, but one of the following
length or data bytes might coincidently by equal to another indicator byte and
then everything breaks.

I tested by adding a new attribute server_addr, and the length of the addr
string was 12=oc. The decoder dropped the new indicator byte 0e but then found
the length byte 0c and assumed this to be equal to the SECRET indicator byte...

No easy way of adding new attributes :(

remotePort and LocalAddr have been forgotten (they were added in Servlet Spec
2.4) (resp. were dropped to not break the AJP13 protocol). We can easily get
both from Apache and IIS, but we first have to find a way to transmit them via
AJP13.
Comment 4 Rainer Jung 2008-01-03 05:54:51 UTC
This needs a protocol extension for AJP13 (or whatever the version number will
then be).
Would be nice to also build in an easier protocol extensibility.
Comment 5 Rainer Jung 2009-03-21 04:47:36 UTC
Just a workaround, not a solution:

You can use JkEnvVar to forward arbitrary data, which is available in the form of so called httpd environment variables. The remote port fortunately is available under the name REMOTE_PORT.

So in mod_jk you can set

JkEnvVar REMOTE_PORT

and in the java webapp you can retrieve the data with

request.getAttribute("REMOTE_PORT")

Obviously this is not spec compliant. You might be able to wrap the request in a filter and overwrite remotePort() using the above call.

A final solution needs an enhanced AJP13 protocol.
Comment 6 Rainer Jung 2009-03-21 07:10:17 UTC
I added a fix to Tomcat trunk to automatically respect the forwarded attribute REMOTE_PORT as the value for getRemotePort():

http://svn.eu.apache.org/viewvc?view=rev&revision=756926

The change has been proposed for backport to TC 6.0 and 5.5.

We might also forward the REMOTE_PORT env var as an attribute automatically without JKEnvVar starting with a future mod_jk version like 1.2.29.
Comment 7 Rainer Jung 2011-03-07 15:45:03 UTC
I added automatic forwarding of port info to mod_jk in r1078805.
Will be part of mod_jk 1.2.32.

A getRemotePort() working out of the box without workaround needs mod_jk 1.2.32 and Tomcat 5.5.28, 6.0.20 or 7.0.0 - or newer.