1# 2# Copyright 2018 - The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import time 17 18from acts import asserts 19from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT 20from acts.test_decorators import test_tracker_info 21from acts_contrib.test_utils.net import connectivity_const as cconst 22from acts_contrib.test_utils.net import connectivity_test_utils as cutils 23from acts_contrib.test_utils.net import net_test_utils as nutils 24from acts_contrib.test_utils.net.net_test_utils import start_tcpdump 25from acts_contrib.test_utils.net.net_test_utils import stop_tcpdump 26from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_DISABLED 27from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name 28from acts_contrib.test_utils.tel.tel_test_utils import set_wfc_mode 29from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 30from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 31from scapy.all import rdpcap 32from scapy.all import Scapy_Exception 33from scapy.all import TCP 34from scapy.all import UDP 35 36 37RST = 0x04 38SSID = wutils.WifiEnums.SSID_KEY 39 40class DnsOverTlsTest(WifiBaseTest): 41 """Tests for DNS-over-TLS.""" 42 43 def setup_class(self): 44 """Setup devices for DNS-over-TLS test and unpack params.""" 45 46 self.dut = self.android_devices[0] 47 if len(self.android_devices) > 1: 48 self.dut_b = self.android_devices[1] 49 for ad in self.android_devices: 50 ad.droid.setPrivateDnsMode(True) 51 nutils.verify_lte_data_and_tethering_supported(ad) 52 set_wfc_mode(self.log, ad, WFC_MODE_DISABLED) 53 req_params = ("ping_hosts",) 54 opt_params = ("ipv4_only_network", "ipv4_ipv6_network", "dns_name") 55 self.unpack_userparams(req_param_names=req_params, 56 opt_param_names=opt_params) 57 58 if OPENWRT in self.user_params: 59 self.openwrt = self.access_points[0] 60 self.private_dns_servers = [self.dns_name] 61 self.configure_openwrt_ap_and_start(wpa_network=True) 62 self.openwrt.network_setting.setup_dns_server(self.dns_name) 63 else: 64 self.private_dns_servers = [cconst.DNS_GOOGLE, 65 cconst.DNS_QUAD9, 66 cconst.DNS_CLOUDFLARE] 67 self.tcpdump_pid = None 68 69 def teardown_test(self): 70 wutils.reset_wifi(self.dut) 71 72 def teardown_class(self): 73 for ad in self.android_devices: 74 ad.droid.setPrivateDnsMode(True) 75 76 if OPENWRT in self.user_params: 77 self.openwrt.network_setting.remove_dns_server() 78 79 def on_fail(self, test_name, begin_time): 80 self.dut.take_bug_report(test_name, begin_time) 81 82 def get_wifi_network(self, ipv6_supported): 83 if OPENWRT in self.user_params: 84 if ipv6_supported: 85 self.openwrt.network_setting.enable_ipv6() 86 else: 87 self.openwrt.network_setting.disable_ipv6() 88 return self.openwrt.get_wifi_network() 89 if ipv6_supported: 90 return self.ipv4_ipv6_network 91 return self.ipv4_only_network 92 93 def _start_tcp_dump(self, ad): 94 """Start tcpdump on the given dut. 95 96 Args: 97 ad: dut to run tcpdump on 98 """ 99 self.tcpdump_pid = start_tcpdump(ad, self.test_name) 100 101 def _stop_tcp_dump(self, ad): 102 """Stop tcpdump and pull it to the test run logs. 103 104 Args: 105 ad: dut to pull tcpdump from 106 """ 107 return stop_tcpdump(ad, self.tcpdump_pid, self.test_name) 108 109 def _verify_dns_queries_over_tls(self, pcap_file, tls=True): 110 """Verify if DNS queries were over TLS or not. 111 112 Args: 113 pcap_file: tcpdump file 114 tls: if queries should be over TLS or port 853 115 """ 116 try: 117 packets = rdpcap(pcap_file) 118 except Scapy_Exception: 119 asserts.fail("Not a valid pcap file") 120 for pkt in packets: 121 summary = "%s" % pkt.summary() 122 for host in self.ping_hosts: 123 host = host.split(".")[-2] 124 if tls and UDP in pkt and pkt[UDP].dport == 53 and \ 125 host in summary: 126 asserts.fail("Found query to port 53: %s" % summary) 127 elif not tls and TCP in pkt and pkt[TCP].dport == 853 and \ 128 not pkt[TCP].flags: 129 asserts.fail("Found query to port 853: %s" % summary) 130 131 def _verify_no_rst_packets_port_853(self, pcap_file): 132 """Verify if RST packets are found in the pcap file. 133 134 Args: 135 pcap_file: full path of tcpdump file 136 """ 137 packets = rdpcap(pcap_file) 138 for pkt in packets: 139 if TCP in pkt and pkt[TCP].flags == RST and pkt[TCP].dport == 853: 140 asserts.fail("Found RST packets: %s" % pkt.summary()) 141 142 def _test_private_dns_mode(self, ad, net, dns_mode, use_tls, hostname=None): 143 """Test private DNS mode. 144 145 Args: 146 ad: android device object 147 net: wifi network to connect to, LTE network if None 148 dns_mode: private DNS mode 149 use_tls: if True, the DNS packets should be encrypted 150 hostname: private DNS hostname to set to 151 """ 152 153 # set private dns mode 154 if dns_mode: 155 cutils.set_private_dns(self.dut, dns_mode, hostname) 156 157 # connect to wifi 158 if net: 159 wutils.start_wifi_connection_scan_and_ensure_network_found( 160 self.dut, net[SSID]) 161 wutils.wifi_connect(self.dut, net) 162 163 # start tcpdump on the device 164 self._start_tcp_dump(self.dut) 165 166 # ping hosts should pass 167 for host in self.ping_hosts: 168 self.log.info("Pinging %s" % host) 169 status = wutils.validate_connection(self.dut, host) 170 asserts.assert_true(status, "Failed to ping host %s" % host) 171 self.log.info("Ping successful") 172 173 # stop tcpdump 174 pcap_file = self._stop_tcp_dump(self.dut) 175 176 # verify DNS queries 177 self._verify_dns_queries_over_tls(pcap_file, use_tls) 178 179 # reset wifi 180 wutils.reset_wifi(self.dut) 181 182 @test_tracker_info(uuid="2957e61c-d333-45fb-9ff9-2250c9c8535a") 183 def test_private_dns_mode_off_wifi_ipv4_only_network(self): 184 """Verify private dns mode off on ipv4 only network. 185 186 Steps: 187 1. Set private dns mode off 188 2. Connect to wifi network. DNS server supports DNS/TLS 189 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 190 4. Verify ping works to differnt hostnames 191 5. Verify that all queries go to port 53 192 """ 193 self._test_private_dns_mode(self.dut, 194 self.get_wifi_network(False), 195 cconst.PRIVATE_DNS_MODE_OFF, 196 False) 197 198 @test_tracker_info(uuid="ea036d22-25af-4df0-b6cc-0027bc1efbe9") 199 def test_private_dns_mode_off_wifi_ipv4_ipv6_network(self): 200 """Verify private dns mode off on ipv4-ipv6 network. 201 202 Steps: 203 1. Set private dns mode off 204 2. Connect to wifi network. DNS server supports DNS/TLS 205 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 206 4. Verify ping works to differnt hostnames 207 5. Verify that all queries go to port 53 208 """ 209 self._test_private_dns_mode(self.dut, 210 self.get_wifi_network(True), 211 cconst.PRIVATE_DNS_MODE_OFF, 212 False) 213 214 @test_tracker_info(uuid="4227abf4-0a75-4b4d-968c-dfc63052f5db") 215 def test_private_dns_mode_opportunistic_wifi_ipv4_only_network(self): 216 """Verify private dns mode opportunistic on ipv4 only network. 217 218 Steps: 219 1. Set private dns to opportunistic mode 220 2. Connect to wifi network. DNS server supports DNS/TLS 221 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 222 4. Verify ping works to differnt hostnames 223 5. Verify that all queries go to port 853 and encrypted 224 """ 225 self._test_private_dns_mode(self.dut, 226 self.get_wifi_network(False), 227 cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC, 228 True) 229 230 @test_tracker_info(uuid="0c97cfef-4313-4346-b05b-395de63c5c3f") 231 def test_private_dns_mode_opportunistic_wifi_ipv4_ipv6_network(self): 232 """Verify private dns mode opportunistic on ipv4-ipv6 network. 233 234 Steps: 235 1. Set private dns to opportunistic mode 236 2. Connect to wifi network. DNS server supports DNS/TLS 237 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 238 4. Verify ping works to differnt hostnames 239 5. Verify that all queries go to port 853 240 """ 241 self._test_private_dns_mode(self.dut, 242 self.get_wifi_network(True), 243 cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC, 244 True) 245 246 @test_tracker_info(uuid="b70569f1-2613-49d0-be49-fd3464dde305") 247 def test_private_dns_mode_strict_wifi_ipv4_only_network(self): 248 """Verify private dns mode strict on ipv4 only network. 249 250 Steps: 251 1. Set private dns to strict mode 252 2. Connect to wifi network. DNS server supports DNS/TLS 253 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 254 4. Verify ping works to differnt hostnames 255 5. Verify that all queries go to port 853 and encrypted 256 """ 257 for dns in self.private_dns_servers: 258 self._test_private_dns_mode(self.dut, 259 self.get_wifi_network(False), 260 cconst.PRIVATE_DNS_MODE_STRICT, 261 True, 262 dns) 263 264 @test_tracker_info(uuid="85738b52-823b-4c59-a0d5-219e2fab2929") 265 def test_private_dns_mode_strict_wifi_ipv4_ipv6_network(self): 266 """Verify private dns mode strict on ipv4-ipv6 network. 267 268 Steps: 269 1. Set private dns to strict mode 270 2. Connect to wifi network. DNS server supports DNS/TLS 271 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 272 4. Verify ping works to differnt hostnames 273 5. Verify that all queries go to port 853 and encrypted 274 """ 275 for dns in self.private_dns_servers: 276 self._test_private_dns_mode(self.dut, 277 self.get_wifi_network(True), 278 cconst.PRIVATE_DNS_MODE_STRICT, 279 True, 280 dns) 281 282 @test_tracker_info(uuid="727e280a-d2bd-463f-b2a1-653d4b3f7f29") 283 def test_private_dns_mode_off_vzw_carrier(self): 284 """Verify private dns mode off on VZW network. 285 286 Steps: 287 1. Set private dns mode off 288 2. Connect to wifi network. VZW doesn't support DNS/TLS 289 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 290 4. Verify ping works to differnt hostnames 291 5. Verify that all queries go to port 53 292 """ 293 carrier = get_operator_name(self.log, self.dut_b) 294 asserts.skip_if(carrier != "vzw", "Carrier is not Verizon") 295 self._test_private_dns_mode(self.dut_b, 296 None, 297 cconst.PRIVATE_DNS_MODE_OFF, 298 False) 299 300 @test_tracker_info(uuid="b16f6e2c-a24f-4efe-9003-2bfaf28b8d5e") 301 def test_private_dns_mode_off_tmo_carrier(self): 302 """Verify private dns mode off on TMO network. 303 304 Steps: 305 1. Set private dns to off mode 306 2. Connect to wifi network. TMO supports DNS/TLS 307 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 308 4. Verify ping works to differnt hostnames 309 5. Verify that all queries go to port 53 310 """ 311 carrier = get_operator_name(self.log, self.dut) 312 asserts.skip_if(carrier != "tmo", "Carrier is not T-mobile") 313 self._test_private_dns_mode(self.dut, 314 None, 315 cconst.PRIVATE_DNS_MODE_OFF, 316 False) 317 318 @test_tracker_info(uuid="edfa7bfe-3e52-46b4-9d72-7c6c300b3680") 319 def test_private_dns_mode_opportunistic_vzw_carrier(self): 320 """Verify private dns mode opportunistic on VZW network. 321 322 Steps: 323 1. Set private dns mode opportunistic 324 2. Connect to wifi network. VZW doesn't support DNS/TLS 325 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 326 4. Verify ping works to differnt hostnames 327 5. Verify that all queries go to port 53 328 """ 329 carrier = get_operator_name(self.log, self.dut_b) 330 asserts.skip_if(carrier != "vzw", "Carrier is not Verizon") 331 self._test_private_dns_mode(self.dut_b, 332 None, 333 cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC, 334 False) 335 336 @test_tracker_info(uuid="41c3f2c4-11b7-4bb8-a3c9-fac63f6822f6") 337 def test_private_dns_mode_opportunistic_tmo_carrier(self): 338 """Verify private dns mode opportunistic on TMO network. 339 340 Steps: 341 1. Set private dns mode opportunistic 342 2. Connect to wifi network. TMP supports DNS/TLS 343 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 344 4. Verify ping works to differnt hostnames 345 5. Verify that all queries go to port 853 and encrypted 346 """ 347 carrier = get_operator_name(self.log, self.dut) 348 asserts.skip_if(carrier != "tmo", "Carrier is not T-mobile") 349 self._test_private_dns_mode(self.dut, 350 None, 351 cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC, 352 True) 353 354 @test_tracker_info(uuid="65fd2052-f0c0-4446-b353-7ed2273e6c95") 355 def test_private_dns_mode_strict_vzw_carrier(self): 356 """Verify private dns mode strict on VZW network. 357 358 Steps: 359 1. Set private dns mode strict 360 2. Connect to wifi network. VZW doesn't support DNS/TLS 361 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 362 4. Verify ping works to differnt hostnames 363 5. Verify that all queries go to port 853 and encrypted 364 """ 365 carrier = get_operator_name(self.log, self.dut_b) 366 asserts.skip_if(carrier != "vzw", "Carrier is not Verizon") 367 for dns in self.private_dns_servers: 368 self._test_private_dns_mode(self.dut_b, 369 None, 370 cconst.PRIVATE_DNS_MODE_STRICT, 371 True, 372 dns) 373 374 @test_tracker_info(uuid="bca141f7-06c9-4e44-854e-4bdb9443b2da") 375 def test_private_dns_mode_strict_tmo_carrier(self): 376 """Verify private dns mode strict on TMO network. 377 378 Steps: 379 1. Set private dns mode strict 380 2. Connect to wifi network. TMO supports DNS/TLS 381 3. Run HTTP ping to amazon.com, facebook.com, netflix.com 382 4. Verify ping works to differnt hostnames 383 5. Verify that all queries go to port 853 and encrypted 384 """ 385 carrier = get_operator_name(self.log, self.dut) 386 asserts.skip_if(carrier != "tmo", "Carrier is not T-mobile") 387 for dns in self.private_dns_servers: 388 self._test_private_dns_mode(self.dut, 389 None, 390 cconst.PRIVATE_DNS_MODE_STRICT, 391 True, 392 dns) 393 394 @test_tracker_info(uuid="7d977987-d9e3-4be1-b8fc-e5a84050ed48") 395 def test_private_dns_mode_opportunistic_connectivity_toggle_networks(self): 396 """Verify private DNS opportunistic mode connectivity by toggling networks. 397 398 Steps: 399 1. Set private DNS opportunistic mode 400 2. DUT is connected to mobile network 401 3. Verify connectivity and DNS queries going to port 853 for TMO 402 and port 53 for VZW 403 4. Switch to wifi network set with private DNS server 404 5. Verify connectivity and DNS queries going to port 853 405 6. Switch back to mobile network 406 7. Verify connectivity and DNS queries going to port 853 for TMO 407 and port 53 for VZW 408 8. Repeat steps 1-7 for TMO, VZW and different private DNS servers 409 """ 410 for ad in self.android_devices: 411 carrier = get_operator_name(self.log, ad) 412 self.log.info("Carrier is: %s" % carrier) 413 use_tls = True if carrier == "tmo" else False 414 for dns in self.private_dns_servers: 415 self.log.info("Setting opportunistic private dns mode") 416 # set private dns mode 417 cutils.set_private_dns(ad, cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC) 418 419 # verify dns over tls on mobile network 420 self._test_private_dns_mode( 421 self.dut, None, None, use_tls, dns) 422 423 # verify dns over tls on wifi network 424 self._test_private_dns_mode( 425 self.dut, self.ipv4_ipv6_network, None, True, dns) 426 427 # verify dns over tls on mobile network 428 wutils.reset_wifi(self.dut) 429 self._test_private_dns_mode( 430 self.dut, None, None, use_tls, dns) 431 432 @test_tracker_info(uuid="bc2f228f-e288-4539-a4b9-c02968209985") 433 def test_private_dns_mode_strict_connectivity_toggle_networks(self): 434 """Verify private DNS strict mode connectivity by toggling networks. 435 436 Steps: 437 1. Set private DNS strict mode 438 2. DUT is connected to mobile network 439 3. Verify connectivity and DNS queries going to port 853 440 4. Switch to wifi network 441 5. Verify connectivity and DNS queries going to port 853 442 6. Switch back to mobile network 443 7. Verify connectivity and DNS queries going to port 853 444 8. Repeat steps 1-7 for TMO, VZW and different private DNS servers 445 """ 446 for ad in self.android_devices: 447 self.log.info("Carrier is: %s" % get_operator_name(self.log, ad)) 448 for dns in self.private_dns_servers: 449 self.log.info("Setting strict mode private dns: %s" % dns) 450 # set private dns mode 451 cutils.set_private_dns(ad, cconst.PRIVATE_DNS_MODE_STRICT, dns) 452 453 # verify dns over tls on mobile network 454 self._test_private_dns_mode( 455 self.dut, None, None, True, dns) 456 457 # verify dns over tls on wifi network 458 self._test_private_dns_mode( 459 self.dut, self.ipv4_ipv6_network, None, True, dns) 460 461 # verify dns over tls on mobile network 462 wutils.reset_wifi(self.dut) 463 self._test_private_dns_mode( 464 self.dut, None, None, True, dns) 465 466 @test_tracker_info(uuid="1426673a-7728-4df7-8de5-dfb3529ada62") 467 def test_dns_server_link_properties_strict_mode(self): 468 """Verify DNS server in the link properties when set in strict mode. 469 470 Steps: 471 1. Set DNS server hostname in Private DNS settings (stict mode) 472 2. Verify that DNS server set in settings is in link properties 473 3. Verify for WiFi as well as LTE 474 """ 475 # start tcpdump on device 476 self._start_tcp_dump(self.dut) 477 478 # set private DNS to strict mode 479 cutils.set_private_dns( 480 self.dut, cconst.PRIVATE_DNS_MODE_STRICT, cconst.DNS_GOOGLE) 481 482 # connect DUT to wifi network 483 wutils.start_wifi_connection_scan_and_ensure_network_found( 484 self.dut, self.ipv4_ipv6_network[SSID]) 485 wutils.wifi_connect(self.dut, self.ipv4_ipv6_network) 486 for host in self.ping_hosts: 487 wutils.validate_connection(self.dut, host) 488 489 # DNS server in link properties for wifi network 490 link_prop = self.dut.droid.connectivityGetActiveLinkProperties() 491 wifi_dns_servers = link_prop["PrivateDnsServerName"] 492 self.log.info("Link prop: %s" % wifi_dns_servers) 493 494 # DUT is on LTE data 495 wutils.reset_wifi(self.dut) 496 time.sleep(1) # wait till lte network becomes active 497 for host in self.ping_hosts: 498 wutils.validate_connection(self.dut, host) 499 500 # DNS server in link properties for cell network 501 link_prop = self.dut.droid.connectivityGetActiveLinkProperties() 502 lte_dns_servers = link_prop["PrivateDnsServerName"] 503 self.log.info("Link prop: %s" % lte_dns_servers) 504 505 # stop tcpdump on device 506 pcap_file = self._stop_tcp_dump(self.dut) 507 508 # Verify DNS server in link properties 509 asserts.assert_true(cconst.DNS_GOOGLE in wifi_dns_servers, 510 "Hostname not in link properties - wifi network") 511 asserts.assert_true(cconst.DNS_GOOGLE in lte_dns_servers, 512 "Hostname not in link properites - cell network") 513 514 @test_tracker_info(uuid="525a6f2d-9751-474e-a004-52441091e427") 515 def test_dns_over_tls_no_reset_packets(self): 516 """Verify there are no TCP packets with RST flags on port 853. 517 518 Steps: 519 1. Enable opportunistic or strict mode 520 2. Ping hosts and verify that there are TCP pkts with RST flags 521 """ 522 # start tcpdump on device 523 self._start_tcp_dump(self.dut) 524 525 # set private DNS to opportunistic mode 526 cutils.set_private_dns(self.dut, cconst.PRIVATE_DNS_MODE_OPPORTUNISTIC) 527 528 # connect DUT to wifi network 529 wutils.start_wifi_connection_scan_and_ensure_network_found( 530 self.dut, self.ipv4_ipv6_network[SSID]) 531 wutils.wifi_connect(self.dut, self.ipv4_ipv6_network) 532 for host in self.ping_hosts: 533 wutils.validate_connection(self.dut, host) 534 535 # stop tcpdump on device 536 pcap_file = self._stop_tcp_dump(self.dut) 537 538 # check that there no RST TCP packets 539 self._verify_no_rst_packets_port_853(pcap_file) 540 541 @test_tracker_info(uuid="af6e34f1-3ad5-4ab0-b3b9-53008aa08294") 542 def test_private_dns_mode_strict_invalid_hostnames(self): 543 """Verify that invalid hostnames are not saved for strict mode. 544 545 Steps: 546 1. Set private DNS to strict mode with invalid hostname 547 2. Verify that invalid hostname is not saved 548 """ 549 invalid_hostnames = ["!%@&!*", "12093478129", "9.9.9.9", "sdkfjhasdf"] 550 for hostname in invalid_hostnames: 551 cutils.set_private_dns( 552 self.dut, cconst.PRIVATE_DNS_MODE_STRICT, hostname) 553 mode = self.dut.droid.getPrivateDnsMode() 554 specifier = self.dut.droid.getPrivateDnsSpecifier() 555 asserts.assert_true( 556 mode == cconst.PRIVATE_DNS_MODE_STRICT and specifier != hostname, 557 "Able to set invalid private DNS strict mode") 558