亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Dns服務器 > 正文

DDNS 的工作原理及其在 Linux 上的實現

2024-09-08 23:25:46
字體:
來源:轉載
供稿:網友

DDNS 工作原理的分析
DDNS 的實現最根本的一點是當主機的 IP 地址發生變化的時候,實現 DNS 映射信息的及時更新,應用程序需要及時地獲得這一信息,主要的方法可分為兩大類:

一類是輪詢機制,即:應用程序每隔一定的時間,去從查詢主機當前的 IP 地址,并與之前的進行比較,從而判斷網絡地址是否發生了變化。顯然,這種方法不僅效率低下,而且對每次查詢 IP 地址的時間間隔很難得到一個折中的數值。
第二類方法是異步實現方式,即:每當主機的 IP 地址發生變化的時候,應用程序能夠被及時地通知到。這的確是一個簡單而又高效的方法,但與此同時,另一個問題又產生了,那就是:通知源又應該由誰來擔當呢?顯然,這是處于用戶空間的應用程序無法勝任的。于是,我們想到了讓內核來充當這一消息源。這樣,在內核空間和用戶空間之間就需要通過消息來進行通信了。
在 Linux 下用戶空間與內核空間的信息交互方式有許多種,比如:軟中斷、系統調用、netlink 等等。關于這些通信方式的介紹以及其各自的優缺點并不在本文的討論范圍內,您可以自行查看參考資源。

在這許多種通信方式中,netlink 憑借其標準的 socket API、模塊化實現、異步通信機制、多播機制等等多種優勢,成為了內核與越來越多應用程序之間交互的主要方式。在 Linux 的內核中,已經為我們封裝了使用 netlink 對特定網絡狀態變化進行消息通知的功能,這就是著名的 rtnetlink。有關 netlink 在內核空間實現的詳細代碼以及其 API 參數的介紹,您可以自行查看參考資源,本文在此不作過多的贅述。
本文討論的重點是針對 DDNS 這一特定的應用,演示 rtnetlink 檢測到 IP 地址發生了變化、并將消息告知用戶空間的應用程序的整個過程,以及應用程序利用 netlink 套接字接收消息、并告知 DNS 服務器的實現方法。

DDNS 工作流程的簡單介紹
結合上述對 DDNS 工作原理的分析,我們可以將 DDNS 的工作流程簡單地用圖 1 來表示:
圖 1. DDNS 的工作流程圖

DDNS,工作原理

從圖 1 中可以看到,DDNS 的工作流程主要有三個部分:

應用程序實時感知到 IP 地址發生了變化,如上介紹,利用基于 netlink 的異步通知機制可以讓應用程序及時得到內核空間對這些事件的“通知”,具體可以分為如下 5 個步驟:

1、內核空間初始化 rtnetlink 模塊,創建 NETLINK_ROUTE 協議簇類型的 netlink 套接字;
2、用戶空間創建 NETLINK_ROUTE 協議簇類型的 netlink 套接字,并且綁定到 RTMGRP_IPV4_IFADDR 組播 group 中;
3、用戶空間接收從內核空間發來的消息,如果沒有消息,則阻塞自身;
4、當主機被分配了新的 IPV4 地址,內核空間通過 netlink_broadcast,將 RTM_NEWADDR 消息發送到 RTNLGRP_IPV4_IFADDR 組播 group 中 ;
5、用戶空間接收消息,進行驗證、處理;

應用程序接收到“通知”后,把 DNS update 信息發送給 DNS 服務器,目的是將更新后的 IP 地址及時地通知 DNS 服務器,以便網絡上的主機仍然能夠通過原來的域名訪問到自己,通用的做法是利用開源軟件 nsupdate 發送 DNS update 信息給 DNS 服務器以實現 DNS 信息的動態更新。
最后,對應于第一部分 netlink 套接字的創建,用戶空間和內核空間關閉所創建的 netlink 套接字。

下文將詳細闡述其中的每一環節及其實現。

