成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

TCP三次握手,四次揮手,你真的懂嗎?

網絡 通信技術 開發工具
記得剛畢業找工作面試的時候,經常會被問到:你知道“三次握手,四次揮手”嗎?

 記得剛畢業找工作面試的時候,經常會被問到:你知道“三次握手,四次揮手”嗎?

本文來自于作者投稿,公眾號:碼農桃花源

這時候我會“胸有成竹”地“背誦”前期準備好的“答案”,第一次怎么怎么,第二次……答完后就沒有下文了,面試官貌似也沒有深入下去的意思,深入下去我也不懂,皆大歡喜!

作為程序員,要有“刨根問底”的精神,知其然,更要知其所以然。這篇文章希望能抽絲剝繭,還原背后的原理。

什么是“三次握手,四次揮手”

TCP 是一種面向連接的單播協議,在發送數據前,通信雙方必須在彼此間建立一條連接。

所謂的“連接”,其實是客戶端和服務器的內存里保存的一份關于對方的信息,如 IP 地址、端口號等。

TCP 可以看成是一種字節流,它會處理 IP 層或以下的層的丟包、重復以及錯誤問題。

在連接的建立過程中,雙方需要交換一些連接的參數。這些參數可以放在 TCP 頭部。

TCP 提供了一種可靠、面向連接、字節流、傳輸層的服務,采用三次握手建立一個連接。采用四次揮手來關閉一個連接。

TCP 服務模型

在了解了建立連接、關閉連接的“三次握手和四次揮手”后,我們再來看下 TCP 相關的東西。

一個 TCP 連接由一個 4 元組構成,分別是兩個 IP 地址和兩個端口號。一個 TCP 連接通常分為三個階段:啟動、數據傳輸、退出(關閉)。

當 TCP 接收到另一端的數據時,它會發送一個確認,但這個確認不會立即發送,一般會延遲一會兒。

ACK 是累積的,一個確認字節號 N 的 ACK 表示所有直到 N 的字節(不包括 N)已經成功被接收了。

這樣的好處是如果一個 ACK 丟失,很可能后續的 ACK 就足以確認前面的報文段了。

一個完整的 TCP 連接是雙向和對稱的,數據可以在兩個方向上平等地流動,給上層應用程序提供一種雙工服務。

一旦建立了一個連接,這個連接的一個方向上的每個 TCP 報文段都包含了相反方向上的報文段的一個 ACK。

序列號的作用是使得一個 TCP 接收端可丟棄重復的報文段,記錄以雜亂次序到達的報文段。

因為 TCP 使用 IP 來傳輸報文段,而 IP 不提供重復消除或者保證次序正確的功能。

另一方面,TCP 是一個字節流協議,絕不會以雜亂的次序給上層程序發送數據。

因此 TCP 接收端會被迫先保持大序列號的數據不交給應用程序,直到缺失的小序列號的報文段被填滿。

TCP 頭部

源端口和目的端口在 TCP 層確定雙方進程,序列號表示的是報文段數據中的第一個字節號,ACK 表示確認號。

該確認號的發送方期待接收的下一個序列號,即最后被成功接收的數據字節序列號加 1,這個字段只有在 ACK 位被啟用的時候才有效。

當新建一個連接時,從客戶端發送到服務端的第一個報文段的 SYN 位被啟用,這稱為 SYN 報文段。

這時序列號字段包含了在本次連接的這個方向上要使用的第一個序列號,即初始序列號 ISN,之后發送的數據是 ISN 加 1。

因此 SYN 位字段會消耗一個序列號。這意味著使用重傳進行可靠傳輸,而不消耗序列號的 ACK 則不是。

頭部長度(圖中的數據偏移)以 32 位字為單位,也就是以 4bytes 為單位,它只有 4 位,最大為 15,因此頭部最大長度為 60 字節,而其最小為 5,也就是頭部最小為 20 字節(可變選項為空)。

  • ACK —— 確認,使得確認號有效。
  • RST —— 重置連接(經常看到的 reset by peer)就是此字段搞的鬼。
  • SYN —— 用于初如化一個連接的序列號。
  • FIN —— 該報文段的發送方已經結束向對方發送數據。

當一個連接被建立或被終止時,交換的報文段只包含 TCP 頭部,而沒有數據。

狀態轉換

三次握手和四次揮手的狀態轉換如下圖:

為什么要“三次握手,四次揮手”

三次握手

換個易于理解的視角來看為什么要三次握手。

