<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手工模擬實(shí)現(xiàn) Docker 容器網(wǎng)絡(luò)!

          共 7516字,需瀏覽 16分鐘

           ·

          2021-11-19 02:25

          ????關(guān)注后回復(fù)?“進(jìn)群”?,拉你進(jìn)程序員交流群????


          作者丨張彥飛allen

          來(lái)源丨開發(fā)內(nèi)功修煉


          大家好,我是飛哥!


          如今服務(wù)器虛擬化技術(shù)已經(jīng)發(fā)展到了深水區(qū)。現(xiàn)在業(yè)界已經(jīng)有很多公司都遷移到容器上了。我們的開發(fā)寫出來(lái)的代碼大概率是要運(yùn)行在容器上的。因此深刻理解容器網(wǎng)絡(luò)的工作原理非常的重要。這有這樣將來(lái)遇到問(wèn)題的時(shí)候才知道該如何下手處理。

          網(wǎng)絡(luò)虛擬化,其實(shí)用一句話來(lái)概括就是用軟件來(lái)模擬實(shí)現(xiàn)真實(shí)的物理網(wǎng)絡(luò)連接。比如 Docker 就是用純軟件的方式在宿主機(jī)上模擬出來(lái)的獨(dú)立網(wǎng)絡(luò)環(huán)境。我們今天來(lái)徒手打造一個(gè)虛擬網(wǎng)絡(luò),實(shí)現(xiàn)在這個(gè)網(wǎng)絡(luò)里訪問(wèn)外網(wǎng)資源,同時(shí)監(jiān)聽端口提供對(duì)外服務(wù)的功能。


          看完這一篇后,相信你對(duì) Docker 虛擬網(wǎng)絡(luò)能有進(jìn)一步的理解。好了,我們開始!

          一、基礎(chǔ)知識(shí)回顧

          1.1 veth、bridge 與 namespace

          Linux 下的 veth 是一對(duì)兒虛擬網(wǎng)卡設(shè)備,和我們常見的 lo 很類似。在這兒設(shè)備里,從一端發(fā)送數(shù)據(jù)后,內(nèi)核會(huì)尋找該設(shè)備的另一半,所以在另外一端就能收到。不過(guò) veth 只能解決一對(duì)一通信的問(wèn)題。

          如果有很多對(duì)兒 veth 需要互相通信的話,就需要引入 bridge 這個(gè)虛擬交換機(jī)。各個(gè) veth 對(duì)兒可以把一頭連接在 bridge 的接口上,bridge 可以和交換機(jī)一樣在端口之間轉(zhuǎn)發(fā)數(shù)據(jù),使得各個(gè)端口上的 veth 都可以互相通信。參見

          Namespace 解決的是隔離性的問(wèn)題。每個(gè)虛擬網(wǎng)卡設(shè)備、進(jìn)程、socket、路由表等等網(wǎng)絡(luò)棧相關(guān)的對(duì)象默認(rèn)都是歸屬在 init_net 這個(gè)缺省的 namespace 中的。不過(guò)我們希望不同的虛擬化環(huán)境之間是隔離的,用 Docker 來(lái)舉例,那就是不能讓 A 容器用到 B 容器的設(shè)備、路由表、socket 等資源,甚至連看一眼都不可以。只有這樣才能保證不同的容器之間復(fù)用資源的同時(shí),還不會(huì)影響其它容器的正常運(yùn)行。參見

          通過(guò) veth、namespace 和 bridge 我們?cè)谝慌_(tái) Linux 上就能虛擬多個(gè)網(wǎng)絡(luò)環(huán)境出來(lái)。而且它們之間、和宿主機(jī)之間都可以互相通信。


            還拿 Docker 容器來(lái)舉例,你啟動(dòng)的容器里的服務(wù)肯定是需要訪問(wèn)外部的數(shù)據(jù)庫(kù)的。還有就是可能需要暴露比如 80 端口對(duì)外提供服務(wù)。例如在 Docker 中我們通過(guò)下面的命令將容器的 80 端口上的 web 服務(wù)要能被外網(wǎng)訪問(wèn)的到。

            我們今天的文章主要就是解決這兩個(gè)問(wèn)題的,一是從虛擬網(wǎng)絡(luò)中訪問(wèn)外網(wǎng),二是在虛擬網(wǎng)絡(luò)中提供服務(wù)供外網(wǎng)使用。解決它們需要用到路由nat 技術(shù)。

            1.2 路由選擇

            Linux 是在發(fā)送數(shù)據(jù)包的時(shí)候,會(huì)涉及到路由過(guò)程。這個(gè)發(fā)送數(shù)據(jù)包既包括本機(jī)發(fā)送數(shù)據(jù)包,也包括途徑當(dāng)前機(jī)器的數(shù)據(jù)包的轉(zhuǎn)發(fā)。

            先來(lái)看本機(jī)發(fā)送數(shù)據(jù)包。

            所謂路由其實(shí)很簡(jiǎn)單,就是該選擇哪張網(wǎng)卡(虛擬網(wǎng)卡設(shè)備也算)將數(shù)據(jù)寫進(jìn)去。到底該選擇哪張網(wǎng)卡呢,規(guī)則都是在路由表中指定的。Linux 中可以有多張路由表,最重要和常用的是 local 和 main。

            local 路由表中統(tǒng)一記錄本地,確切的說(shuō)是本網(wǎng)絡(luò)命名空間中的網(wǎng)卡設(shè)備 IP 的路由規(guī)則。

            #ip?route?list?table?local
            local?10.143.x.y?dev?eth0?proto?kernel?scope?host?src?10.143.x.y
            local?127.0.0.1?dev?lo?proto?kernel?scope?host?src?127.0.0.1

            其它的路由規(guī)則,一般都是在 main 路由表中記錄著的。

            再看途徑當(dāng)前機(jī)器的數(shù)據(jù)包的轉(zhuǎn)發(fā)。除了本機(jī)發(fā)送以外,轉(zhuǎn)發(fā)也會(huì)涉及路由過(guò)程。如果 Linux 收到數(shù)據(jù)包以后發(fā)現(xiàn)目的地址并不是本地的地址的話,就可以選擇把這個(gè)數(shù)據(jù)包從自己的某個(gè)網(wǎng)卡設(shè)備上轉(zhuǎn)發(fā)出去。這個(gè)時(shí)候和本機(jī)發(fā)送一樣,也需要讀取路由表。根據(jù)路由表的配置來(lái)選擇從哪個(gè)設(shè)備將包轉(zhuǎn)走。

            不過(guò)值得注意的是,Linux 上轉(zhuǎn)發(fā)功能默認(rèn)是關(guān)閉的。也就是發(fā)現(xiàn)目的地址不是本機(jī) IP 地址默認(rèn)是將包直接丟棄。需要做一些簡(jiǎn)單的配置,然后 Linux 才可以干像路由器一樣的活兒,實(shí)現(xiàn)數(shù)據(jù)包的轉(zhuǎn)發(fā)。

            1.3 iptables 與 NAT

            Linux 內(nèi)核網(wǎng)絡(luò)棧在運(yùn)行上基本上是一個(gè)純內(nèi)核態(tài)的東西,但為了迎合各種各樣用戶層不同的需求,內(nèi)核開放了一些口子出來(lái)供用戶層來(lái)干預(yù)。其中 iptables 就是一個(gè)非常常用的干預(yù)內(nèi)核行為的工具,它在內(nèi)核里埋下了五個(gè)鉤子入口,這就是俗稱的五鏈。

            Linux 在接收數(shù)據(jù)的時(shí)候,在 IP 層進(jìn)入 ip_rcv 中處理。再執(zhí)行路由判斷,發(fā)現(xiàn)是本機(jī)的話就進(jìn)入 ip_local_deliver 進(jìn)行本機(jī)接收,最后送往 TCP 協(xié)議層。在這個(gè)過(guò)程中,埋了兩個(gè) HOOK,第一個(gè)是 PRE_ROUTING。這段代碼會(huì)執(zhí)行到 iptables 中 pre_routing 里的各種表。發(fā)現(xiàn)是本地接收后接著又會(huì)執(zhí)行到 LOCAL_IN,這會(huì)執(zhí)行到 iptables 中配置的 input 規(guī)則。

            在發(fā)送數(shù)據(jù)的時(shí)候,查找路由表找到出口設(shè)備后,依次通過(guò) __ip_local_out、 ip_output 等函數(shù)將包送到設(shè)備層。在這兩個(gè)函數(shù)中分別過(guò)了 OUTPUT 和 PREROUTING 開的各種規(guī)則。

            如果是轉(zhuǎn)發(fā)過(guò)程,Linux 收到數(shù)據(jù)包發(fā)現(xiàn)不是本機(jī)的包可以通過(guò)查找自己的路由表找到合適的設(shè)備把它轉(zhuǎn)發(fā)出去。那就先是在 ip_rcv 中將包送到 ip_forward 函數(shù)中處理,最后在 ip_output 函數(shù)中將包轉(zhuǎn)發(fā)出去。在這個(gè)過(guò)程中分別過(guò)了 PREROUTING、FORWARD 和 POSTROUTING 三個(gè)規(guī)則。

            綜上所述,iptables 里的五個(gè)鏈在內(nèi)核網(wǎng)絡(luò)模塊中的位置就可以歸納成如下這幅圖。

            數(shù)據(jù)接收過(guò)程走的是 1 和 2,發(fā)送過(guò)程走的是 4 、5,轉(zhuǎn)發(fā)過(guò)程是 1、3、5。有了這張圖,我們能更清楚地理解 iptable 和內(nèi)核的關(guān)系。

            在 iptables 中,根據(jù)實(shí)現(xiàn)的功能的不同,又分成了四張表。分別是 raw、mangle、nat 和 filter。其中 nat 表實(shí)現(xiàn)我們常說(shuō)的 NAT(Network AddressTranslation) 功能。其中 nat 又分成 SNAT(Source NAT)和 DNAT(Destination NAT)兩種。

            SNAT 解決的是內(nèi)網(wǎng)地址訪問(wèn)外部網(wǎng)絡(luò)的問(wèn)題。它是通過(guò)在 POSTROUTING 里修改來(lái)源 IP 來(lái)實(shí)現(xiàn)的。

            DNAT 解決的是內(nèi)網(wǎng)的服務(wù)要能夠被外部訪問(wèn)到的問(wèn)題。它在通過(guò) PREROUTING 修改目標(biāo) IP 實(shí)現(xiàn)的。

            二、 實(shí)現(xiàn)虛擬網(wǎng)絡(luò)外網(wǎng)通信

            基于以上的基礎(chǔ)知識(shí),我們用純手工的方式搭建一個(gè)可以和 Docker 類似的虛擬網(wǎng)絡(luò)。而且要實(shí)現(xiàn)和外網(wǎng)通信的功能。

            1. 實(shí)驗(yàn)環(huán)境準(zhǔn)備

            我們先來(lái)創(chuàng)建一個(gè)虛擬的網(wǎng)絡(luò)環(huán)境出來(lái),其命名空間為 net1。宿主機(jī)的 IP 是 10.162 的網(wǎng)段,可以訪問(wèn)外部機(jī)器。虛擬網(wǎng)絡(luò)為其分配 192.168.0 的網(wǎng)段,這個(gè)網(wǎng)段是私有的,外部機(jī)器無(wú)法識(shí)別。

            這個(gè)虛擬網(wǎng)絡(luò)的搭建過(guò)程如下。先創(chuàng)建一個(gè) netns 出來(lái),命名為 net1。

            #?ip?netns?add?net1

            創(chuàng)建一個(gè) veth 對(duì)兒(veth1 - veth1_p),把其中的一頭 veth1 放在 net1 中,給它配置上 IP,并把它啟動(dòng)起來(lái)。

            #?ip?link?add?veth1?type?veth?peer?name?veth1_p
            #?ip?link?set?veth1?netns?net1
            #?ip?netns?exec?net1?ip?addr?add?192.168.0.2/24?dev?veth1??#?IP
            #?ip?netns?exec?net1?ip?link?set?veth1?up

            創(chuàng)建一個(gè) bridge,給它也設(shè)置上 ip。接下來(lái)把 veth 的另外一端 veth1_p 插到 bridge 上面。最后把網(wǎng)橋和 veth1_p 都啟動(dòng)起來(lái)。

            #?brctl?addbr?br0
            #?ip?addr?add?192.168.0.1/24?dev?br0
            #?ip?link?set?dev?veth1_p?master?br0
            #?ip?link?set?veth1_p?up
            #?ip?link?set?br0?up

            這樣我們就在 Linux 上創(chuàng)建出了一個(gè)虛擬的網(wǎng)絡(luò)。

            2. 請(qǐng)求外網(wǎng)資源

            現(xiàn)在假設(shè)我們上面的 net1 這個(gè)網(wǎng)絡(luò)環(huán)境中想訪問(wèn)外網(wǎng)。這里的外網(wǎng)是指的虛擬網(wǎng)絡(luò)宿主機(jī)外部的網(wǎng)絡(luò)。

            我們假設(shè)它要訪問(wèn)的另外一臺(tái)機(jī)器 IP 是 10.153.*.* ,這個(gè) 10.153.*.* 后面兩段由于是我的內(nèi)部網(wǎng)絡(luò),所以隱藏起來(lái)了。你在實(shí)驗(yàn)的過(guò)程中,用自己的 IP 代替即可。

            我們直接來(lái)訪問(wèn)一下試試

            #?ip?netns?exec?net1?ping?10.153.*.*
            connect:?Network?is?unreachable

            提示網(wǎng)絡(luò)不通,這是怎么回事?用這段報(bào)錯(cuò)關(guān)鍵字在內(nèi)核源碼里搜索一下:

            //file:?arch/parisc/include/uapi/asm/errno.h
            #define?ENETUNREACH?229?/*?Network?is?unreachable?*/

            //file:?net/ipv4/ping.c
            static?int?ping_sendmsg(struct?kiocb?*iocb,?struct?sock?*sk,?struct?msghdr?*msg,
            ???size_t?len)

            {
            ?...
            ?rt?=?ip_route_output_flow(net,?&fl4,?sk);
            ?if?(IS_ERR(rt))?{
            ??err?=?PTR_ERR(rt);
            ??rt?=?NULL;
            ??if?(err?==?-ENETUNREACH)
            ???IP_INC_STATS_BH(net,?IPSTATS_MIB_OUTNOROUTES);
            ??goto?out;
            ?}
            ?...
            out:?
            ?return?err;?
            }

            在 ip_route_output_flow 這里的返回值判斷如果是 ENETUNREACH 就退出了。這個(gè)宏定義注釋上來(lái)看報(bào)錯(cuò)的信息就是 “Network is unreachable”。

            這個(gè) ip_route_output_flow 主要是執(zhí)行路由選路。所以我們推斷可能是路由出問(wèn)題了,看一下這個(gè)命名空間的路由表。

            #?ip?netns?exec?net1?route?-n
            Kernel?IP?routing?table
            Destination?????Gateway?????????Genmask?????????Flags?Metric?Ref????Use?Iface
            192.168.0.0?????0.0.0.0?????????255.255.255.0???U?????0??????0????????0?veth1

            怪不得,原來(lái) net1 這個(gè) namespace 下默認(rèn)只有 192.168.0.* 這個(gè)網(wǎng)段的路由規(guī)則。我們 ping 的 IP 是 10.153.*.* ,根據(jù)這個(gè)路由表里找不到出口。自然就發(fā)送失敗了。

            我們來(lái)給 net 添加上默認(rèn)路由規(guī)則,只要匹配不到其它規(guī)則就默認(rèn)送到 veth1 上,同時(shí)指定下一條是它所連接的 bridge(192.168.0.1)。

            #?ip?netns?exec?net1?route?add?default?gw?192.168.0.1?veth1?

            再 ping 一下試試。

            #?ip?netns?exec?net1?ping?10.153.*.*?-c?2
            PING?10.153.*.*?(10.153.*.*)?56(84)?bytes?of?data.

            ---?10.153.*.*?ping?statistics?---
            2?packets?transmitted,?0?received,?100%?packet?loss,?time?999ms

            額好吧,仍然不通。上面路由幫我們把數(shù)據(jù)包從 veth 正確送到了 bridge 這個(gè)網(wǎng)橋上。接下來(lái)網(wǎng)橋還需要 bridge 轉(zhuǎn)發(fā)到 eth0 網(wǎng)卡上。所以我們得打開下面這兩個(gè)轉(zhuǎn)發(fā)相關(guān)的配置

            #?sysctl?net.ipv4.conf.all.forwarding=1
            #?iptables?-P?FORWARD?ACCEPT

            不過(guò)這個(gè)時(shí)候,還存在一個(gè)問(wèn)題。那就是外部的機(jī)器并不認(rèn)識(shí) 192.168.0.* 這個(gè)網(wǎng)段的 ip。它們之間都是通過(guò) 10.153.*.* 來(lái)進(jìn)行通信的。設(shè)想下我們工作中的電腦上沒有外網(wǎng) IP 的時(shí)候是如何正常上網(wǎng)的呢?外部的網(wǎng)絡(luò)只認(rèn)識(shí)外網(wǎng) IP。沒錯(cuò),那就是我們上面說(shuō)的 NAT 技術(shù)。

            我們這次的需求是實(shí)現(xiàn)內(nèi)部虛擬網(wǎng)絡(luò)訪問(wèn)外網(wǎng),所以需要使用的是 SNAT。它將 namespace 請(qǐng)求中的 IP(192.168.0.2)換成外部網(wǎng)絡(luò)認(rèn)識(shí)的 10.153.*.*,進(jìn)而達(dá)到正常訪問(wèn)外部網(wǎng)絡(luò)的效果。

            #?iptables?-t?nat?-A?POSTROUTING?-s?192.168.0.0/24?!?-o?br0?-j?MASQUERADE

            來(lái)再 ping 一下試試,歐耶,通了!

            #?ip?netns?exec?net1?ping?10.153.*.*
            PING?10.153.*.*?(10.153.*.*)?56(84)?bytes?of?data.
            64?bytes?from?10.153.*.*:?icmp_seq=1?ttl=57?time=1.70?ms
            64?bytes?from?10.153.*.*:?icmp_seq=2?ttl=57?time=1.68?ms

            這時(shí)候我們可以開啟 tcpdump 抓包查看一下,在 bridge 上抓到的包我們能看到還是原始的源 IP 和 目的 IP。

            再到 eth0 上查看的話,源 IP 已經(jīng)被替換成可和外網(wǎng)通信的 eth0 上的 IP 了。

            至此,容器就可以通過(guò)宿主機(jī)的網(wǎng)卡來(lái)訪問(wèn)外部網(wǎng)絡(luò)上的資源了。我們來(lái)總結(jié)一下這個(gè)發(fā)送過(guò)程

            3. 開放容器端口

            我們?cè)倏紤]另外一個(gè)需求,那就是把在這個(gè)命名空間內(nèi)的服務(wù)提供給外部網(wǎng)絡(luò)來(lái)使用。

            和上面的問(wèn)題一樣,我們的虛擬網(wǎng)絡(luò)環(huán)境中 192.168.0.2 這個(gè) IP 外界是不認(rèn)識(shí)它的。只有這個(gè)宿主機(jī)知道它是誰(shuí)。所以我們同樣還需要 NAT 功能。

            這次我們是要實(shí)現(xiàn)外部網(wǎng)絡(luò)訪問(wèn)內(nèi)部地址,所以需要的是 DNAT 配置。DNAT 和 SNAT 配置中有一個(gè)不一樣的地方就是需要明確指定容器中的端口在宿主機(jī)上是對(duì)應(yīng)哪個(gè)。比如在 docker 的使用中,是通過(guò) -p 來(lái)指定端口的對(duì)應(yīng)關(guān)系。

            #?docker?run?-p?8000:80?...

            我們通過(guò)如下這個(gè)命令來(lái)配置 DNAT 規(guī)則

            #?iptables?-t?nat?-A?PREROUTING??!?-i?br0?-p?tcp?-m?tcp?--dport?8088?-j?DNAT?--to-destination?192.168.0.2:80

            這里表示的是宿主機(jī)在路由之前判斷一下如果流量不是來(lái)自 br0,并且是訪問(wèn) tcp 的 8088 的話,那就轉(zhuǎn)發(fā)到 192.168.0.2:80 。

            在 net1 環(huán)境中啟動(dòng)一個(gè) Server

            #?ip?netns?exec?net1?nc?-lp?80

            外部選一個(gè)ip,比如 10.143.*.*, telnet 連一下 10.162.*.* 8088 試試,通了!

            #?telnet?10.162.*.*?8088
            Trying?10.162.*.*...
            Connected?to?10.162.*.*.
            Escape?character?is?'^]'.

            開啟抓包, # tcpdump -i eth0 host 10.143.*.*。可見在請(qǐng)求的時(shí)候,目的是宿主機(jī)的 IP 的端口。

            但數(shù)據(jù)包到宿主機(jī)協(xié)議棧以后命中了我們配置的 DNAT 規(guī)則,宿主機(jī)把它轉(zhuǎn)發(fā)到了 br0 上。在 bridge 上由于沒有那么多的網(wǎng)絡(luò)流量包,所以不用過(guò)濾直接抓包就行,# tcpdump -i br0

            在 br0 上抓到的目的 IP 和端口是已經(jīng)替換過(guò)的了。

            bridge 當(dāng)然知道 192.168.0.2 是 veth 1。于是,在 veth1 上監(jiān)聽 80 的服務(wù)就能收到來(lái)自外界的請(qǐng)求了!我們來(lái)總結(jié)一下這個(gè)接收過(guò)程

            三、總結(jié)

            現(xiàn)在業(yè)界已經(jīng)有很多公司都遷移到容器上了。我們的開發(fā)寫出來(lái)的代碼大概率是要運(yùn)行在容器上的。因此深刻理解容器網(wǎng)絡(luò)的工作原理非常的重要。這有這樣將來(lái)遇到問(wèn)題的時(shí)候才知道該如何下手處理。

            本文開頭我們先是簡(jiǎn)單介紹了 veth、bridge、namespace、路由、iptables 等基礎(chǔ)知識(shí)。Veth 實(shí)現(xiàn)連接,bridge 實(shí)現(xiàn)轉(zhuǎn)發(fā),namespace 實(shí)現(xiàn)隔離,路由表控制發(fā)送時(shí)的設(shè)備選擇,iptables 實(shí)現(xiàn) nat 等功能。

            接著基于以上基礎(chǔ)知識(shí),我們采用純手工的方式搭建了一個(gè)虛擬網(wǎng)絡(luò)環(huán)境。

            這個(gè)虛擬網(wǎng)絡(luò)可以訪問(wèn)外網(wǎng)資源,也可以提供端口服務(wù)供外網(wǎng)來(lái)調(diào)用。這就是 Docker 容器網(wǎng)絡(luò)工作的基本原理。

            整個(gè)實(shí)驗(yàn)我打包寫成一個(gè) Makefile,放到了這里:https://github.com/yanfeizhang/coder-kung-fu/tree/main/tests/network/test07

            最后,我們?cè)贁U(kuò)展一下。今天我們討論的問(wèn)題是 Docker 網(wǎng)絡(luò)通信的問(wèn)題。Docker 容器通過(guò)端口映射的方式提供對(duì)外服務(wù)。外部機(jī)器訪問(wèn)容器服務(wù)的時(shí)候,仍然需要通過(guò)容器的宿主機(jī) IP 來(lái)訪問(wèn)。

            在 Kubernets 中,對(duì)跨主網(wǎng)絡(luò)通信有更高的要求,要不同宿主機(jī)之間的容器可以直接互聯(lián)互通。所以 Kubernets 的網(wǎng)絡(luò)模型也更為復(fù)雜。

            -End-

            最近有一些小伙伴,讓我?guī)兔φ乙恍?面試題?資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

            點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

            在看點(diǎn)這里好文分享給更多人↓↓

            瀏覽 29
            點(diǎn)贊
            評(píng)論
            收藏
            分享

            手機(jī)掃一掃分享

            分享
            舉報(bào)
            評(píng)論
            圖片
            表情
            推薦
            點(diǎn)贊
            評(píng)論
            收藏
            分享

            手機(jī)掃一掃分享

            分享
            舉報(bào)
            <kbd id="afajh"><form id="afajh"></form></kbd>
            <strong id="afajh"><dl id="afajh"></dl></strong>
              <del id="afajh"><form id="afajh"></form></del>
                  1. <th id="afajh"><progress id="afajh"></progress></th>
                    <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    五月激情四射网 | 无码aaa | 黄色A在线观看 | 热亚洲热中文热日韩 | 靠bi视频网站免费入口在线观看 |