內核空間 rtnetlink 檢測 IP 地址變化的實現與分析
在我們開始利用 netlink 套接字、實現與內核通信的應用程序之前,先來分析一下內核空間的 rtnetlink 模塊是如何工作的。
內核空間 rtnetlink 的初始化
清單 1. rtnetlink 的初始化

 /* 以下代碼摘自 Linux kernel 2.6.18, net/core/rtnetlink.c 文件,并只選擇了與本主題相關的最重要的部分,其他的都用省略號略過,之后的各清單也一樣。 */  void __init rtnetlink_init(void)  {  ...... 	 rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv, THIS_MODULE);  if (rtnl == NULL) 	 panic("rtnetlink_init: cannot initialize rtnetlink/n");  ......  }

從清單 1 中可以看到:
在 rtnetlink 進行初始化的時候,首先會調用 netlink_kernel_create 來創建一個 NETLINK_ROUTE 類型的 netlink 套接字,并指定接收函數為 rtnetlink_rcv,有關 rtnetlink_rcv 的實現細節可以查閱內核 net/core/rtnetlink.c 文件。這里需要指出的是,netlink 提供了包括 NETLINK_ROUTE、NETLINK_FIREWALL、NETLINK_INET_DIAG 等在內的多種協議簇(詳細列表及各協議簇的含義可以自行查看參考資源),其中 NETLINK_ROUTE 類型提供了網絡地址發生變化的消息,這正是 DDNS 需要用到的。
內核空間 IP 地址變化事件的通知過程
引起主機 IP 地址變化的原因有很多種,如:DHCP 分配的 IP 過期、用戶手動修改了 IP 等等。無論何種原因,最終都會觸發內核空間對相應事件的通知機制,這里以最常用的修改 IPV4 地址的工具 ifconfig 為例。
ifconfig 先是創建一個 AF_INET 的 socket,然后通過系統調用 ioctl 來完成配置的,ioctl 在內核中對應的函數是 sys_ioctl,對于 IP 地址、子網掩碼、默認網關等配置的修改,其最終會調用 devinet_ioctl。devinet_ioctl 函數處理包括 get、set 在內的多種命令,與 DDNS 應用有關的是 set 類命令,圖 2 給出了 SIOCSIFADDR 命令(設置網絡地址)的 ifconfig 調用樹:
圖 2. SIOCSIFADDR 命令的 ifconfig 調用樹

DDNS,工作原理

從圖 2 中可以看到,當用戶使用 ifconfig 對主機的 IP 地址作了修改,內核在進行了新地址的設置之后,會調用 rtmsg_ifa,傳遞的事件為 RTM_NEWADDR。
清單 2. rtmsg_ifa 發送 IP 地址變化消息

/* 以下代碼摘自 Linux kernel 2.6.18, net/ipv4/devinet.c 文件 */  static void rtmsg_ifa(int event, struct in_ifaddr* ifa)  { 	 int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128); 	 struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); 	 if (!skb) 		 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS);  else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { 		 kfree_skb(skb); 		 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); 	 } else { 		 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL); 	 }  }

從清單 2 中可以看到,rtmsg_ifa 的實現主要包括:
首先分配了一塊類型為 struct sk_buff 的空間用于存放需要發送的消息內容。
隨后,調用 inet_fill_ifaddr 將消息填充至上述緩存(有關消息的格式,您可以自行查看參考資源)。值得注意的是,RTM_NEWADDR 被作為 nlmsg_type 封裝到了內核發送給應用程序的 netlink 消息頭 nlmsghdr 中,這樣用戶空間的應用程序在接收后就能夠根據 type 來分別處理不同類型的消息了。
rtmsg_ifa 的最后是調用了 netlink_broadcast 將上述封裝完畢的 sk_buff 結構廣播到 RTNLGRP_IPV4_IFADDR 這個 group,以下是內核空間組播 group 與用戶空間組播 group 的對應關系:
清單 3. 內核空間組播 group 與用戶空間組播 group 的對應關系

