zl程序教程

您现在的位置是:首页 >  其他

当前栏目

learning:vpp dns plugins

2023-02-19 12:21:04 时间

DNS简介

域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。 DNS 不仅方便了人们访问不同的互联网服务,更为很多应用提供了,动态服务发现和全局负载均衡(Global Server Load Balance,GSLB)的机制。这样,DNS 就可以选择离用户最近的 IP 来提供服务。即使后端服务的 IP 地址发生变化,用户依然可以用相同域名来访问。 VPP dns plugins一个缓存DNS域名解析器,适合优化域名解析性能,并覆盖LD_PRELOAD库中的gethostbyname()。目前支持以下特性: 1、缓存上游ipv4 DNS服务器的A、AAAA记录; 2、响应ipv4和ipv6的名称解析请求; 3、支持最大64K的cache并发项;--目前缺省是1000条目。 4、支持CNAME间接访问; 5、静态缓存条目创建,适合于重定向特定的名称; 6、轮询上游域名查找; 7、性能/规模适合SOHO设备或其他轻型应用程序。 本文主要介绍vpp dns 插件模块,DNS相关基础知识详细介绍请参阅参考资料中文章。下面就重点介绍dns测试环境搭建与配置。

基本组网与配置

1、组网介绍:

使用VMware搭建虚拟机来完成测试,在wan接口使能dhcp client功能,可以自动从路由器上分配ip地址,为了让虚拟机可以正常上网使能nat功能并配置snat。具体如下:

2、基本配置:

1、vpp配置如下:

#wan接口状态设置up并使能dhcp clinet。
set interface state GigabitEthernet13/0/0 up
set dhcp client intfc GigabitEthernet13/0/0
#lan侧接口设置up并配置ip地址。
set interface state GigabitEthernetb/0/0 up
set interface ip address GigabitEthernetb/0/0 192.168.100.1/24
#使能snat功能配置如下:--这里不过多介绍。
nat44 enable
nat44 add interface address GigabitEthernet13/0/0
set interface nat44 in GigabitEthernetb/0/0 out GigabitEthernet13/0/0 output-feature
#内核配置 设置ens33 ip地址并配置缺省路由指向vpp lan口。
ifconfig ens33 192.168.100.2/24
ip route add default via 192.168.100.1 dev ens33

2、dns相关配置如下: dns使能需要首先配置dns server,否则无法使能。vpp 只能通过api接口进行使能,cli可以查询name server配置、查询dns cache条目及设置静态dns cache条目。

api接口可以使用两种方式来执行: 1、运行vat程序,./vpp_api_test方式。 2、直接在cli中 bin dns_name_server_add_del 114.114.114.114。

learning_vpp2# bin dns_name_server_add_del 114.114.114.114
learning_vpp2# show dns servers 
ip4 name servers:
114.114.114.114

下面主要以第一种方式来说明。

#设置dns name server
dns_name_server_add_del 114.114.114.114
dns_name_server_add_del 192.168.1.1
dns_enable_disable enable  #使能dns功能。

3、dns cli & api

1、查询dns name server

learning_vpp2# show dns servers 
ip4 name servers:
114.114.114.114
192.168.1.1

2、查询dns cache信息。

learning_vpp2# show dns cache verbose
DNS cache contains 3 entries
[P] www.dpdk-vpp.top: www.dpdk-vpp.top: 
[P] 127.10.106.39.in-addr.arpa: 127.10.106.39.in-addr.arpa: 
    www.baidu.com -> www.baidu.com: www.baidu.com: 39.156.66.18 [26] 39.156.66.14 [26]   TTL left 594.7

3、dns cache add del clear