客戶端和服務端通信前要進行連接,“三次握手”的作用就是雙方都能明確自己和對方的收、發能力是正常的。

第一次握手:客戶端發送網絡包,服務端收到了。這樣服務端就能得出結論:客戶端的發送能力、服務端的接收能力是正常的。

第二次握手:服務端發包,客戶端收到了。這樣客戶端就能得出結論:服務端的接收、發送能力,客戶端的接收、發送能力是正常的。

從客戶端的視角來看,我接到了服務端發送過來的響應數據包,說明服務端接收到了我在第一次握手時發送的網絡包,并且成功發送了響應數據包,這就說明,服務端的接收、發送能力正常。

而另一方面,我收到了服務端的響應數據包,說明我第一次發送的網絡包成功到達服務端,這樣,我自己的發送和接收能力也是正常的。

第三次握手:客戶端發包,服務端收到了。這樣服務端就能得出結論:客戶端的接收、發送能力,服務端的發送、接收能力是正常的。

第一、二次握手后,服務端并不知道客戶端的接收能力以及自己的發送能力是否正常。

而在第三次握手時,服務端收到了客戶端對第二次握手作的回應。從服務端的角度,我在第二次握手時的響應數據發送出去了,客戶端接收到了。所以,我的發送能力是正常的。而客戶端的接收能力也是正常的。

經歷了上面的三次握手過程,客戶端和服務端都確認了自己的接收、發送能力是正常的。之后就可以正常通信了。

每次都是接收到數據包的一方可以得到一些結論,發送的一方其實沒有任何頭緒。

我雖然有發包的動作,但是我怎么知道我有沒有發出去,而對方有沒有接收到呢?

而從上面的過程可以看到,最少是需要三次握手過程的。兩次達不到讓雙方都得出自己、對方的接收、發送能力都正常的結論。

其實每次收到網絡包的一方至少是可以得到:對方的發送、我方的接收是正常的。

而每一步都是有關聯的,下一次的“響應”是由于第一次的“請求”觸發,因此每次握手其實是可以得到額外的結論的。

比如第三次握手時,服務端收到數據包,表明看服務端只能得到客戶端的發送能力、服務端的接收能力是正常的。

但是結合第二次,說明服務端在第二次發送的響應包,客戶端接收到了,并且作出了響應,從而得到額外的結論:客戶端的接收、服務端的發送是正常的。

用表格總結一下:

四次揮手

TCP 連接是雙向傳輸的對等的模式,就是說雙方都可以同時向對方發送或接收數據。

當有一方要關閉連接時,會發送指令告知對方,我要關閉連接了。這時對方會回一個 ACK,此時一個方向的連接關閉。

但是另一個方向仍然可以繼續傳輸數據,等到發送完了所有的數據后,會發送一個 FIN 段來關閉此方向上的連接。接收方發送 ACK 確認關閉連接。

注意,接收到 FIN 報文的一方只能回復一個 ACK, 它是無法馬上返回對方一個 FIN 報文段的,因為結束數據傳輸的“指令”是上層應用層給出的,我只是一個“搬運工”,我無法了解“上層的意志”。

“三次握手,四次揮手”怎么完成?

其實三次握手的目的并不只是讓通信雙方都了解到一個連接正在建立,還在于利用數據包的選項來傳輸特殊的信息,交換初始序列號 ISN。

三次握手是指發送了 3 個報文段,四次揮手是指發送了 4 個報文段。注意,SYN 和 FIN 段都是會利用重傳進行可靠傳輸的。

三次握手原理:

  • 客戶端發送一個 SYN 段,并指明客戶端的初始序列號,即 ISN(c)。
  • 服務端發送自己的 SYN 段作為應答,同樣指明自己的 ISN(s)。為了確認客戶端的 SYN,將 ISN(c)+1 作為 ACK 數值。這樣,每發送一個 SYN,序列號就會加 1,如果有丟失的情況,則會重傳。
  • 為了確認服務器端的 SYN,客戶端將 ISN(s)+1 作為返回的 ACK 數值。

四次揮手原理:

  • 客戶端發送一個 FIN 段,并包含一個希望接收者看到的自己當前的序列號 K。同時還包含一個 ACK 表示確認對方最近一次發過來的數據。
  • 服務端將 K 值加 1 作為 ACK 序號值,表明收到了上一個包。這時上層的應用程序會被告知另一端發起了關閉操作,通常這將引起應用程序發起自己的關閉操作。
  • 服務端發起自己的 FIN 段,ACK=K+1, Seq=L。
  • 客戶端確認。ACK=L+1