/* 以下代碼摘自 Linux kernel 2.6.18, include/linux/rtnetlink.h 文件 */  /* RTnetlink multicast groups */  enum rtnetlink_groups { 	 RTNLGRP_NONE,  #define RTNLGRP_NONE 		 RTNLGRP_NONE  RTNLGRP_LINK,  #define RTNLGRP_LINK 		 RTNLGRP_LINK  ..... 	 RTNLGRP_IPV4_IFADDR,  #define RTNLGRP_IPV4_IFADDR 	 RTNLGRP_IPV4_IFADDR  ......  };  #ifndef __KERNEL__  /* RTnetlink multicast groups - backwards compatibility for userspace */  #define RTMGRP_LINK 		 1  #define RTMGRP_NOTIFY 		 2  ......  #define RTMGRP_IPV4_IFADDR 	 0x10  ......  #endif

綜上所述,當主機的 IP 地址發生變化時,內核會向所有 RTNLGRP_IPV4_IFADDR 組播成員發送 RTM_NEWADDR 消息。因此,在用戶空間創建 netlink 套接字時,只需要加入到 RTMGRP_IPV4_IFADDR 這個組播 group 中,就可以實現當本機 IP 地址有更新的時候,DDNS 應用程序能夠異步地收到內核空間發來的通知消息了。

用戶空間 netlink socket 的創建、綁定與消息接收處理
用戶空間創建 netlink 套接字
用戶空間的 netlink socket 相關操作與標準 socket API 完全一致,因此可以像使用標準 socket 來進行兩臺主機間的 IP 協議通信一樣地來使用它,這也是 netlink 之所以能夠得到越來越廣泛應用的一個重要原因。
清單 4. 用戶空間創建 netlink socket

#include <sys/socket.h>  #include <linux/types.h>  #include <linux/netlink.h>  #include <linux/rtnetlink.h>  ......  int main(void)  {  ......  if((nl_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))==-1)    // 指定通信域、通信方式以及通信協議 exit(1);  ......  }

在創建 netlink 套接字時:
我們指定了通信域為 PF_NETLINK,表明這是一個 netlink 套接字。其定義可以在如下所示的內核 include/linux/socket.h 文件中找到。從中我們也可以看到自己非常熟悉的 AF_INET:
清單 5. 清單 4 中使用到的宏定義

 /* 以下代碼摘自 include/linux/socket.h 文件 */  /* Supported address families. */  #define AF_UNSPEC 	   0  #define AF_UNIX 		 1 	 /* Unix domain sockets 	 */  #define AF_LOCAL 		 1 	 /* POSIX name for AF_UNIX 	 */  #define AF_INET 		 2 	 /* Internet IP Protocol 	 */  ......  #define AF_NETLINK 		 16  ......  /* Protocol families, same as address families. */  #define PF_NETLINK 	 AF_NETLINK  ......

對于通信方式,我們選擇了 SOCK_DGRAM。事實上對于 netlink 這種基于無連接的 socket,使用 SOCK_DGRAM 或者 SOCK_RAW 都是可以的。
對于通信協議,我們使用了 NETLINK_ROUTE。這是因為在清單 1 中,內核空間創建 netlink 套接字、用于發送 IP 地址發生變化的消息時使用的是它,所以這里需要保持一致以進行雙方間的通信。
用戶空間綁定 netlink 套接字
與標準的 socket 使用方法相似,在建立 netlink 套接字之后,也需要綁定到一個 netlink 地址才能夠進行消息的發送與接收。netlink 地址在 struct sockaddr_nl 結構中定義,各結構成員的含義可參見附錄 3。
清單 6. 用戶空間 bind netlink socket

 #include <sys/socket.h>  #include <linux/types.h>  #include <linux/netlink.h>  #include <linux/rtnetlink.h>  ......  int main(void)  {  ......  struct sockaddr_nl addr // 在 include/linux/netlink.h 中定義,結構各成員的含義可參見附錄 3  memset(&addr, 0, sizeof(addr));  addr.nl_family = PF_NETLINK;   // 定義協議簇為 PF_NETLINK  addr.nl_groups = RTMGRP_IPV4_IFADDR // 加入到 RTMGRP_IPV4_IFADDR 組播 group 中 addr.nl_pid = 0;       // 讓 kernel 來分配 pid  ......  // 將清單 5 中創建的 netlink 套接字與上述協議地址進行綁定 if(bind(nl_socket, (struct sockaddr *) &addr, sizeof(addr)) == -1)  {   close(nl_socket);   exit(1);  }  ......  }

從清單 6 中可以看到,在綁定應用程序的 netlink 套接字時,我們將自己加入到了 RTMGRP_IPV4_IFADDR 組播 group 中,這與前文我們對內核空間 IP 地址變化事件的通知過程的分析是一致的。
用戶空間接收并處理內核空間消息
同樣與標準的 socket 使用方法類似,用戶空間接收內核空間發來的 netlink 消息可以使用 recv、recvfrom 或 recvmsg。值得一提的是,netlink 套接字有自己的消息頭:nlmsghdr 結構(該結構具體各成員變量的含義請查看參考資源),而其中的 nlmsg_type 正是我們需要用到的包含了消息類型的字段。
清單 7. 用戶空間接收內核空間消息

#define MAX_MSG_SIZE 1024  ......  #include <sys/socket.h>  #include <linux/types.h>  #include <linux/netlink.h>  #include <linux/rtnetlink.h>  ......  struct if_info  {  int index;    //interface 的序號 char name[IFNAMSIZ]; //interface 的名稱,Linux 內核 include/linux/if.h 中定義了 IFNAMSIZ  uint8_t mac[ETH_ALEN];  //interface 的 mac 地址,Linux 內核 include/linux/if_ether.h 中定義了 ETH_ALEN  ......      //interface 的其他信息	 struct if_info *next; // 指向下一個 if_info 結構的指針 };  static struct if_info *if_list = NULL; // 存放現有的 interface 列表,在每次程序初始化時更新 int receive_netlink_message(struct nlmsghdr *nl); // 用于接收內核空間發來的消息的函數 handle_newaddr(struct ifinfomsg *ifi, int len); // 用于處理向 DNS 服務器發送更新的函數 ......  int main(void)  {  ......  int len = 0;  struct nlmsghdr *nl; // 結構體定義可以參考內核 include/linux/netlink.h 文件 while((len = receive_netlink_message(&nl)) > 0)  { 	 while(NLMSG_OK(nl, len)) //NLMSG 相關的宏定義可以參考內核 include/linux/netlink.h 文件	 { 		 switch(nl->nlmsg_type) 		 { 		 case RTM_NEWADDR: // 處理 RTM_NEWADDR 的 netlink 消息類型 //ifinfomsg 結構可以參考內核 include/linux/rtnetlink.h 文件			 handle_newaddr((struct ifinfomsg *)NLMSG_DATA(nl), 			    NLMSG_PAYLOAD(nl, sizeof(struct ifinfomsg))); 			 break; 					 ...... // 處理其他 netlink 消息類型,如:RTM_NEWLINK,這里略過					 default: 			 printf("Unknown netlink message type : %d", nl->nlmsg_type); 		 } 				 nl = NLMSG_NEXT(nl, len); 	 } 	 if( nl != NULL )  free(nl);  }  ...... }			 int receive_netlink_message(struct nlmsghdr **nl)  { 	 struct iovec iov; // 使用 iovec 進行接收	 struct msghdr msg = {NULL, 0, &iov, 1, NULL, 0, 0}; // 初始化 msghdr 	 int length; 	 *nl = NULL;  if ((*nl = (struct nlmsghdr *) malloc(MAX_MSG_SIZE)) == NULL ) 		 return 0;  iov.iov_base = *nl;    // 封裝 nlmsghdr  iov.iov_len = MAX_MSG_SIZE; // 指定長度		 length = recvmsg(nl_socket, &msg, 0); 		 if(length <= 0)  FREE(*nl); 		 return length;  }

應用程序在收到了 RTM_NEWADDR 類型的 netlink 消息后,需要根據 IP 的變化進行處理。這里使用了 handle_newaddr 函數,對 IP 的變化分為了兩種情況:一種是 interface 已經存在、僅僅是 IP 發生了變化;另一種是 interface 是新添加的。無論是哪種情況,handle_newaddr 函數在進行了相應的處理之后,都需要調用 update_dns.sh 這個腳本通知 DNS 服務器。關于 update_dns.sh 的實現參見下一章。
清單 8. 用戶空間處理內核空間消息

void handle_newaddr(struct ifinfomsg *ifinfo, int len)  { 	 struct if_info *i; 		 for(i = if_list ; i ; i = i->next) // 遍歷 in_list,找到 ip 發生變化的 interface 		 if(i->index == ifinfo->ifi_index) 			 break; 		 if(i != NULL){ // 找到了相應的 interface,執行 update_dns.sh 		 system(update_dns.sh); 		 return; 	 } 		 // 沒有找到對應的 interface,說明該 interface 是新添加的 if((i = calloc(sizeof(struct if_info), 1)) == NULL)// 分配一個 if_info 結構用于添加新的 interface 		 exit(1); 		 // 根據 ifinfo->ifi_index 等信息更新 if_info 結構 i,考慮到與 ddns 應用關系不大,限于篇幅,這里略過	 ...... 		 system(update_dns.sh); // 執行 update_dns.sh 		 i->next = if_list; // 在 if_list 的末尾添加新發現的 interface 	 if_list = i;  }

應用程序與 DNS 服務器的交互
應用程序可以利用開源工具 nsupdate 來向 DNS 服務器發送 DNS update 消息。nsupdate 的詳細用法及特性可以請查看參考資源,受篇幅所限,本章將會結合例子簡單介紹這個工具的基本用法。
nsupdate 可以從終端或文件中讀取命令,每個命令一行。一個空行或一個"send"命令,則會將先前輸入的命令發送到 DNS 服務器上,典型的使用方法如清單 9 所示。nsupdate 默認從文件 /etc/resolv.conf 中解析 DNS 服務器和域名,在實際應用中,我們可以首先解析網絡參數,生成 nsupdate 的輸入文件,最后調用 nsupdate。update_dns.sh 的實現流程如圖 3 所示。
清單 9. nsupdate 的使用例子

 # nsupdate  > server 9.0.148.50  //DNS 服務器地址 9.0.148.50,默認端口 53  > update delete oldhost.example.com A   // 刪除域名 oldhost.example.com 的任何 A 類型記錄  > update add newhost.example.com 86400 A 172.16.1.1  // 添加一條 172.16.1.1<----->newhost.example.com A 類型的記錄, // 記錄的 TTL 是 24 小時(86400 秒)            > send   // 發送命令

圖 3. update_dns.sh 的實現流程

DDNS,工作原理

netlink socket 的關閉
用戶空間關閉 netlink socket
同標準的 socket API 一樣,用戶空間關閉 netlink socket 使用的也是 close 函數,而且用法完全一致。您可以參考清單 6 中 close 函數在 DDNS 應用程序中的使用。
內核空間關閉 netlink socket
內核空間關閉 netlink socket 使用 sock_release 函數,函數原型如下所示:
清單 10. 內核空間關閉 netlink socket - sock_release

/* 以下代碼摘自 Linux kernel 3.4.3, net/socket.c 文件 */  void sock_release(struct socket * sock);

其中 sock 為 netlink_kernel_create 創建的 netlink 套接字。
值得一提的是,在最新的 Linux kernel 中,還提供了 netlink_kernel_release 接口,函數原型如下所示:
清單 11. 內核空間關閉 netlink socket —— netlink_kernel_release

 /* 以下代碼摘自 Linux kernel 3.4.3, net/netlink/af_netlink.c 文件 */  void netlink_kernel_release(struct sock *sk);

其中 sk 為 netlink_kernel_create 創建的 netlink 套接字。

對 DDNS 應用實現的擴展啟示
DDNS 利用 rtnetlink 的 NETLINK_ROUTE 協議簇套接字來監聽 Linux 內核網絡事件“RTM_NEWADDR”,實時更新 DNS 映射信息,從而實現 DNS 信息的動態更新。除了 NETLINK_ROUTE,netlink_family 還提供了多種協議簇來實現多種信息的報告,比如 SELinux、防火墻、Netfilter、IPV6 等。就 NETLINK_ROUTE 協議簇而言,也提供了多個組播 group 對應多種網絡連接、網絡參數、路由信息、網絡流量類別等等變化的事件。
這就啟示我們可以利用 netlink,特別是 rtnetlink,實現許多其他的與網絡相關的應用。比如:應用程序如果需要實時地監控本機路由表的變化,就可以在用戶空間創建 NETLINK_ROUTE 協議簇的 netlink 套接字時把自己加到 RTMGRP_IPV4_ROUTE 及 RTMGRP_NOTIFY 的多播組中(即:addr.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_NOTIFY;)通過這種方式,可以實現包括 OSPF、RIPv2、BGP 等在內的多種現行路由協議;再比如:也可以利用 rtnetlink 來監聽網絡的連接情況,rtnetlink 在初始化的時候將 rtnetlink 消息處理函數 rtnetlink_event 掛到了通知鏈 netdev_chain 上,網絡設備的啟動,關閉,更名等事件都能觸發通知鏈并回調消息處理函數,從而組播 RTM_NEWLINK 或者 RTM_DELLINK 信息,向用戶程序通知網絡的連接情況。

總結
本文結合 DDNS 的工作原理,簡單闡釋了 DDNS 的實現流程,并在此基礎之上,進一步演示了利用 Linux rtnetlink 套接字實現內核空間與用戶空間的網絡狀態 IP 地址變化信息的交互、以及利用 nsupdate 實現 DDNS 客戶端與服務器端的同步更新,并且在實際的應用中完全實現了 DDNS 的功能,希望能夠為使用 DDNS 進行網絡管理的人員及 Linux 網絡編程愛好者提供有益的參考。

 

參考資料

學習

  • 參考“在 Linux 下用戶空間與內核空間數據交換的方式,第 1 部分 : 內核啟動參數、模塊參數與 sysfs、sysctl、系統調用和 netlink”,了解 Linux 用戶空間與內核空間的多種數據交換方式,以及它們各自的優缺點。
  • 參考“Linux 系統內核空間與用戶空間通信的實現與分析”,了解 netlink 套接字在內核空間的 API
  • 參考 netlink(7) 的 man 手冊,了解 Linux netlink 所支持的包括 NETLINK_ROUTE 在內的各種消息類型、消息頭格式、消息地址格式及其用法等等。
  • 參考 nsupdate 的 man 手冊,了解開源工具 nsupdate 的詳細用法與特性
  • 在 developerWorks Linux 專區尋找為 Linux 開發人員(包括 Linux 新手入門)準備的更多參考資料。

作者:王 寒芷, 軟件工程師, IBM
王 俊元, 軟件工程師, IBM

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国语自产精品视频在线看抢先版图片| 亚洲无av在线中文字幕| 国产精品一区二区电影| 日本精品性网站在线观看| 国产脚交av在线一区二区| 亚洲精品久久在线| 国产精品精品久久久久久| 亚洲国产精久久久久久久| 国产日韩一区在线| 久久色精品视频| 亚洲精品成a人在线观看| 国产成人精品在线| 欧美日韩中文字幕在线| 九九热最新视频//这里只有精品| 久久视频这里只有精品| 久久91精品国产91久久跳| 亚洲电影免费观看高清完整版在线| 国产成人小视频在线观看| 欧美猛交免费看| 国产精品久久色| 欧美日韩国产一区二区| 久久精品人人爽| 国产精品高清在线观看| 91久久精品日日躁夜夜躁国产| 久久久久久久999| 国产91色在线免费| 欧美一区亚洲一区| 亚洲一区二区三区xxx视频| 欧美日本国产在线| 7m精品福利视频导航| 久久久国产一区二区三区| 日韩av最新在线观看| 久久人体大胆视频| 91情侣偷在线精品国产| 欧美一级视频一区二区| 欧美激情区在线播放| 少妇精69xxtheporn| 国产精自产拍久久久久久蜜| 久久九九免费视频| 国产精品欧美亚洲777777| 成人欧美一区二区三区在线| 亚洲欧美激情在线视频| 久久精品国产亚洲7777| 亚洲欧美日韩综合| 亚洲国产日韩一区| 在线观看欧美www| 亚洲欧美在线一区| 国产精品偷伦视频免费观看国产| 色偷偷88888欧美精品久久久| 色综合导航网站| 国产一区二区在线播放| 久久青草精品视频免费观看| 国产精品精品视频| 久久综合亚洲社区| 精品视频一区在线视频| 国产精品18久久久久久麻辣| 日韩中文字幕不卡视频| 久久精品国产欧美激情| 美女精品视频一区| 国产精品美女久久久免费| 国产香蕉精品视频一区二区三区| 国产精品99免视看9| 午夜精品视频网站| 色悠久久久久综合先锋影音下载| 久久成年人免费电影| 国产日韩精品在线| 日韩免费黄色av| 社区色欧美激情 | 88国产精品欧美一区二区三区| 亚洲电影免费观看高清完整版| 精品久久久久久久中文字幕| 国产精品入口尤物| 国产一区深夜福利| 日韩中文字幕视频在线观看| 伦伦影院午夜日韩欧美限制| 自拍偷拍亚洲在线| 久久在线观看视频| 日韩成人在线网站| 伊人久久综合97精品| 精品女同一区二区三区在线播放| 欧美寡妇偷汉性猛交| 亚洲精品久久久久中文字幕欢迎你| 中文字幕国产日韩| 精品国产乱码久久久久久婷婷| 欧美午夜影院在线视频| 亚洲欧美国产精品专区久久| 亚洲女人天堂色在线7777| 亚洲女人天堂网| 亚洲国产精品久久久久秋霞蜜臀| 成人h视频在线观看播放| 日韩电影免费观看在线观看| 4438全国成人免费| 欧美影院成年免费版| 亚洲白拍色综合图区| 欧美激情欧美激情| 中文字幕最新精品| 亚洲精品国产欧美| 国产一区私人高清影院| 日本精品va在线观看| 一区二区三区四区精品| 国产精品狼人色视频一区| 日韩精品在线视频美女| 国产91露脸中文字幕在线| 欧洲亚洲妇女av| 日韩av片永久免费网站| 国产91精品网站| 日韩黄在线观看| 在线日韩日本国产亚洲| 亚洲老板91色精品久久| 亚洲视频在线播放| 成人免费看黄网站| 亚洲国模精品一区| 欧美极品少妇xxxxⅹ免费视频| 一区国产精品视频| 91精品视频大全| 8090成年在线看片午夜| 日韩欧美亚洲综合| 欧美中文字幕在线观看| 亚洲国产日韩精品在线| 一区二区成人精品| 精品久久久久久久久久ntr影视| 91精品国产九九九久久久亚洲| 福利一区福利二区微拍刺激| 精品一区二区三区电影| 91亚洲精华国产精华| 精品国产91乱高清在线观看| 久久中国妇女中文字幕| 成人xvideos免费视频| 久久成人国产精品| 国产亚洲精品成人av久久ww| 欧美亚洲国产日本| 欧美成人小视频| 国产日韩换脸av一区在线观看| 欧美一区二区三区精品电影| 国产视频福利一区| 国产精品揄拍一区二区| 国产精选久久久久久| 亚洲自拍av在线| 久久影院资源站| 中国人与牲禽动交精品| 国产91精品高潮白浆喷水| 国产亚洲精品综合一区91| 国产精品精品视频| 亚洲偷熟乱区亚洲香蕉av| 91精品久久久久久久久久久久久久| 亚洲国产精品一区二区三区| 亚洲精品白浆高清久久久久久| 精品久久久久久中文字幕一区奶水| 欧美刺激性大交免费视频| 2019中文字幕免费视频| 亚洲美女精品久久| 97精品国产97久久久久久| 91在线观看欧美日韩| 国产成人av在线播放| 亚洲福利影片在线| 日韩亚洲综合在线| 69久久夜色精品国产7777| 欧美电影在线观看网站| 日本久久精品视频| 狠狠色狠狠色综合日日小说| 欧美成人精品三级在线观看| 91中文在线视频| 自拍偷拍亚洲欧美| 中文字幕久精品免费视频|