Proxypass Ajp

ProxyPass, ProxyReverse vs AJP – Stack Overflow

I currently have a Tomcat + Apache HTTP server setting to serve my Java servlet:
ProxyPass /myservice localhost:8080/myservice
ProxyPassRerverse /myservice localhost:8080/myservice
This is all fine except that myservice needs to know the client IP address, which always turns out to be 127. 0. 1 due to the proxy. Is there a solution to get the real IP address? Is AJP an option?
doGet(HttpServletRequest request, HttpServletResponse response){
tRemoteAddr()}
skaffman386k95 gold badges793 silver badges755 bronze badges
asked Jul 25 ’09 at 2:05
user121196user12119627. 9k56 gold badges139 silver badges197 bronze badges
Do it like this:
in the apache config:

ProxyPass ajplocalhost:8009/foo
ProxyPassReverse ajplocalhost:8009/foo

And then in your

That should pass everything through. The AJP protocol passes the info, but: doesn’t.
You may not want secure=”true”, I use that because SSL is handled at the apache layer and I need tomcat to know that the connection should be considered a secure one.
answered Jul 25 ’09 at 2:47
6
You can read the X-Forwarded-For in the request header.
From the Apache mod_proxy documentation:
When acting in a reverse-proxy mode (using the ProxyPass directive, for example), mod_proxy_ adds several request headers in order to pass information to the origin server. These headers are:
X-Forwarded-For: The IP address of the client.
X-Forwarded-Host: The original host requested by the client in the Host HTTP request header.
X-Forwarded-Server: The hostname of the proxy server.
Be careful when using these headers on the origin server, since they will contain more than one (comma-separated) value if the original request already contained one of these headers. For example, you can use%{X-Forwarded-For}i in the log format string of the origin server to log the original clients IP address, but you may get more than one address if the request passes through several proxies.
In your servlet, you would have:
tHeader(“X-Forwarded-For”)}
answered Dec 2 ’12 at 21:36
rocketscientistrocketscientist2, 2883 gold badges17 silver badges17 bronze badges
1
this is very simple:

ServerName
redirect /
ProxyRequests off
ProxyPass / ajplocalhost:8009/

answered Dec 13 ’10 at 8:25
Not the answer you’re looking for? Browse other questions tagged apache tomcat ajp proxypass or ask your own question.
mod_proxy_ajp - Apache HTTP Server Version 2.4

mod_proxy_ajp – Apache HTTP Server Version 2.4

Usage
This module is used to reverse proxy to a backend application server
(e. g. Apache Tomcat) using the AJP13 protocol. The usage is similar to
an HTTP reverse proxy, but uses the ajp prefix:
Simple Reverse ProxyProxyPass “/app” “ajp”
Options such as the secret option of Tomcat (required by
default since Tomcat 8. 5. 51 and 9. 0. 31) can just be added as a separate
parameter at the end of ProxyPass
or BalancerMember. This parameter
is available in Apache HTTP Server 2. 4. 42 and later:
Simple Reverse Proxy with secret optionProxyPass “/app” “ajp” secret=YOUR_AJP_SECRET
Balancers may also be used:
Balancer Reverse Proxy
BalancerMember “ajp” loadfactor=1
BalancerMember “ajp” loadfactor=2
ProxySet lbmethod=bytraffic

