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