成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【Nginx源碼研究】Tcpdump抓包Nginx中FastCGI協(xié)議實(shí)戰(zhàn)

leone / 3138人閱讀

摘要:可以通過等方式按照協(xié)議通信。函數(shù)所需的變量在進(jìn)入該函數(shù)之前認(rèn)為已經(jīng)初始化完成。和都有自己的,且互不干涉,后續(xù)發(fā)送的序列號(hào)以此為基準(zhǔn)。

運(yùn)營研發(fā)團(tuán)隊(duì) 方波 施洪寶

一. FastCGI協(xié)議簡介 1.1 簡介

FastCGI(Fast Common Gateway Interface, 快速通用網(wǎng)關(guān)接口)是一種通信協(xié)議。可以通過Unix Domain Socket, Named Pipe, TCP等方式按照FastCGI協(xié)議通信。

圖 1.1 FastCGI簡介

1.2 數(shù)據(jù)包格式

FastCGI數(shù)據(jù)包兩部分, 頭部(header), 包體(body), 每個(gè)數(shù)據(jù)包都必須包含header, body可以沒有。header為8個(gè)字節(jié), body必須為8的整數(shù)倍, 不是的話需要填充。

1.2.1 頭部
typedef struct {
    unsigned char version;            // 版本號(hào)
    unsigned char type;               // 數(shù)據(jù)包類型
    unsigned char requestIdB1;        // 記錄id高8位
    unsigned char requestIdB0;        // 記錄id低8位
    unsigned char contentLengthB1;    // 記錄內(nèi)容長度高8位(body長度高8位)
    unsigned char contentLengthB0;    // 記錄內(nèi)容長度低8位(body長度低8位)
    unsigned char paddingLength;      // 補(bǔ)齊位長度(body補(bǔ)齊長度)
    unsigned char reserved;           // 補(bǔ)齊位
}Header;

圖 1.2 FastCGI協(xié)議數(shù)據(jù)包頭部字段說明

type的取值

#define FCGI_BEGIN_REQUEST       1                     //(web->fastcgi)請(qǐng)求開始數(shù)據(jù)包
#define FCGI_ABORT_REQUEST       2                     //(web->fastcgi)終止請(qǐng)求
#define FCGI_END_REQUEST         3                     //(fastcgi->web)請(qǐng)求結(jié)束
#define FCGI_PARAMS              4                     //(web->fastcgi)傳遞參數(shù)
#define FCGI_STDIN               5                     //(web->fastcgi)數(shù)據(jù)流傳輸數(shù)據(jù)
#define FCGI_STDOUT              6                     //(fastcgi->web)數(shù)據(jù)流傳輸數(shù)據(jù)
#define FCGI_STDERR              7                     //(fastcgi->web)數(shù)據(jù)流傳輸
#define FCGI_DATA                8                     //(web->fastcgi)數(shù)據(jù)流傳輸
#define FCGI_GET_VALUES          9                     //(web->fastcgi)查詢fastcgi服務(wù)器性能參數(shù)
#define FCGI_GET_VALUES_RESULT  10                     //(fastcgi->web)fastcgi性能參數(shù)查詢返回
#define FCGI_UNKNOWN_TYPE       11
#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
1.2.2 params類型數(shù)據(jù)包

圖 1.3 Params數(shù)據(jù)包

說明:

1.params數(shù)據(jù)包以key, value格式發(fā)送, 具體格式為(keyLen, valLen, key, val)

2.key或者val長度大于127時(shí),會(huì)用4個(gè)字節(jié)存儲(chǔ)長度,否則用一個(gè)字節(jié)

1.2.3 數(shù)據(jù)流類型數(shù)據(jù)包(stdin, stdout, stderr, data)

圖 1.4 數(shù)據(jù)流類型數(shù)據(jù)包

1.3 通信流程示例

圖 1.5 FastCGI簡單通信流程

說明:

begin request 代表請(qǐng)求開始, end request 代表請(qǐng)求結(jié)束。

除begin request, end request類型數(shù)據(jù)包外, 其他類型數(shù)據(jù)包在發(fā)送完成后,需要發(fā)送一個(gè)只有頭部,包體長度為0, 也就是沒有包體的數(shù)據(jù)包,代表這種類型的數(shù)據(jù)包發(fā)送結(jié)束。

1.4 參考

https://segmentfault.com/a/11...
https://blog.csdn.net/hepangd...

二. Nginx FastCGI

nginx發(fā)送的緩沖區(qū)數(shù)據(jù)格式如下:

圖 2.1 FastCGI數(shù)據(jù)包總體結(jié)構(gòu)圖

說明:

本部分主要依據(jù)ngx_http_fastcgi_create_request函數(shù), 該函數(shù)會(huì)構(gòu)造緩存區(qū),并向其中寫入上圖所示內(nèi)容,上述沒有考慮HTTP請(qǐng)求含有body的情況。

ngx_http_fastcgi_create_request 函數(shù)所需的變量, 在進(jìn)入該函數(shù)之前認(rèn)為已經(jīng)初始化完成。

2.1 基礎(chǔ) 2.1.1 le.ip結(jié)構(gòu)圖

fastcgi le.ip

圖 2.2 le.ip 結(jié)構(gòu)圖

2.1.2 e.ip結(jié)構(gòu)圖

圖2.3 e.ip結(jié)構(gòu)圖

2.2 ngx_http_fastcgi_create_request

該函數(shù)主要依據(jù)圖2.1, 將所需數(shù)據(jù)寫入到ngx_http_request_t對(duì)應(yīng)的ngx_http_upstream_t的緩沖區(qū)中。

寫入key, val時(shí), 通過調(diào)用相應(yīng)函數(shù)實(shí)現(xiàn), 該函數(shù)是與對(duì)應(yīng)的key, val放置在一起的, 如圖2.3所示。

//params數(shù)據(jù)包寫入核心代碼
while (*(uintptr_t *) le.ip) {
    lcode = *(ngx_http_script_len_code_pt *) le.ip;
    key_len = (u_char) lcode(&le); //獲取key的長度
    lcode = *(ngx_http_script_len_code_pt *) le.ip;
    skip_empty = lcode(&le);      //查看空時(shí)是否跳過
    for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
        lcode = *(ngx_http_script_len_code_pt *) le.ip;
    }
    le.ip += sizeof(uintptr_t);        //當(dāng)前key:value結(jié)束, le.ip后移1位
    if (skip_empty && val_len == 0) { //value為空, 并且設(shè)置空時(shí)跳過該key
        e.skip = 1;
        while (*(uintptr_t *) e.ip) {
            code = *(ngx_http_script_code_pt *) e.ip;
            code((ngx_http_script_engine_t *) &e);
        }
        e.ip += sizeof(uintptr_t);
        e.skip = 0;
        continue;
    }
    *e.pos++ = (u_char) key_len; //寫入key len 
    if (val_len > 127) {         //寫入value len
        *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
        *e.pos++ = (u_char) ((val_len >> 16) & 0xff);
        *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
        *e.pos++ = (u_char) (val_len & 0xff);
    } else {
        *e.pos++ = (u_char) val_len;
    }
    while (*(uintptr_t *) e.ip) {
        code = *(ngx_http_script_code_pt *) e.ip;
        code((ngx_http_script_engine_t *) &e);  //調(diào)用code存儲(chǔ)的處理函數(shù), 負(fù)責(zé)將key, value內(nèi)容寫入緩存, 并將e.ip后移
    }
    e.ip += sizeof(uintptr_t);                  //當(dāng)前Key:Value結(jié)束, 跳過NULL, e.ip后移一位
    ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "fastcgi param: "%*s: %*s"",
                   key_len, e.pos - (key_len + val_len),
                   val_len, e.pos - val_len);
}
三. 抓包分析 3.1 TCP三次握手
14:50:02.836252 IP bogon.46288 > localhost.cslistener: Flags [S], seq 304127093, win 29200, options [mss 1460,sackOK,TS val 105743206 ecr 0,nop,wscale 7], length 0
14:50:02.874743 IP localhost.cslistener > bogon.46288: Flags [S.], seq 15154, ack 304127094, win 32768, options [mss 1460], length 0
14:50:02.874804 IP bogon.46288 > localhost.cslistener: Flags [.], ack 15155, win 29200, length 0

代碼3.1 tcpdump三次握手

圖3.1 三次握手鏈接過程

Client發(fā)送請(qǐng)求包seq 304127093,Server返回確認(rèn)數(shù)據(jù)包ack=seq(client)+1,同時(shí)返回Server自己的seq 15154,Client收到后發(fā)送確認(rèn)包ack=seq(server)+1,建立鏈接。
Client和Server都有自己的seq,且互不干涉,后續(xù)發(fā)送的序列號(hào)以此為基準(zhǔn)。

3.2 發(fā)送數(shù)據(jù)