ProxyPass “/app” “balancercluster/app”
Note that usually no
ProxyPassReverse
directive is necessary. The AJP request includes the original host
header given to the proxy, and the application server can be expected
to generate self-referential headers relative to this host, so no
rewriting is necessary.
The main exception is when the URL path on the proxy differs from that
on the
backend. In this case, a redirect header can be rewritten relative to the
original host URL (not the backend ajp URL), for
example:
Rewriting Proxied PathProxyPass “/apps/foo” “ajp”
ProxyPassReverse “/apps/foo” ”
However, it is usually better to deploy the application on the backend
server at the same path as the proxy rather than to take this approach.
Environment Variables
Environment variables whose names have the prefix AJP_
are forwarded to the origin server as AJP request attributes
(with the AJP_ prefix removed from the name of the key).
Overview of the protocol
The AJP13 protocol is packet-oriented. A binary format
was presumably chosen over the more readable plain text for reasons of
performance. The web server communicates with the servlet container over
TCP connections. To cut down on the expensive process of socket creation,
the web server will attempt to maintain persistent TCP connections to the
servlet container, and to reuse a connection for multiple request/response
cycles.
Once a connection is assigned to a particular request, it will not be
used for any others until the request-handling cycle has terminated. In
other words, requests are not multiplexed over connections. This makes
for much simpler code at either end of the connection, although it does
cause more connections to be open at once.
Once the web server has opened a connection to the servlet container,
the connection can be in one of the following states:
Idle No request is being handled over this connection.
Assigned The connection is handling a specific request.
Once a connection is assigned to handle a particular request, the basic
request information (e. HTTP headers, etc) is sent over the connection in
a highly condensed form (e. common strings are encoded as integers).
Details of that format are below in Request Packet Structure. If there is a
body to the request (content-length > 0), that is sent in a
separate packet immediately after.
At this point, the servlet container is presumably ready to start
processing the request. As it does so, it can send the
following messages back to the web server:
SEND_HEADERS Send a set of headers back to the browser.
SEND_BODY_CHUNK Send a chunk of body data back to the browser.
GET_BODY_CHUNK Get further data from the request if it hasn’t all
been transferred yet. This is necessary because the packets have a fixed
maximum size and arbitrary amounts of data can be included the body of a
request (for uploaded files, for example). (Note: this is unrelated to
HTTP chunked transfer).
END_RESPONSE Finish the request-handling cycle.
Each message is accompanied by a differently formatted packet of data.
See Response Packet Structures below for details.
Basic Packet Structure
There is a bit of an XDR heritage to this protocol, but it differs
in lots of ways (no 4 byte alignment, for example).
AJP13 uses network byte order for all data types.
There are four data types in the protocol: bytes, booleans,
integers and strings.
ByteA single byte.
Boolean
A single byte, 1 = true, 0 = false.
Using other non-zero values as true (i. e. C-style) may work in some places,
but it won’t in others.
Integer
A number in the range of 0 to 2^16 (32768). Stored in
2 bytes with the high-order byte first.
String
A variable-sized string (length bounded by 2^16). Encoded with
the length packed into two bytes first, followed by the string
(including the terminating ‘’). Note that the encoded length does
not include the trailing ‘’ — it is like
strlen. This is a touch confusing on the Java side, which
is littered with odd autoincrement statements to skip over these
terminators. I believe the reason this was done was to allow the C
code to be extra efficient when reading strings which the servlet
container is sending back — with the terminating character, the
C code can pass around references into a single buffer, without copying.
if the was missing, the C code would have to copy things out in order
to get its notion of a string.
Packet Size
According to much of the code, the max packet size is
8 * 1024 bytes (8K). The actual length of the packet is encoded in
the header.
Packet Headers
Packets sent from the server to the container begin with
0x1234. Packets sent from the container to the server
begin with AB (that’s the ASCII code for A followed by the
ASCII code for B). After those first two bytes, there is an integer
(encoded as above) with the length of the payload. Although this might
suggest that the maximum payload could be as large as 2^16, in fact, the
code sets the maximum to be 8K.
Packet Format (Server->Container)
Byte
0
1
2
3
4… (n+3)
Contents
0x12
0x34
Data Length (n)
Data
Packet Format (Container->Server)
A
B
For most packets, the first byte of the payload encodes the type of
message. The exception is for request body packets sent from the server to
the container — they are sent with a standard packet header (
0x1234 and then length of the packet), but without any prefix code
after that.
The web server can send the following messages to the servlet
container:
Code
Type of Packet
Meaning
Forward Request
Begin the request-processing cycle with the following data
7
Shutdown
The web server asks the container to shut itself down.
8
Ping
The web server asks the container to take control
(secure login phase).
10
CPing
The web server asks the container to respond quickly with a CPong.
none
Size (2 bytes) and corresponding body data.
To ensure some basic security, the container will only actually do the
Shutdown if the request comes from the same machine on which
it’s hosted.
The first Data packet is send immediately after the
Forward Request by the web server.
The servlet container can send the following types of messages to the
webserver:
Send Body Chunk
Send a chunk of the body from the servlet container to the web
server (and presumably, onto the browser).
4
Send Headers
Send the response headers from the servlet container to the web
5
End Response
Marks the end of the response (and thus the request-handling cycle).
6
Get Body Chunk
Get further data from the request if it hasn’t all been
transferred yet.
9
CPong Reply
The reply to a CPing request
Each of the above messages has a different internal structure, detailed
below.
Request Packet Structure
For messages from the server to the container of type
Forward Request:
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
The request_headers have the following structure:
req_header_name:=
sc_req_header_name | (string) [see below for how this is parsed]
sc_req_header_name:= 0xA0xx (integer)
req_header_value:= (string)
The attributes are optional and have the following
structure:
attribute_name:= sc_a_name | (sc_a_req_attribute string)
attribute_value:= (string)
Not that the all-important header is content-length,
because it determines whether or not the container looks for another
packet immediately.
Detailed description of the elements of Forward Request
Request prefix
For all requests, this will be 2. See above for details on other Prefix
codes.
Method
The HTTP method, encoded as a single byte:
Command NameCode
OPTIONS1
GET2
HEAD3
POST4
PUT5
DELETE6
TRACE7
PROPFIND8
PROPPATCH9
MKCOL10
COPY11
MOVE12
LOCK13
UNLOCK14
ACL15
REPORT16
VERSION-CONTROL17
CHECKIN18
CHECKOUT19
UNCHECKOUT20
SEARCH21
MKWORKSPACE22
UPDATE23
LABEL24
MERGE25
BASELINE_CONTROL26
MKACTIVITY27
Later version of ajp13, will transport
additional methods, even if they are not in this list.
protocol, req_uri, remote_addr, remote_host, server_name,
server_port, is_ssl
These are all fairly self-explanatory. Each of these is required, and
will be sent for every request.
Headers
The structure of request_headers is the following:
First, the number of headers num_headers is encoded.
Then, a series of header name req_header_name / value
req_header_value pairs follows.
Common header names are encoded as integers,
to save space. If the header name is not in the list of basic headers,
it is encoded normally (as a string, with prefixed length). The list of
common headers sc_req_header_nameand their codes
is as follows (all are case-sensitive):
NameCode valueCode name
accept0xA001SC_REQ_ACCEPT
accept-charset0xA002SC_REQ_ACCEPT_CHARSET
accept-encoding0xA003SC_REQ_ACCEPT_ENCODING
accept-language0xA004SC_REQ_ACCEPT_LANGUAGE
authorization0xA005SC_REQ_AUTHORIZATION
connection0xA006SC_REQ_CONNECTION
content-type0xA007SC_REQ_CONTENT_TYPE
content-length0xA008SC_REQ_CONTENT_LENGTH
cookie0xA009SC_REQ_COOKIE
cookie20xA00ASC_REQ_COOKIE2
host0xA00BSC_REQ_HOST
pragma0xA00CSC_REQ_PRAGMA
referer0xA00DSC_REQ_REFERER
user-agent0xA00ESC_REQ_USER_AGENT
The Java code that reads this grabs the first two-byte integer and if
it sees an ‘0xA0’ in the most significant
byte, it uses the integer in the second byte as an index into an array of
header names. If the first byte is not 0xA0, it assumes that
the two-byte integer is the length of a string, which is then read in.
This works on the assumption that no header names will have length
greater than 0x9FFF (==0xA000 – 1), which is perfectly
reasonable, though somewhat arbitrary.
Note:
The content-length header is extremely
important. If it is present and non-zero, the container assumes that
the request has a body (a POST request, for example), and immediately
reads a separate packet off the input stream to get that body.
Attributes
The attributes prefixed with a?
(e. g.? context) are all optional. For each, there is a
single byte code to indicate the type of attribute, and then its value
(string or integer). They can be sent in any order (though the C code
always sends them in the order listed below). A special terminating code
is sent to signal the end of the list of optional attributes. The list of
byte codes is:
InformationCode ValueType Of ValueNote? context0x01-Not currently implemented? servlet_path0x02-Not currently implemented? remote_user0x03String? auth_type0x04String? query_string0x05String? jvm_route0x06String? ssl_cert0x07String? ssl_cipher0x08String? ssl_session0x09String? req_attribute0x0AStringName (the name of the
attribute follows)? ssl_key_size0x0BInteger? secret0x0CStringSupported since 2. 42
are_done0xFF-request_terminator
The context and servlet_path are not
currently set by the C code, and most of the Java code completely ignores
whatever is sent over for those fields (and some of it will actually break
if a string is sent along after one of those codes). I don’t know if this
is a bug or an unimplemented feature or just vestigial code, but it’s
missing from both sides of the connection.
The remote_user and auth_type presumably
refer to HTTP-level authentication, and communicate the remote user’s
username and the type of authentication used to establish their identity
(e. Basic, Digest).
The query_string, ssl_cert,
ssl_cipher, ssl_session and
ssl_key_size refer to the
corresponding pieces of HTTP and HTTPS.
The jvm_route, is used to support sticky
sessions — associating a user’s sesson with a particular Tomcat instance
in the presence of multiple, load-balancing servers.
The secret is sent when the secret=secret_keyword
parameter is used in
ProxyPass or
BalancerMember directives.
The backend needs to support secret and the values must match.
or requiredSecret are documented in the AJP
configuration of the Apache Tomcat.
Beyond this list of basic attributes, any number of other attributes
can be sent via the req_attribute code 0x0A.
A pair of strings to represent the attribute name and value are sent
immediately after each instance of that code. Environment values are passed
in via this method.
Finally, after all the attributes have been sent, the attribute
terminator, 0xFF, is sent. This signals both the end of the
list of attributes and also then end of the Request Packet.
Response Packet Structure
for messages which the container can send back to the server.
AJP13_SEND_BODY_CHUNK:=
prefix_code 3
chunk_length (integer)
chunk *(byte)
chunk_terminator (byte) Ox00
AJP13_SEND_HEADERS:=
prefix_code 4
_status_code (integer)
_status_msg (string)
response_headers *(res_header_name header_value)
res_header_name:=
sc_res_header_name | (string) [see below for how this is parsed]
sc_res_header_name:= 0xA0 (byte)
header_value:= (string)
AJP13_END_RESPONSE:=
prefix_code 5
reuse (boolean)
AJP13_GET_BODY_CHUNK:=
prefix_code 6
requested_length (integer)
Details:
The chunk is basically binary data, and is sent directly back to the
browser.
The status code and message are the usual HTTP things
(e. 200 and OK). The response header names are
encoded the same way the request header names are. See header_encoding above
for details about how the codes are distinguished from the strings.
The codes for common headers are:
NameCode value
Content-Type0xA001
Content-Language0xA002
Content-Length0xA003
Date0xA004
Last-Modified0xA005
Location0xA006
Set-Cookie0xA007
Set-Cookie20xA008
Servlet-Engine0xA009
Status0xA00A
WWW-Authenticate0xA00B
After the code or the string header name, the header value is
immediately encoded.
Signals the end of this request-handling cycle. If the
reuse flag is true (anything other than 0 in the actual
C code), this TCP connection can now be used to handle new incoming
requests. If reuse is false (==0), the connection should
be closed.
The container asks for more data from the request (If the body was
too large to fit in the first packet sent over or when the request is
chunked). The server will send a body packet back with an amount of data
which is the minimum of the request_length, the maximum send
body size (8186 (8 Kbytes – 6)), and the number of bytes
actually left to send from the request body.
If there is no more data in the body (i. the servlet container is
trying to read past the end of the body), the server will send back an
empty packet, which is a body packet with a payload length of 0.
(0x12, 0x34, 0x00, 0x00)
Configuring Apache Reverse Proxy Using the AJP Protocol