dns cache [add|del|clear] <name> [ip4][ip6]
#添加静态dns 域名www.dpdk-vpp.top
learning_vpp2# dns cache add www.dpdk-vpp.top 39.106.10.127
#查询dns cache
learning_vpp2# show dns cache verbose                      
DNS cache contains 4 entries
[P] www.dpdk-vpp.top: www.dpdk-vpp.top: 
[P] 127.10.106.39.in-addr.arpa: 127.10.106.39.in-addr.arpa: 
    www.baidu.com -> www.baidu.com: www.baidu.com: 39.156.66.18 [26] 39.156.66.14 [26]   TTL left 472.4
[S] www.dpdk-vpp.top -> www.dpdk-vpp.top: 39.106.10.127 [86400] 

4、通过域名查询ip

vat# dns_resolve_name www.dpdk-vpp.top
vl_api_dns_resolve_name_reply_t_handler:50: resolved: 39.106.10.127
vat# 

5、IP地址反向域名解析:

vat# dns_resolve_ip 39.106.10.127  #目前是查询失败了,未分析。
dns_resolve_ip error: Misc
vat# 

反向解析 IPv4 地址时使用一个特殊的域名 in-addr.arpa。在这个模式下,一个 IPv4 由点号分隔的四个十进制数字串联,并加上一个 .in-addr.arpa 域名后缀。通过将 32 位IPv4地址拆分为四个八位字节,并将每个八位字节转换为十进制数来获得前四个十进制数。不过需要注意的是,在反向 DNS 解析时,IPv4 书写的顺序是和普通 IPv4 地址相反的。比如,如果要查询 8.8.4.4 这个IP地址的 PTR 记录,那么需要查询 4.4.8.8.in-addr.arpa,结果被指到 google-public-dns-b.google.com 这条记录。如果 google-public-dns-b.google.com的 A 记录反过来指向 8.8.4.4,那么就可以说转发被认证(Forward-confirmed)。 目前代码中没有调试正确,IP地址反向域名解析未成功--待分析。

dns处理逻辑

在调试过程中通过trace抓取了dns请求和dns回应的报文,具体流程如下:

00:02:42:464245: dpdk-input
  GigabitEthernetb/0/0 rx queue 0
  buffer 0x87c05: current data 0, length 73, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x8
                  ext-hdr-valid 
                  l4-cksum-computed l4-cksum-correct 
  PKT MBUF: port 0, nb_segs 1, pkt_len 73
    buf_len 2176, data_len 73, ol_flags 0x180, data_off 128, phys_addr 0x5a9f01c0
    packet_type 0x291 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
    Packet Offload Flags
      PKT_RX_IP_CKSUM_GOOD (0x0080) IP cksum of RX pkt. is valid
      PKT_RX_L4_CKSUM_GOOD (0x0100) L4 cksum of RX pkt. is valid
    Packet Types
      RTE_PTYPE_L2_ETHER (0x0001) Ethernet packet
      RTE_PTYPE_L3_IPV4_EXT_UNKNOWN (0x0090) IPv4 packet with or without extension headers
      RTE_PTYPE_L4_UDP (0x0200) UDP packet
  IP4: 00:0c:29:17:0a:58 -> 00:0c:29:17:0a:3a
  UDP: 192.168.100.2 -> 192.168.100.1
    tos 0x00, ttl 64, length 59, checksum 0x9bd2 dscp CS0 ecn NON_ECN
    fragment id 0x558b, flags DONT_FRAGMENT
  UDP: 59125 -> 53
    length 39, checksum 0x3153
00:02:42:464257: ethernet-input
  frame: flags 0x1, hw-if-index 1, sw-if-index 1
  IP4: 00:0c:29:17:0a:58 -> 00:0c:29:17:0a:3a
00:02:42:464268: ip4-input
  UDP: 192.168.100.2 -> 192.168.100.1
    tos 0x00, ttl 64, length 59, checksum 0x9bd2 dscp CS0 ecn NON_ECN
    fragment id 0x558b, flags DONT_FRAGMENT
  UDP: 59125 -> 53
    length 39, checksum 0x3153