為什么建立連接是三次握手,而關閉連接卻是四次揮手呢?這是因為服務端在 LISTEN 狀態下,收到建立連接請求的 SYN 報文后,把 ACK 和 SYN 放在一個報文里發送給客戶端。

而關閉連接時,當收到對方的 FIN 報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方是否現在關閉發送數據通道,需要上層應用來決定,因此,己方 ACK 和 FIN 一般都會分開發送。

“三次握手,四次揮手”進階

ISN

三次握手的一個重要功能是客戶端和服務端交換 ISN(Initial Sequence Number), 以便讓對方知道接下來接收數據的時候如何按序列號組裝數據。

如果 ISN 是固定的,攻擊者很容易猜出后續的確認號:

  1. ISN = M + F(localhost, localport, remotehost, remoteport) 

M 是一個計時器,每隔 4 毫秒加 1。F 是一個 Hash 算法,根據源 IP、目的 IP、源端口、目的端口生成一個隨機數值。要保證 Hash 算法不能被外部輕易推算得出。

序列號回繞

因為 ISN 是隨機的,所以序列號容易就會超過 2^31-1。而 TCP 對于丟包和亂序等問題的判斷都是依賴于序列號大小比較的。

此時就出現了所謂的 TCP 序列號回繞(sequence wraparound)問題怎么解決?

  1. /* 
  2. * The next routines deal with comparing 32 bit unsigned ints 
  3. and worry about wraparound (automatic with unsigned arithmetic). 
  4. */ 
  5. static inline int before(__u32 seq1, __u32 seq2) 
  6.     return (__s32)(seq1-seq2) < 0; 
  7.  
  8. #define after(seq2, seq1) before(seq1, seq2) 

上述代碼是內核中的解決回繞問題代碼。__s32 是有符號整型的意思,而 __u32 則是無符號整型。

序列號發生回繞后,序列號變小,相減之后,把結果變成有符號數了,因此結果成了負數。

  1. 假設seq1=255, seq2=1(發生了回繞)。 
  2. seq1 = 1111 1111 seq2 = 0000 0001 
  3. 我們希望比較結果是 
  4. seq1 - seq2= 
  5. 1111 1111 
  6. -0000 0001 
  7. ----------- 
  8. 1111 1110 
  9.  
  10. 由于我們將結果轉化成了有符號數,由于最高位是1,因此結果是一個負數,負數的絕對值為 
  11. 0000 0001 + 1 = 0000 0010 = 2 
  12.  
  13. 因此seq1 - seq2 < 0 

SYN Flood 攻擊

最基本的 DoS 攻擊就是利用合理的服務請求來占用過多的服務資源,從而使合法用戶無法得到服務的響應。SYN Flood 屬于 Dos 攻擊的一種。

如果惡意的向某個服務器端口發送大量的 SYN 包,則可以使服務器打開大量的半開連接,分配 TCB(Transmission Control Block), 從而消耗大量的服務器資源,同時也使得正常的連接請求無法被響應。

當開放了一個 TCP 端口后,該端口就處于 Listening 狀態,不停地監視發到該端口的 SYN 報文,一 旦接收到 Client 發來的 SYN 報文,就需要為該請求分配一個 TCB。

通常一個 TCB 至少需要 280 個字節,在某些操作系統中 TCB 甚至需要 1300 個字節,并返回一個 SYN ACK 命令,立即轉為 SYN-RECEIVED 即半開連接狀態,系統會為此耗盡資源。常見的防攻擊方法有:

①無效連接的監視釋放

監視系統的半開連接和不活動連接,當達到一定閾值時拆除這些連接,從而釋放系統資源。

這種方法對于所有的連接一視同仁,而且由于 SYN Flood 造成的半開連接數量很大,正常連接請求也被淹沒在其中被這種方式誤釋放掉,因此這種方法屬于入門級的 SYN Flood 方法。

②延緩 TCB 分配方法

消耗服務器資源主要是因為當 SYN 數據報文一到達,系統立即分配 TCB,從而占用了資源。

而 SYN Flood 由于很難建立起正常連接,因此,當正常連接建立起來后再分配 TCB 則可以有效地減輕服務器資源的消耗。常見的方法是使用 Syn Cache 和 Syn Cookie 技術。

③Syn Cache 技術