3.2 請(qǐng)求數(shù)據(jù)包圖2.1 Client向Server發(fā)送請(qǐng)求數(shù)據(jù)包

Mac幀頭部(14字節(jié))

IP頭部(20字節(jié))

TCP頭部(20字節(jié))

FastCGI數(shù)據(jù)包(begin request(8+ 8 = 16) + params(8 + 507 + 5 = 520) + end params(8+ 0 = 8) + stdin(8 + 0 = 8) = 552)

Params 數(shù)據(jù)包參數(shù)整理:

key len val len key val
10 4 PRODUCTION true
15 38 SCRIPT_FILENAME /home/xiaoju/webroot/default/index.php
12 0 QUERY_STRING
14 3 REQUEST_METHOD GET
12 0 CONTENT_TYPE
14 0 CONTENT_LENGTH
11 10 SCRIPT_NAME /index.php
11 1 REQUEST_URI /
12 10 DOCUMENT_URI /index.php
13 28 DOCUMENT_ROOT /home/xiaoju/webroot/default
15 8 SERVER_PROTOCOL HTTP/1.1
17 7 GATEWAY_INTERFACE CGI/1.1
15 11 SERVER_SOFTWARE nginx/1.6.2
11 9 REMOTE_ADDR 127.0.0.1
11 5 REMOTE_PORT 42282
11 9 SERVER_ADDR 127.0.0.1
11 4 SERVER_PORT 8100
11 0 SERVER_NAME
15 3 REDIRECT_STATUS 200
15 11 HTTP_USER_AGENT curl/7.29.0
9 14 HTTP_HOST localhost:8100
11 3 HTTP_ACCEPT */*

說明

stdin類型數(shù)據(jù)包長度大于32k時(shí), nginx fastcgi會(huì)進(jìn)行分包, 此時(shí)會(huì)發(fā)送多個(gè)stdin類型數(shù)據(jù)包, 發(fā)送完成后再發(fā)送stdin結(jié)束包(只有包頭,沒有包體的數(shù)據(jù)包)。

wireshark或者tcpdump抓包時(shí), 可能會(huì)出現(xiàn)某個(gè)數(shù)據(jù)包長度大于MTU, 主要是由于主機(jī)開啟TSO功能導(dǎo)致, 具體可以參考http://wsfdl.com/%E8%B8%A9%E5...

TSO進(jìn)行的是TCP分段, 不是IP分片

如果抓到的包, IP頭部, identified field is 0, 表明tcp不需分段, don"t fragment 置位1, 具體參考http://www.linuxsa.org.au/pip...

TCP頭部可選項(xiàng)含義參考https://www.jianshu.com/p/39b...

3.3 響應(yīng)包
14:50:02.913289 IP localhost.cslistener > bogon.46288: Flags [P.], seq 15155:15395, ack 304127646, win 32216, length 240
    0x0000:  0800 2701 5190 5254 0012 3500 0800 4500  ..".Q.RT..5...E.
    0x0010:  0118 02bf 0000 ff06 2fb6 0a60 7207 0a00  ......../..`r...
    0x0020:  0204 2328 b4d0 0000 3b33 1220 9e9e 5018  ..#(....;3....P.
    0x0030:  7dd8 df40 0000 0106 0001 00d8 0000 5365  }[email protected]
    0x0040:  742d 436f 6f6b 6965 3a20 5048 5053 4553  t-Cookie:.PHPSES
    0x0050:  5349 443d 6268 3174 3772 6e61 3233 716c  SID=bh1t7rna23ql
    0x0060:  6d63 6235 6d6a 686d 3967 756f 7631 3b20  mcb5mjhm9guov1;.
    0x0070:  7061 7468 3d2f 0d0a 4578 7069 7265 733a  path=/..Expires:
    0x0080:  2054 6875 2c20 3139 204e 6f76 2031 3938  .Thu,.19.Nov.198
    0x0090:  3120 3038 3a35 323a 3030 2047 4d54 0d0a  1.08:52:00.GMT..
    0x00a0:  4361 6368 652d 436f 6e74 726f 6c3a 206e  Cache-Control:.n
    0x00b0:  6f2d 7374 6f72 652c 206e 6f2d 6361 6368  o-store,.no-cach
    0x00c0:  652c 206d 7573 742d 7265 7661 6c69 6461  e,.must-revalida
    0x00d0:  7465 0d0a 5072 6167 6d61 3a20 6e6f 2d63  te..Pragma:.no-c
    0x00e0:  6163 6865 0d0a 436f 6e74 656e 742d 7479  ache..Content-ty
    0x00f0:  7065 3a20 7465 7874 2f68 746d 6c3b 2063  pe:.text/html;.c
    0x0100:  6861 7273 6574 3d55 5446 2d38 0d0a 0d0a  harset=UTF-8....
    0x0110:  646f 636b 6572 0103 0001 0008 0000 0000  docker..........
    0x0120:  0000 0064 223a                           ...d":

代碼3.2 Server向Client發(fā)送響應(yīng)數(shù)據(jù)包

Mac幀頭部(14字節(jié))

IP頭部(20字節(jié))

TCP頭部(20字節(jié))

FastCGI數(shù)據(jù)包(begin stdout(8+ 216 = 224) + end request(8+ 8 = 16) = 240)

3.4 Client發(fā)送接收Server數(shù)據(jù)的確認(rèn)包
14:50:02.913365 IP bogon.46288 > localhost.cslistener: Flags [.], ack 15395, win 30016, length 0

圖3.3 數(shù)據(jù)發(fā)送

3.5 斷開鏈接
14:50:02.913629 IP bogon.46288 > localhost.cslistener: Flags [F.], seq 304127646, ack 15395, win 30016, length 0
14:50:02.913767 IP localhost.cslistener > bogon.46288: Flags [.], ack 304127647, win 32215, length 0
14:50:02.951270 IP localhost.cslistener > bogon.46288: Flags [F.], seq 15395, ack 304127647, win 32215, length 0
14:50:02.951452 IP bogon.46288 > localhost.cslistener: Flags [.], ack 15396, win 30016, length 0

代碼3.3 tcp斷開鏈接

圖3.4 tcpdump抓包對(duì)應(yīng)的tcp流程圖

3.6 參考

https://my.oschina.net/manmao...
https://segmentfault.com/a/11...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/40175.html

相關(guān)文章

  • Nginx源碼研究NginxFastCGI淺析

    摘要:可以通過等方式按照協(xié)議通信。上述都需要發(fā)送結(jié)束包。函數(shù)所需的變量在進(jìn)入該函數(shù)之前認(rèn)為已經(jīng)初始化完成。和都有自己的,且互不干涉,后續(xù)發(fā)送的序列號(hào)以此為基準(zhǔn)。 運(yùn)營研發(fā)團(tuán)隊(duì) 施洪寶 一. FastCGI協(xié)議簡介 1.1 簡介 FastCGI(Fast Common Gateway Interface, 快速通用網(wǎng)關(guān)接口)是一種通信協(xié)議??梢酝ㄟ^Unix Domain Socket, Na...

    Taste 評(píng)論0 收藏0
  • [轉(zhuǎn)載] PHP升級(jí)導(dǎo)致系統(tǒng)負(fù)載過高問題分析

    摘要:分析的結(jié)果,發(fā)現(xiàn)內(nèi)存,基本沒有什么大的變化,網(wǎng)卡流量明顯降低,上下文切換明顯升高。網(wǎng)卡流量降低可以理解,因?yàn)楫?dāng)前系統(tǒng)已不能正常返回響應(yīng),但上下文切換升高卻不知道什么原因。 原文:http://chuansongme.com/n/797172 背景 據(jù)XX部門兄弟反應(yīng), 其在將PHP從5.3.8 升級(jí)到5.5.13 時(shí), 開始運(yùn)行正常, 運(yùn)行一段時(shí)間后, 系統(tǒng)負(fù)載變高,達(dá)到200%以...

    awokezhou 評(píng)論0 收藏0
  • 【PHP7源碼學(xué)習(xí)】2019-04-09 FastCGI協(xié)議1

    摘要:所以,它就會(huì)將端口號(hào)還有一些額外的信息被稱作首部,和應(yīng)用層下發(fā)的數(shù)據(jù)部分進(jìn)行封裝,一起傳給下一層即網(wǎng)絡(luò)層。它們之間的通信,屬于同一機(jī)器上不同端口號(hào)之間的通信。而協(xié)議傳輸?shù)膬H僅是無意義的字節(jié)流數(shù)據(jù),接收方并不能正確讀取數(shù)據(jù)的含義。 baiyan 全部視頻:https://segmentfault.com/a/11... 計(jì)算機(jī)網(wǎng)絡(luò)架構(gòu)的分層與封裝 我們經(jīng)常談到,計(jì)算機(jī)網(wǎng)絡(luò)有多種體系架構(gòu)...

    wh469012917 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<