00:02:42:464276: ip4-sv-reassembly-feature
  [not-fragmented]
00:02:42:464283: ip4-lookup
  fib 0 dpo-idx 7 flow hash: 0x00000000
  UDP: 192.168.100.2 -> 192.168.100.1
    tos 0x00, ttl 64, length 59, checksum 0x9bd2 dscp CS0 ecn NON_ECN
    fragment id 0x558b, flags DONT_FRAGMENT
  UDP: 59125 -> 53
    length 39, checksum 0x3153
00:02:42:464292: ip4-local
    UDP: 192.168.100.2 -> 192.168.100.1
      tos 0x00, ttl 64, length 59, checksum 0x9bd2 dscp CS0 ecn NON_ECN
      fragment id 0x558b, flags DONT_FRAGMENT
    UDP: 59125 -> 53
      length 39, checksum 0x3153
00:02:42:464298: ip4-udp-lookup
  UDP: src-port 59125 dst-port 53
00:02:42:464306: dns4-request
  DNS46_REPLY: pool index -1, disposition  6
00:02:42:464322: error-drop
  rx:GigabitEthernetb/0/0
00:02:42:464327: drop
  dns4-request: DNS pkts pending upstream name resolution

###回应
00:03:15:457671: dpdk-input
  GigabitEthernet13/0/0 rx queue 0
  buffer 0x9b729: current data 0, length 184, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x18
                  ext-hdr-valid 
                  l4-cksum-computed l4-cksum-correct 
  PKT MBUF: port 1, nb_segs 1, pkt_len 184
    buf_len 2176, data_len 184, ol_flags 0x180, data_off 128, phys_addr 0x592dcac0
    packet_type 0x291 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
    Packet Offload Flags
      PKT_RX_IP_CKSUM_GOOD (0x0080) IP cksum of RX pkt. is valid
      PKT_RX_L4_CKSUM_GOOD (0x0100) L4 cksum of RX pkt. is valid
    Packet Types
      RTE_PTYPE_L2_ETHER (0x0001) Ethernet packet
      RTE_PTYPE_L3_IPV4_EXT_UNKNOWN (0x0090) IPv4 packet with or without extension headers
      RTE_PTYPE_L4_UDP (0x0200) UDP packet
  IP4: 44:6a:2e:bd:b5:be -> 00:0c:29:17:0a:44
  UDP: 192.168.1.1 -> 192.168.1.67
    tos 0x00, ttl 64, length 170, checksum 0x5498 dscp CS0 ecn NON_ECN
    fragment id 0x6216, flags DONT_FRAGMENT
  UDP: 53 -> 53053
    length 150, checksum 0x739c
00:03:15:457694: ethernet-input
  frame: flags 0x1, hw-if-index 2, sw-if-index 2
  IP4: 44:6a:2e:bd:b5:be -> 00:0c:29:17:0a:44
00:03:15:457708: ip4-input
  UDP: 192.168.1.1 -> 192.168.1.67
    tos 0x00, ttl 64, length 170, checksum 0x5498 dscp CS0 ecn NON_ECN
    fragment id 0x6216, flags DONT_FRAGMENT
  UDP: 53 -> 53053
    length 150, checksum 0x739c
00:03:15:457716: ip4-sv-reassembly-feature
  [not-fragmented]
00:03:15:457721: ip4-dhcp-client-detect
  dhcp-client-detect: no
00:03:15:457725: nat-pre-out2in
  out2in next_index 6 arc_next_index 12
00:03:15:457728: nat44-ed-out2in
  NAT44_OUT2IN_ED_FAST_PATH: sw_if_index 2, next index 12, session 4, translation result 'success' via o2if
  i2of match: saddr 192.168.1.67 sport 53053 daddr 192.168.1.1 dport 53 proto UDP fib_idx 0 rewrite: saddr 192.168.1.67 sport 53053 daddr 192.168.1.1 dport 53 txfib 0 
  o2if match: saddr 192.168.1.1 sport 53 daddr 192.168.1.67 dport 53053 proto UDP fib_idx 0 rewrite: daddr 192.168.1.67 dport 53053 txfib 0 
  search key local 192.168.1.1:53 remote 192.168.1.67:53053 proto UDP fib 0 thread-index 32767 session-index 3437162768
 no reason for slow path