系統在收到一個 SYN 報文時,在一個專用 Hash 表中保存這種半連接信息,直到收到正確的回應 ACK 報文再分配 TCB。這個開銷遠小于 TCB 的開銷。當然還需要保存序列號。

④Syn Cookie 技術

Syn Cookie 技術則完全不使用任何存儲資源,這種方法比較巧妙,它使用一種特殊的算法生成 Sequence Number。

這種算法考慮到了對方的 IP、端口、己方 IP、端口的固定信息,以及對方無法知道而己方比較固定的一些信息。

如 MSS(Maximum Segment Size,最大報文段大小,指的是 TCP 報文的最大數據報長度,其中不包括 TCP 首部長度。)、時間等。

在收到對方的 ACK 報文后,重新計算一遍,看其是否與對方回應報文中的(Sequence Number-1)相同,從而決定是否分配 TCB 資源。

⑤使用 SYN Proxy 防火墻

一種方式是防止墻 dqywb 連接的有效性后,防火墻才會向內部服務器發起 SYN 請求。

防火墻代服務器發出的 SYN ACK 包使用的序列號為 c, 而真正的服務器回應的序列號為 c',。

這樣,在每個數據報文經過防火墻的時候進行序列號的修改。另一種方式是防火墻確定了連接的安全后,會發出一個 safe reset 命令,Client 會進行重新連接,這時出現的 SYN 報文會直接放行。

這樣不需要修改序列號了。但是,Client 需要發起兩次握手過程,因此建立連接的時間將會延長。

連接隊列

在外部請求到達時,被服務程序最終感知到前,連接可能處于 SYN_RCVD 狀態或是 ESTABLISHED 狀態,但還未被應用程序接受。

對應地,服務器端也會維護兩種隊列,處于 SYN_RCVD 狀態的半連接隊列,而處于 ESTABLISHED 狀態但仍未被應用程序 Accept 的為全連接隊列。

如果這兩個隊列滿了之后,就會出現各種丟包的情形:

  1. 查看是否有連接溢出 
  2. netstat -s | grep LISTEN 

半連接隊列滿了

在三次握手協議中,服務器維護一個半連接隊列,該隊列為每個客戶端的 SYN 包開設一個條目(服務端在接收到 SYN 包的時候,就已經創建了request_sock結構,存儲在半連接隊列中)。

該條目表明服務器已收到 SYN 包,并向客戶發出確認,正在等待客戶的確認包。

這些條目所標識的連接在服務器處于 Syn_RECV 狀態,當服務器收到客戶的確認包時,刪除該條目,服務器進入 ESTABLISHED 狀態。

目前,Linux 下默認會進行 5 次重發 SYN-ACK 包,重試的間隔時間從 1s 開始,下次的重試間隔時間是前一次的雙倍,5 次的重試時間間隔為 1s, 2s, 4s, 8s, 16s, 總共 31s,稱為指數退避。

第 5 次發出后還要等 32s 才知道第 5 次也超時了,所以,總共需要 1s + 2s + 4s + 8s + 16s + 32s = 63s,TCP 才會斷開這個連接。

由于,SYN 超時需要 63 秒,那么就給攻擊者一個攻擊服務器的機會,攻擊者在短時間內發送大量的 SYN 包給 Server(俗稱 SYN Flood 攻擊),用于耗盡 Server 的 SYN 隊列。

對于應對 SYN 過多的問題,Linux 提供了幾個 TCP 參數來調整應對:

  • tcp_syncookies
  • tcp_synack_retries
  • tcp_max_syn_backlog
  • tcp_abort_on_overflow

全連接隊列滿了

當第三次握手時,當 Server 接收到 ACK 包之后,會進入一個新的叫 Accept 的隊列。

當 Accept 隊列滿了之后,即使 Client 繼續向 Server 發送 ACK 的包,也會不被響應。

此時 ListenOverflows+1,同時 Server 通過 tcp_abort_on_overflow 來決定如何返回,0 表示直接丟棄該 ACK,1 表示發送 RST 通知 Client。

相應的,Client 則會分別返回 read timeout 或者 connection reset by peer。

另外,tcp_abort_on_overflow 是 0 的話,Server 過一段時間再次發送 SYN+ACK 給 Client(也就是重新走握手的第二步),如果 Client 超時等待比較短,就很容易異常了。

而客戶端收到多個 SYN ACK 包,則會認為之前的 ACK 丟包了。于是促使客戶端再次發送 ACK ,在 Accept 隊列有空閑的時候最終完成連接。

