AJP协议总结与分析
2016-08-04 00:11
316 查看
Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户。默认情况下,Tomcat在server.xml中配置了两种连接器:
<!-- Define a non-SSL Coyote HTTP/1.1
Connector on port 8080 -->
<Connector port="8080"
maxThreads="150"
minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
redirectPort="8443"
acceptCount="100"
debug="0"
connectionTimeout="20000"
disableUploadTimeout="true" />
<!-- Define a Coyote/JK2 AJP 1.3
Connector on port 8009 -->
<Connector port="8009"
enableLookups="false"
redirectPort="8443" debug="0"
protocol="AJP/1.3" />
第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个
http://blog.sina.com.cn/s/blog_6870d1e00100mv64.html
一般Tomcat默认的SSL端口号是8443,但是对于SSL标准端口号是443,这样在访问网页的时候,直接使用https而不需要输入端口号就可以访问,如https://ip/
想要修改端口号,需要修改Tomcat的server.xml文件:
1.non-SSL HTTP/1.1 Connector定义的地方,一般如下:
<Connector port="80" maxHttpHeaderSize="8192"
maxThreads="500" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
将其中的redirectPort端口号改为:443
2.SSL HTTP/1.1 Connector定义的地方,修改端口号为:443,如下:
<Connector
port="443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
disableUploadTimeout="true"
acceptCount="100" scheme="https"
secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="conf/tomcat.keystore"
keystorePass="123456" />
3.AJP 1.3 Connector定义的地方,修改redirectPort为443,如下:
<Connector port="8009"
enableLookups="false" redirectPort="443" protocol="AJP/1.3" />
重新启动Tomcat就可以了。到这一步可以形成访问方式 https://ip/
4、强制https访问
在tomcat\conf\web.xml中的</welcome-file-list>后面加上这样一段:
<login-config>
<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
注意:(如果对方使用的机器端口被占用)
需要切换端口来转换数据:iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
AJP(Apache JServ Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本。WEB服务器通过TCP连接和SERVLET容器连接。
(格式显示不好,本文已放附件中)
AJP协议是定向包(面向包)协议,采用二进制形式代替文本形式,以提高性能。Web Server一般维持和Web Container的多个TCP Connecions,即TCP连接池,多个request/respons循环重用同一个Connection。但是当Connection被分配(Assigned)到某个请求时,该请求完成之前,其他请求不得使用该连接。
Tcp Connection 具有两种状态:
(1). Idle
没有请求正使用该连接。
(2). Assigned
当前连接正在处理某个请求.
数据类型:
AJP协议中包括四种数据类型:Byte, Boolean, Integer and String.
Byte: 一个字节
Boolean: 一个字节,1 = true, 0 = false。
Integer:两个字节,无符号整数,高位字节在前。
String:可变字符串,最大长度为2^16. 字符串的前而会有二个字节(Integer型)表示字符串的长度,-1表示null。字符串后面会跟上终结符”\0”,而且字符串长度不包括这个终结符。
AJP的包结构,图表1:
图表1
可以看出,从apache发向tomcat包都带有0x1234头,而从tomcat发向apache的包都带有AB(ascii码)头,随后二字节代表数据的长度(不包括前四个字节).所认AJP包的最大长度可以接近2^16,但目前的版本支持的最大包长度为2^13,即8K。
再看数据部分(payload),除Server->Container的请求体包外,其他包的数据部分的首字节为其消息类型(code),如下表(描述部分是原文,译成中文本人认为更难理解,英文表义比中文是好一些):
[align=left]Forward Request包数据部分(payload)结构:[/align]
---------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------
(1) prefix_code 所有的Forward Request包都是0x02.
(2) Method: 一个字节,对方法的编码,其对应如下(只列了部分):
(参考:http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html)
(3) protocol, req_uri, remote_addr, remote_host, server_name, server_port, is_ssl: 每个请求包都有这几个字段,格式都是 长度+字符串值+\0结束符。
(4) num_headers: 请求头的个数,两个字节。
(5) request_headers:
请求头名称分化为两类,一类请求头被转换为0xA0xx格式(如下表所示),其他请求头仍然用原字符串编码。
(6) Java代码读取头两个字节的整数型,如果高位字节为”0xA0” ,则第二字节为上在列表的索引。如果高位字节不是”0xA0”,则这两个字节为随后请求头名称的长度。
(7) Attributes:很少用,直接看tomcat文档吧。
(8) request_terminator: 一个字节0xFF,请求结束符。
响应包数据部分(payload)结构:
1. response_headers: 和请求头一样,一类响应头被转换为0xA0xx格式(如下表所示),其他响应头名称采用原字符串编码。
2. reuse: 如果为1,表示该连接可以被子重用,否则这个连接应该关闭。
下面我们来看一个简单AJP请求过程中抓到的请求包:
http://localhost/test/testCluster.jsp请求:
[align=left] [/align]
1,2字节是上文所说的Server->Container包头,3,4字节表示包长度(0x01b0=432),即从第5个字节到最后的一个字节(ff)的长度。第5个字节(02)代表是”Forward Request”包。
第6个字节(02)代表是Get请求。第7,8字节(0x0008)代表protocol字符串的长度,后8个字节为protocol字符串(HTTP/1.1),第9个字节为protocol字符串的终结符“\0”。
18-41字节代表req_uri字符串(0x15+2+1=24个)。
42-53字节代表remote_addr字符串(0x09+2+1=12个)
54-55 两字节(0xffff=-1)代表null字符串,即remote_host不存在。
56-67两字节代表server_name字符串(0x09+2+1=12个)
68-69两字节(0x0050=80)代表server_port
70字节(0x00)代表is_ssl为false
71-72两字节(0x0009)代表该请求有9个请求头,如图中的前9个红色椭圆.
第10个红色椭圆(0x06)代表Attributes的route.
第11个红椭圆之后,代表AJP_REMOTE_PORT与JK_LB_ACTIVATION两个请求属性.
最后一个字节0xFF表示请求结束。
[align=left] [/align]
和请示头比较类似,不再细描述。其中第5个字节0x04代表”Send Headers”响应。
并且没有终结符字节0xFF.
响应结束End Response:
其中最后一个字节(01),代表当前连接仍然可用。
(完) http://guojuanjun.blog.51cto.com/277646/688559/
<!-- Define a non-SSL Coyote HTTP/1.1
Connector on port 8080 -->
<Connector port="8080"
maxThreads="150"
minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
redirectPort="8443"
acceptCount="100"
debug="0"
connectionTimeout="20000"
disableUploadTimeout="true" />
<!-- Define a Coyote/JK2 AJP 1.3
Connector on port 8009 -->
<Connector port="8009"
enableLookups="false"
redirectPort="8443" debug="0"
protocol="AJP/1.3" />
第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个
http://blog.sina.com.cn/s/blog_6870d1e00100mv64.html
一般Tomcat默认的SSL端口号是8443,但是对于SSL标准端口号是443,这样在访问网页的时候,直接使用https而不需要输入端口号就可以访问,如https://ip/
想要修改端口号,需要修改Tomcat的server.xml文件:
1.non-SSL HTTP/1.1 Connector定义的地方,一般如下:
<Connector port="80" maxHttpHeaderSize="8192"
maxThreads="500" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
将其中的redirectPort端口号改为:443
2.SSL HTTP/1.1 Connector定义的地方,修改端口号为:443,如下:
<Connector
port="443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
disableUploadTimeout="true"
acceptCount="100" scheme="https"
secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="conf/tomcat.keystore"
keystorePass="123456" />
3.AJP 1.3 Connector定义的地方,修改redirectPort为443,如下:
<Connector port="8009"
enableLookups="false" redirectPort="443" protocol="AJP/1.3" />
重新启动Tomcat就可以了。到这一步可以形成访问方式 https://ip/
4、强制https访问
在tomcat\conf\web.xml中的</welcome-file-list>后面加上这样一段:
<login-config>
<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
注意:(如果对方使用的机器端口被占用)
需要切换端口来转换数据:iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
AJP(Apache JServ Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本。WEB服务器通过TCP连接和SERVLET容器连接。
(格式显示不好,本文已放附件中)
AJP协议是定向包(面向包)协议,采用二进制形式代替文本形式,以提高性能。Web Server一般维持和Web Container的多个TCP Connecions,即TCP连接池,多个request/respons循环重用同一个Connection。但是当Connection被分配(Assigned)到某个请求时,该请求完成之前,其他请求不得使用该连接。
Tcp Connection 具有两种状态:
(1). Idle
没有请求正使用该连接。
(2). Assigned
当前连接正在处理某个请求.
数据类型:
AJP协议中包括四种数据类型:Byte, Boolean, Integer and String.
Byte: 一个字节
Boolean: 一个字节,1 = true, 0 = false。
Integer:两个字节,无符号整数,高位字节在前。
String:可变字符串,最大长度为2^16. 字符串的前而会有二个字节(Integer型)表示字符串的长度,-1表示null。字符串后面会跟上终结符”\0”,而且字符串长度不包括这个终结符。
AJP的包结构,图表1:
包方向 | 0 | 1 | 2 | 3 | 4…(n+3) |
Server->Container | 0x12 | 0x34 | 数据长度(n) | 数据(payload) | |
Container->Server | A | B | 数据长度(n) | 数据(payload) |
可以看出,从apache发向tomcat包都带有0x1234头,而从tomcat发向apache的包都带有AB(ascii码)头,随后二字节代表数据的长度(不包括前四个字节).所认AJP包的最大长度可以接近2^16,但目前的版本支持的最大包长度为2^13,即8K。
再看数据部分(payload),除Server->Container的请求体包外,其他包的数据部分的首字节为其消息类型(code),如下表(描述部分是原文,译成中文本人认为更难理解,英文表义比中文是好一些):
[align=center]方向[/align] | code | 包类型 | 描述 |
[align=center]Server->Container[/align] | 2 | 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 | Data | Size (2 bytes) and corresponding body data. | |
[align=center]Container->Server[/align] | [align=left]3[/align] | [align=left]Send Body Chunk[/align] | Send a chunk of the body from the servlet container to the web server |
[align=left]4[/align] | [align=left]Send Headers[/align] | Send the response headers from the servlet container to the web server | |
[align=left]5[/align] | [align=left]End Response[/align] | [align=left]Marks the end of the response[/align] | |
[align=left]6[/align] | [align=left]Get Body Chunk[/align] | Get further data from the request if it hasn't all been transferred yet | |
[align=left]9[/align] | [align=left]CPong Reply[/align] | [align=left]The reply to a CPing request[/align] |
[align=left]AJP13_FORWARD_REQUEST :=[/align] [align=left] prefix_code (byte) 0x02 = JK_AJP13_FORWARD_REQUEST[/align] [align=left] method (byte)[/align] [align=left] protocol (string)[/align] [align=left] req_uri (string)[/align] [align=left] remote_addr (string)[/align] [align=left] remote_host (string)[/align] [align=left] server_name (string)[/align] [align=left] server_port (integer)[/align] [align=left] is_ssl (boolean)[/align] [align=left] num_headers (integer)[/align] request_headers *(req_header_name req_header_value) [align=left] attributes *(attribut_name attribute_value)[/align] request_terminator (byte) OxFF |
[align=left]req_header_name :=[/align] sc_req_header_name | (string) [see below for how this is parsed] |
sc_req_header_name := 0xA0xx (integer) [align=left]req_header_value := (string)[/align] |
attribute_name := sc_a_name | (sc_a_req_attribute string) [align=left]attribute_value := (string)[/align] |
(2) Method: 一个字节,对方法的编码,其对应如下(只列了部分):
Command Name | code | POST | 4 |
OPTIONS | 1 | PUT | 5 |
GET | 2 | DELETE | 6 |
HEAD | 3 | TRACE | 7 |
(3) protocol, req_uri, remote_addr, remote_host, server_name, server_port, is_ssl: 每个请求包都有这几个字段,格式都是 长度+字符串值+\0结束符。
(4) num_headers: 请求头的个数,两个字节。
(5) request_headers:
请求头名称分化为两类,一类请求头被转换为0xA0xx格式(如下表所示),其他请求头仍然用原字符串编码。
请求头 | Code 值 | Code 名称 |
accept | 0xA001 | SC_REQ_ACCEPT |
accept-charset | 0xA002 | SC_REQ_ACCEPT_CHARSET |
accept-encoding | 0xA003 | SC_REQ_ACCEPT_ENCODING |
accept-language | 0xA004 | SC_REQ_ACCEPT_LANGUAGE |
authorization | 0xA005 | SC_REQ_AUTHORIZATION |
connection | 0xA006 | SC_REQ_CONNECTION |
content-type | 0xA007 | SC_REQ_CONTENT_TYPE |
content-length | 0xA008 | SC_REQ_CONTENT_LENGTH |
cookie | 0xA009 | SC_REQ_COOKIE |
cookie2 | 0xA00A | SC_REQ_COOKIE2 |
host | 0xA00B | SC_REQ_HOST 0xA00C |
pragma | 0xA00C | SC_REQ_PRAGMA |
referer | 0xA00D | SC_REQ_REFERER |
user-agent | 0xA00E | SC_REQ_USER_AGENT |
(7) Attributes:很少用,直接看tomcat文档吧。
(8) request_terminator: 一个字节0xFF,请求结束符。
响应包数据部分(payload)结构:
[align=left]AJP13_SEND_HEADERS :=[/align] [align=left] prefix_code 4[/align] [align=left] http_status_code (integer)[/align] [align=left] http_status_msg (string)[/align] [align=left] num_headers (integer)[/align] response_headers *(res_header_name header_value) [align=left] [/align] [align=left]res_header_name :=[/align] [align=left] sc_res_header_name | (string) [see below for how this is parsed][/align] [align=left] [/align] sc_res_header_name := 0xA0 (byte) [align=left]header_value := (string)[/align] [align=left] [/align] [align=left]AJP13_SEND_BODY_CHUNK :=[/align] [align=left] prefix_code 3[/align] [align=left] chunk_length (integer)[/align] chunk *(byte) [align=left] [/align] [align=left]AJP13_END_RESPONSE :=[/align] [align=left] prefix_code 5[/align] [align=left] reuse (boolean)[/align] [align=left] [/align] [align=left]AJP13_GET_BODY_CHUNK :=[/align] [align=left] prefix_code 6[/align] [align=left] requested_length (integer)[/align] |
请求头 | Code 值 | Code 名称 |
Content-Type | 0xA001 | SC_RESP_CONTENT_TYPE |
Content-Language | 0xA002 | SC_RESP_CONTENT_LANGUAGE |
Content-Length | 0xA003 | SC_RESP_CONTENT_LENGTH |
Date | 0xA004 | SC_RESP_DATE |
Last-Modified | 0xA005 | SC_RESP_LAST_MODIFIED |
Location | 0xA006 | SC_RESP_LOCATION |
Set-Cookie | 0xA007 | SC_RESP_SET_COOKIE |
Set-Cookie2 | 0xA008 | SC_RESP_SET_COOKIE2 |
Servlet-Engine | 0xA009 | SC_RESP_SERVLET_ENGINE |
Status | 0xA00A | SC_RESP_STATUS |
WWW-Authenticate | 0xA00B | SC_RESP_WWW_AUTHENTICATE |
下面我们来看一个简单AJP请求过程中抓到的请求包:
http://localhost/test/testCluster.jsp请求:
[align=left] [/align]
1,2字节是上文所说的Server->Container包头,3,4字节表示包长度(0x01b0=432),即从第5个字节到最后的一个字节(ff)的长度。第5个字节(02)代表是”Forward Request”包。
第6个字节(02)代表是Get请求。第7,8字节(0x0008)代表protocol字符串的长度,后8个字节为protocol字符串(HTTP/1.1),第9个字节为protocol字符串的终结符“\0”。
18-41字节代表req_uri字符串(0x15+2+1=24个)。
42-53字节代表remote_addr字符串(0x09+2+1=12个)
54-55 两字节(0xffff=-1)代表null字符串,即remote_host不存在。
56-67两字节代表server_name字符串(0x09+2+1=12个)
68-69两字节(0x0050=80)代表server_port
70字节(0x00)代表is_ssl为false
71-72两字节(0x0009)代表该请求有9个请求头,如图中的前9个红色椭圆.
第10个红色椭圆(0x06)代表Attributes的route.
第11个红椭圆之后,代表AJP_REMOTE_PORT与JK_LB_ACTIVATION两个请求属性.
最后一个字节0xFF表示请求结束。
响应头数据包:
[align=left] [/align]
和请示头比较类似,不再细描述。其中第5个字节0x04代表”Send Headers”响应。
并且没有终结符字节0xFF.
响应正文数据包:
响应结束End Response:
其中最后一个字节(01),代表当前连接仍然可用。
(完) http://guojuanjun.blog.51cto.com/277646/688559/
相关文章推荐
- AJP协议总结与分析
- AJP协议总结与分析
- AJP协议总结与分析
- AJP协议总结与分析 推荐
- spice 协议相关分析总结
- QQ协议分析总结
- 协议分析总结
- 【总结】一款功能强大的协议分析软件
- [rtsp]协议UDP、TCP、RTP三种协议的总结分析
- JAVA中的网络协议,UDP,TCP案例分析及笔记总结
- OSPF协议分析(总结)
- OSPF协议分析(总结)
- Android IOS WebRTC 音视频开发总结(八十六)-- WebRTC中RTP/RTCP协议实现分析
- 应用架构设计与分析相关资料的收集、总结与复习(动态更新)
- 【分析】总结windows下堆溢出的三种利用方式
- 【总结】性能分析的几个指标(参考)
- 联众升级协议分析5
- 用协议分析工具学习TCP/IP 摘抄
- (转载)使用Perl编写协议分析脚本
- 新一代的AAA协议——Diameter分析