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