若 Accept 隊列始終滿員,則最終客戶端收到 RST 包(此時服務端發送 SYN+ACK 的次數超出了 tcp_synack_retries)。

服務端僅僅只是創建一個定時器,以固定間隔重傳 SYN 和 ACK 到服務端:

命令

  1. [root@server ~]#  netstat -s | egrep "listen|LISTEN" 
  2. 667399 times the listen queue of a socket overflowed 
  3. 667399 SYNs to LISTEN sockets ignored 

上面看到的 667399 times ,表示全連接隊列溢出的次數,隔幾秒鐘執行下,如果這個數字一直在增加的話肯定全連接隊列偶爾滿了。

查看 Accept queue 是否有溢出:

  1. [root@server ~]#  netstat -s | grep TCPBacklogDrop 

ss 命令:

  1. [root@server ~]#  ss -lnt 
  2. State Recv-Q Send-Q Local Address:Port Peer Address:Port 
  3. LISTEN     0      128 *:6379 *:* 
  4. LISTEN     0      128 *:22 *:* 

如果 State 是 Listen 狀態,Send-Q 表示第三列的 Listen 端口上的全連接隊列最大為 50,第一列 Recv-Q 為全連接隊列當前使用了多少。

非 LISTEN 狀態中 Recv-Q 表示 receive queue 中的 bytes 數量;Send-Q 表示 send queue 中的 bytes 數值。

小結:當外部連接請求到來時,TCP 模塊會首先查看 max_syn_backlog,如果處于 SYN_RCVD 狀態的連接數目超過這一閾值,進入的連接會被拒絕。

根據 tcp_abort_on_overflow 字段來決定是直接丟棄,還是直接 reset。

從服務端來說,三次握手中,第一步 Server 接受到 Client 的 SYN 后,把相關信息放到半連接隊列中,同時回復 SYN+ACK 給 Client。第三步當收到客戶端的 ACK,將連接加入到全連接隊列。

一般,全連接隊列比較小,會先滿,此時半連接隊列還沒滿。如果這時收到 SYN 報文,則會進入半連接隊列,沒有問題。

但是如果收到了三次握手中的第 3 步(ACK),則會根據 tcp_abort_on_overflow 字段來決定是直接丟棄,還是直接 reset。

此時,客戶端發送了 ACK, 那么客戶端認為三次握手完成,它認為服務端已經準備好了接收數據的準備。

但此時服務端可能因為全連接隊列滿了而無法將連接放入,會重新發送第 2 步的 SYN+ACK,如果這時有數據到來,服務器 TCP 模塊會將數據存入隊列中。

一段時間后,Client 端沒收到回復,超時,連接異常,Client 會主動關閉連接。

“三次握手,四次揮手”Redis 實例分析

①我在 dev 機器上部署 Redis 服務,端口號為 6379,通過 tcpdump 工具獲取數據包,使用如下命令:

  1. tcpdump -w /tmp/a.cap port 6379 -s0 
  2. -w把數據寫入文件,-s0設置每個數據包的大小默認為68字節,如果用-S0則會抓到完整數據包 

②在 dev2 機器上用 redis-cli 訪問 dev:6379, 發送一個 ping, 得到回復 pong,停止抓包,用 tcpdump 讀取捕獲到的數據包:

  1. tcpdump -r /tmp/a.cap -n -nn -A -x| vim - 
  2. (-x 以16進制形式展示,便于后面分析) 

共收到了 7 個包。

抓到的是 IP 數據包,IP 數據包分為 IP 頭部和 IP 數據部分,IP 數據部分是 TCP 頭部加 TCP 數據部分。

IP 的數據格式為:

它由固定長度 20B+ 可變長度構成。

 

對著 IP 頭部格式,來拆解數據包的具體含義。

剩余的數據部分即為 TCP 協議相關的。TCP 也是 20B 固定長度+可變長度部分。

可變長度部分,協議如下:

這樣第一個包分析完了。dev2 向 dev 發送 SYN 請求。也就是三次握手中的第一次了。

  1. SYN seq(c)=4133153791 

第二個包,dev 響應連接,ack=4133153792。表明 dev 下次準備接收這個序號的包,用于 tcp 字節注的順序控制。dev(也就是 server 端)的初始序號為 seq=4264776963, syn=1。

  1. SYN ack=seq(c)+1 seq(s)=4264776963 