Configuring Apache Reverse Proxy Using the AJP Protocol

Atlassian applications allow the use of reverse-proxies within our products, however Atlassian Support does not provide assistance for configuring them. Consequently, Atlassian can not guarantee providing any support for assistance with configuration is required, please raise a question on Atlassian Community.
“Ghostcat” vulnerability in Apache TomcatFollowing this guide might make your Jira instance prone to a recent high-risk vulnerability found in Apache Tomcat.
Step 1: Configure TomcatStop the AJP Connector on the Tomcat container hosting Jira by uncommenting the following element in $JIRA_INSTALL/conf/

Start that Jira is accessible on the standard HTTP connector, for example jiraserver:8080. This is to ensure that Tomcat has successfully 2: Configure Apache HTTP ServerThe installation of Apache and configuration of a DNS is not covered in this documentation. Additionally, it is assumed that Apache 2. 2 has been installed and DNS entries have been configured for the Jira domain. As Apache’s configuration is specific to the operation system that is used, only some distributions and their configurations are currently documented. 2. 1 Enable the Proxy ModulesDebian/Ubuntu
Expand to see Debian/Ubuntu instructions
Enable the module with the following:
$ sudo a2enmod proxy_ajp
Considering dependency proxy for proxy_ajp:
Module proxy already enabled
Enabling module proxy_ajp.
To activate the new configuration, you need to run:
service apache2 restart
Restart Apache.
Windows/Other OS
Expand to see Windows/Other OS instructions
Locate and edit the file, adding the below lines:
LoadModule proxy_module modules/
LoadModule proxy_ajp_module modules/
2. Configure Apache to use those ModulesDebian/Ubuntu
Switch into user the existing site or create a new one. Creating a new site is not covered within this documentation (copying the default should be sufficient) the existing site within $APACHE_INSTALL/sites-available, for example default (HTTP) or default-ssl (HTTPS) the following inside the VirtualHost, replacing jiraserver with the hostname of the Jira server and also modifying the port if required.
# Jira AJP Proxy Configuration:

Order deny, allow
Allow from all

ProxyRequests Off
ProxyPass / ajpjiraserver:8009/
ProxyPassReverse / ajpjiraserver:8009/
Missing a forward slash at the end of the URL will cause proxy errors – ensure this is in place! (Optional): Enable the site with the following:
# a2ensite jira
Enabling site jira.
service apache2 reload
This is only required if a new site has been created in favor of using the using HTTP, skip to step 8. For HTTPS, the certificates need to be installed by copying the certificate and private key to the appropriate directories and the following will also need to be added to the site:
Include them in the Apache configuration, within the VirtualHost as below:
SSLCertificateFile /etc/ssl/certs/
SSLCertificateKeyFile /etc/ssl/private/
Reload the Apache by accessing Jira through Apache, for example or
Locate and edit the the following inside the VirtualHost, replacing jiraserver with the hostname of the Jira server and also modifying the port if required.
Missing a forward slash at the end of the URL will cause proxy errors – ensure this is in place! If using HTTP, skip to step 5. For HTTPS, the certificates need to be installed by copying the certificate and private key to the appropriate directories and the following will also need to be added to the site:
Restart by accessing Jira through Apache, for example or
2. 3 Redirect HTTP to HTTPSThis is an optional step and is only required if using HTTPS. It can be done by using mod_rewrite (this module may require enabling), add the following to the HTTP VirtualHost:
RewriteEngine On
RewriteCond%{HTTPS} off
RewriteRule (. *)%{HTTP_HOST}%{REQUEST_URI}
Step 3: Configure JiraSet Use gzip compression to OFF as in Configuring Jira options. GZIP compression is known to cause performance issues using a reverse-proxy, especially if the proxy is also compressing the the Base URL to be the FQDN that Jira will be accessed on, for example. This is also located in Configuring Jira options. Jira can only be configured to respond to a single URL and the Base URL (as in Configuring Jira options) must match the URL end-users are accessing. Misconfiguration of this may cause significant problems within Jira such as the Activity Stream and Dashboard Gadgets failing to function by accessing Jira on the FQDN (e. g. :), ensuring that Jira is accessible and all dashboard gadgets correctly oubleshootingHijacked Sessions: Some users have reported problems with user sessions being hijacked when the mod_cache module is enabled. If these problems are encountered, try disabling the mod_cache module. This module is enabled by default in some Apache HTTP Server version 2 rmission Denied Errors enabling mod_proxy (and mod_jk) on Linux distros that use SELinux: Users have reported ‘permission denied’ errors when trying to get mod_proxy (and mod_jk) working. Disabling SELinux (/etc/selinux/config) apparently fixes nning Mac OS X: Disable webperfcache, which proxies port 80 by default. A user reported this as the likely cause of Jira session problems, in the form of users’ identities becoming mixed up, as below. Additionally we do not recommend using Max OS X as it is not supported, as in our Supported OSX Servers enable webperfcache by default for Virtual Hosts, which for static content would be great, but for dynamic instances (which ALL of ours are) it is Evil and causes many issues. Of note recently was the jira session issue. Also see:- even if you disable webperfcache for a instance, if there is a single instance enabled then all instances will still proxy through webperfcache with resulting session problems.
Too many redirects: Both Tomcat & Apache are redirecting, when only one should be. Disable redirection in Tomcat (revert any changes as in Running Jira over SSL or HTTPS) and check that there is only one redirection in neral Problems:Clear the browser cache and try that Jira works as expected when running directly from Tomcat and bypassing Apache. For example, accessing jiraserver:8080 instead of the LogLevel for Apache to debug and restart tempt to access Jira and check the Apache Log Files for any a question on Atlassian Answers for assistance. 403 Forbidden error: Add the RequestHeader unset Authorization line to the apache configuration page to disable authorization headers.