00:03:15:457739: ip4-lookup
  fib 0 dpo-idx 8 flow hash: 0x00000000
  UDP: 192.168.1.1 -> 192.168.1.67
    tos 0x00, ttl 64, length 170, checksum 0x5498 dscp CS0 ecn NON_ECN
    fragment id 0x6216, flags DONT_FRAGMENT
  UDP: 53 -> 53053
    length 150, checksum 0x739c
00:03:15:457745: ip4-local
    UDP: 192.168.1.1 -> 192.168.1.67
      tos 0x00, ttl 64, length 170, checksum 0x5498 dscp CS0 ecn NON_ECN
      fragment id 0x6216, flags DONT_FRAGMENT
    UDP: 53 -> 53053
      length 150, checksum 0x739c
00:03:15:457750: ip4-udp-lookup
  UDP: src-port 53 dst-port 53053
00:03:15:457755: dns46_reply
  DNS46_REPLY: pool index 0, disposition  1
00:03:15:457780: error-drop
  rx:GigabitEthernet13/0/0
00:03:15:457785: drop
  dns46_reply: DNS reply pkts processed

在验证过程中遇到了很多问题,主要是以下三个都未能解决。 1、内核中设置dns nameserver:192.168.100.1时,无法ping www.baidu.com,丢包原因是因为做了Dnat,未查询的session吧。这个目前怀疑需要设置nat44 add identity mapping。具体原因是因为当dns cache中未查询时,需要使用sip(wan接口ip,)dip(name server)发送dns request报文请求查询。回应报文不应该查询nat。 2、内核中设置dns nameserver:192.168.1.1,或114.114.114.114,可以首次ping www.baidu.com通。但是后续在ping时,会报错误。原因dns cache中并没有学习百度对应的ip地址,导致代码中直接回应了未查询到。 3、开启多核场景下,很容易出现异常。异常挂载nat处理中。

非常遗憾本文并没有完全明白dns plugins的使用。相关的邮件中也说明存在一些问题。https://lists.fd.io/g/vpp-dev/topic/32881233#13809。dns测试用例中也只是测试基本的api接口,并没有对功能进行详细验证。真正使用可能还需要详细研究一下。

处理流程如下:

1、dns请求逻辑:

1)当在dns 缓存中能查询到dns信息时,直接回应dns reply报文。

2)dns缓存中查询不到时,需要请求nameserver来查询,并且唤醒dns process node节点,设置超时任务用于向nameserver 再次发送dns request 报文。每个namesever请求查询次数最大三次。如果设置多个nameserver,遍历查询。直到查询成果或者查询超时退出。

发送dns request报文中的id(dns标识字段)是使用pool id (也就是当前dns在dns缓存池的索引。dns_cache_entry_t *entries)。主要用于dns reply报文的处理。

2、dns回应处理逻辑。

收到dns reply报文后,直接给dns process节点发送DNS_RESOLVER_EVENT_RESOLVED 事件,用户唤醒process节点处理dns回应报文。

参考资料:

1、一文搞懂 DNS 基础知识,收藏起来有备无患~ https://mp.weixin.qq.com/s/3rdJEDREcDMthJMH2xgUeA 2、万字长文爆肝 DNS 协议! https://mp.weixin.qq.com/s/HTOJyRaAmvZtuouw2wABmw 3、DNS协议报文(RFC1035) https://blog.csdn.net/josunna/article/details/6535947

4、案例篇:DNS 解析时快时慢,我该怎么办?

https://time.geekbang.org/column/article/81850