第三個包,client 包確認,這里使用了相對值應答。seq=4133153792,等于第二個包的 ack. ack=4264776964。

  1. ack=seq(s)+1, seq=seq(c)+1 

至此,三次握手完成。接下來就是發送 ping 和 pong 的數據了。

接著第四個包:

tcp 首部長度為 32B,可選長度為 12B。IP 報文的總長度為 66B,首部長度為 20B,因此 TCP 數據部分長度為 14B. seq=0xf65a ec00=4133153792。

ACK, PSH. 數據部分為 2a31 0d0a 2434 0d0a 7069 6e67 0d0a:

  1. 0x2a31         -> *1 
  2. 0x0d0a         -> \r\n 
  3. 0x2434         -> $4 
  4. 0x0d0a         -> \r\n 
  5. 0x7069 0x6e67  -> ping 
  6. 0x0d0a         -> \r\n 

dev2 向 dev 發送了 ping 數據,第四個包完畢。第五個包,dev2 向 dev 發送 ack 響應。

序列號為 0xfe33 5504=4264776964,ack 確認號為 0xf65a ec0e=4133153806=(4133153792+14)。

第六個包,dev 向 dev2 響應 pong 消息。序列號 fe33 5504,確認號 f65a ec0e,TCP 頭部可選長度為 12B,IP 數據報總長度為 59B,首部長度為 20B,因此 TCP 數據長度為 7B。

數據部分 2b50 4f4e 470d 0a,翻譯過來就是+PONG\r\n。至此,Redis 客戶端和 Server 端的三次握手過程分析完畢。

總結

“三次握手,四次揮手”看似簡單,但是深究進去,還是可以延伸出很多知識點的,比如半連接隊列、全連接隊列等等。

以前關于 TCP 建立連接、關閉連接的過程很容易就會忘記,可能是因為只是死記硬背了幾個過程,沒有深入研究背后的原理。所以,“三次握手,四次揮手”你真的懂了嗎?

 

 

責任編輯:武曉燕 來源: 碼農桃花源
相關推薦

2023-10-17 15:44:19

TCP四次揮手

2015-10-13 09:42:52

TCP網絡協議

2019-06-12 11:26:37

TCP三次握手四次揮手

2023-10-24 15:22:09

TCPUDP

2024-01-12 08:23:11

TCPACK服務器

2021-07-03 17:47:25

TCP控制協議

2025-05-29 08:39:24

三次握手四次揮手TCP

2021-01-29 06:11:08

TCP通信三次握手

2021-05-18 12:27:40

TCP控制協議

2020-02-17 10:10:43

TCP三次握手四次揮手

2017-09-25 21:27:07

TCP協議數據鏈

2023-03-07 08:38:23

三次握手四次揮手服務端

2021-05-28 09:08:20

TCP連接序列號

2020-06-29 14:50:47

TCP狀態ACK

2025-05-20 08:38:03

2015-11-09 09:58:56

2023-10-28 09:07:57

TCP面試三次握手

2022-11-17 10:20:49

TCP三次握手四次揮手

2014-09-19 09:46:46

TCPIP

2023-11-01 08:04:08

WiresharkTCP協議
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久99 | 国产精品中文字幕在线播放 | 在线免费观看黄色 | 国产成人精品网站 | 久久婷婷色 | 成人中文字幕av | 91久久久www播放日本观看 | 国产在线精品一区二区三区 | 久久精品综合 | 中文字幕视频在线观看 | 亚洲最大的成人网 | 亚洲欧美成人 | 天天插日日操 | 亚洲一区二区三区乱码aⅴ 四虎在线视频 | 人人澡人人爱 | 91久久国产综合久久 | 精品国产黄a∨片高清在线 成人区精品一区二区婷婷 日本一区二区视频 | 九七午夜剧场福利写真 | 四虎影院免费在线 | 欧美一区二区三区 | 999免费观看视频 | 久久er99热精品一区二区 | 日韩欧美不卡 | 国产综合久久久久久鬼色 | 妞干网av | 亚洲a网| 欧美成人综合 | 天天拍天天操 | 免费在线看黄 | 欧美福利网站 | 日日欧美 | 亚洲一区在线日韩在线深爱 | 国产综合精品一区二区三区 | 中文一区二区 | 国产精品一区二区三 | 精品二区| 国产精品一区二区在线 | 好姑娘影视在线观看高清 | 久久久久久久久久久丰满 | 在线一区 | 伊人精品一区二区三区 |