RequestHeader unset Authorization
ProxyPreserveHost On
ProxyPass jiraserver/jira
ProxyPassReverse jiraserver/jira

See alsoIntegrating Jira with ApacheIntegrating Jira with Apache using SSLApache Virtual Host documentation
Last modified on Mar 4, 2020
Related content
No related content found

Frequently Asked Questions about proxypass ajp

What is ProxyPass and ProxyPassReverse in httpd conf?

The “ProxyPass” and “ProxyPassReverse” parameters are used to tell Apache how to proxy requests. They require the “mod_proxy.so” and “mod_proxy_http.so” Apache modules, which are loaded by default in RHEL5 and RHEL6, but check the following lines are uncommented in the “/etc/httpd/conf/httpd. conf” file to make sure.

What is ProxyPass?

ProxyPass is the main proxy configuration directive. In this case, it specifies that everything under the root URL ( / ) should be mapped to the backend server at the given address. … ProxyPassReverse should have the same configuration as ProxyPass . It tells Apache to modify the response headers from backend server.Feb 2, 2017

What is difference between AJP and HTTP?

AJP Connectors work in the same way as HTTP Connectors, but they use the AJP protocol in place of HTTP. Apache JServ Protocol, or AJP, is an optimized binary version of HTTP that is typically used to allow Tomcat to communicate with an Apache web server.

Leave a Reply

Your email address will not be published. Required fields are marked *