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.tel.tel_data_utils import wait_for_cell_data_connection 29from acts.test_utils.tel.tel_test_utils import start_adb_tcpdump 30from acts.test_utils.tel.tel_test_utils import stop_adb_tcpdump 31from acts.test_utils.tel.tel_test_utils import verify_http_connection 32from acts.test_utils.wifi import wifi_test_utils as wutils 33 34from scapy.all import TCP 35from scapy.all import UDP 36from scapy.all import rdpcap 37 38DNS_QUAD9 = "dns.quad9.net" 39PRIVATE_DNS_MODE_OFF = "off" 40PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic" 41PRIVATE_DNS_MODE_STRICT = "hostname" 42RST = 0x04 43 44class DnsOverTlsTest(base_test.BaseTestClass): 45 """ Tests for Wifi Tethering """ 46 47 def setup_class(self): 48 """ Setup devices for tethering and unpack params """ 49 50 self.dut = self.android_devices[0] 51 wutils.reset_wifi(self.dut) 52 self.dut.droid.telephonyToggleDataConnection(True) 53 wait_for_cell_data_connection(self.log, self.dut, True) 54 asserts.assert_true( 55 verify_http_connection(self.log, self.dut), 56 "HTTP verification failed on cell data connection") 57 req_params = ("wifi_network_with_dns_tls", "wifi_network_no_dns_tls", 58 "ping_hosts") 59 self.unpack_userparams(req_params) 60 self.tcpdump_pid = None 61 self.tcpdump_file = None 62 63 """ Helper functions """ 64 65 def _start_tcp_dump(self, ad): 66 """ Start tcpdump on the give dut 67 68 Args: 69 1. ad: dut to run tcpdump on 70 """ 71 if self.tcpdump_pid: 72 stop_adb_tcpdump(ad, self.tcpdump_pid, pull_tcpdump=False) 73 self.tcpdump_pid = start_adb_tcpdump(ad, self.test_name, mask='all') 74 75 def _stop_tcp_dump(self, ad): 76 """ Stop tcpdump and pull it to the test run logs 77 78 Args: 79 1. ad: dut to pull tcpdump from 80 """ 81 file_name = ad.adb.shell("ls /sdcard/tcpdump") 82 file_name = os.path.join(ad.log_path, "TCPDUMP_%s" % ad.serial, 83 file_name.split('/')[-1]) 84 if self.tcpdump_pid: 85 stop_adb_tcpdump(ad, self.tcpdump_pid, pull_tcpdump=True) 86 self.tcpdump_pid = None 87 return os.path.join(ad.log_path, file_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 if tls and UDP in pkt and pkt[UDP].dport == 53 and \ 103 "connectivitycheck.gstatic.com." not in summary and \ 104 "www.google.com" not in summary: 105 asserts.fail("Found query to port 53: %s" % summary) 106 elif not tls and TCP in pkt and pkt[TCP].dport == 853 and \ 107 not pkt[TCP].flags: 108 asserts.fail("Found query to port 853: %s" % summary) 109 110 def _verify_rst_packets(self, pcap_file): 111 """ Verify if RST packets are found in the pcap file """ 112 packets = rdpcap(pcap_file) 113 for pkt in packets: 114 if TCP in pkt and pkt[TCP].flags == RST: 115 asserts.fail("Found RST packets: %s" % pkt.summary()) 116 117 def _test_private_dns_mode(self, network, dns_mode, use_tls, 118 hostname = None): 119 """ Test private DNS mode """ 120 # connect to wifi 121 wutils.reset_wifi(self.dut) 122 if network: 123 wutils.wifi_connect(self.dut, network) 124 time.sleep(1) # wait till lte network becomes active - network = None 125 126 # start tcpdump on the device 127 self._start_tcp_dump(self.dut) 128 129 # set private dns mode 130 if dns_mode == PRIVATE_DNS_MODE_OFF: 131 self.dut.droid.setPrivateDnsMode(False) 132 elif hostname: 133 self.dut.droid.setPrivateDnsMode(True, hostname) 134 else: 135 self.dut.droid.setPrivateDnsMode(True) 136 mode = self.dut.droid.getPrivateDnsMode() 137 asserts.assert_true(mode == dns_mode, 138 "Failed to set private DNS mode to %s" % dns_mode) 139 140 # ping hosts should pass 141 for host in self.ping_hosts: 142 self.log.info("Pinging %s" % host) 143 asserts.assert_true(wutils.validate_connection(self.dut, host), 144 "Failed to ping host %s" % host) 145 146 # stop tcpdump 147 pcap_file = self._stop_tcp_dump(self.dut) 148 self.log.info("TCPDUMP file is: %s" % pcap_file) 149 150 # verify DNS queries 151 self._verify_dns_queries_over_tls(pcap_file, use_tls) 152 153 """ Test Cases """ 154 155 @test_tracker_info(uuid="2957e61c-d333-45fb-9ff9-2250c9c8535a") 156 def test_private_dns_mode_off_wifi_no_dns_tls_server(self): 157 """ Verify private dns mode off 158 159 Steps: 160 1. Set private dns mode off 161 2. Connect to wifi network. DNS/TLS server is not set 162 3. Verify ping works to differnt hostnames 163 4. Verify that all queries go to port 53 164 """ 165 self._test_private_dns_mode(self.wifi_network_no_dns_tls, 166 PRIVATE_DNS_MODE_OFF, False) 167 168 @test_tracker_info(uuid="ea036d22-25af-4df0-b6cc-0027bc1efbe9") 169 def test_private_dns_mode_off_wifi_with_dns_tls_server(self): 170 """ Verify private dns mode off 171 172 Steps: 173 1. Set private dns mode off 174 2. Connect to wifi network. DNS server is set to 9.9.9.9, 8.8.8.8 175 3. Verify ping works to differnt hostnames 176 4. Verify that all queries go to port 53 177 """ 178 self._test_private_dns_mode(self.wifi_network_with_dns_tls, 179 PRIVATE_DNS_MODE_OFF, False) 180 181 @test_tracker_info(uuid="4227abf4-0a75-4b4d-968c-dfc63052f5db") 182 def test_private_dns_mode_opportunistic_wifi_no_dns_tls_server(self): 183 """ Verify private dns opportunistic mode 184 185 Steps: 186 1. Set private dns mode to opportunistic 187 2. Connect to wifi network. DNS/TLS server is not set 188 3. Verify ping works to differnt hostnames 189 4. Verify that all queries go to port 53 190 """ 191 self._test_private_dns_mode(self.wifi_network_no_dns_tls, 192 PRIVATE_DNS_MODE_OPPORTUNISTIC, False) 193 194 @test_tracker_info(uuid="0c97cfef-4313-4346-b05b-395de63c5c3f") 195 def test_private_dns_mode_opportunistic_wifi_with_dns_tls_server(self): 196 """ Verify private dns opportunistic mode 197 198 Steps: 199 1. Set private dns mode to opportunistic 200 2. Connect to wifi network. DNS server is set to 9.9.9.9, 8.8.8.8 201 3. Verify ping works to differnt hostnames 202 4. Verify that all queries go to port 853 203 """ 204 self._test_private_dns_mode(self.wifi_network_with_dns_tls, 205 PRIVATE_DNS_MODE_OPPORTUNISTIC, True) 206 207 @test_tracker_info(uuid="b70569f1-2613-49d0-be49-fd3464dde305") 208 def test_private_dns_mode_strict_wifi_no_dns_tls_server(self): 209 """ Verify private dns strict mode 210 211 Steps: 212 1. Set private dns mode to strict 213 2. Connect to wifi network. DNS/TLS server is not set 214 3. Verify ping works to differnt hostnames 215 4. Verify that all queries go to port 853 216 """ 217 self._test_private_dns_mode(self.wifi_network_no_dns_tls, 218 PRIVATE_DNS_MODE_STRICT, True, 219 DNS_QUAD9) 220 221 @test_tracker_info(uuid="85738b52-823b-4c59-a0d5-219e2fab2929") 222 def test_private_dns_mode_strict_wifi_with_dns_tls_server(self): 223 """ Verify private dns strict mode 224 225 Steps: 226 1. Set private dns mode to strict 227 2. Connect to wifi network. DNS server is set to 9.9.9.9, 8.8.8.8 228 3. Verify ping works to differnt hostnames 229 4. Verify that all queries go to port 853 230 """ 231 self._test_private_dns_mode(self.wifi_network_with_dns_tls, 232 PRIVATE_DNS_MODE_STRICT, True, 233 DNS_QUAD9) 234 235 @test_tracker_info(uuid="727e280a-d2bd-463f-b2a1-653d4b3f7f29") 236 def test_private_dns_mode_off_lte(self): 237 """ Verify private dns off mode 238 239 Steps: 240 1. Set private dns mode to off 241 2. Reset wifi and enable LTE on DUT 242 3. Verify ping works to differnt hostnames 243 4. Verify that all queries go to port 53 244 """ 245 self._test_private_dns_mode(None, PRIVATE_DNS_MODE_OFF, False) 246 247 @test_tracker_info(uuid="b16f6e2c-a24f-4efe-9003-2bfaf28b8d5e") 248 def test_private_dns_mode_opportunistic_lte(self): 249 """ Verify private dns opportunistic mode 250 251 Steps: 252 1. Set private dns mode to opportunistic mode 253 2. Reset wifi and enable LTE on DUT 254 3. Verify ping works to differnt hostnames 255 4. Verify that all queries go to port 853 256 """ 257 self._test_private_dns_mode(None, PRIVATE_DNS_MODE_OPPORTUNISTIC, True) 258 259 @test_tracker_info(uuid="edfa7bfe-3e52-46b4-9d72-7c6c300b3680") 260 def test_private_dns_mode_strict_lte(self): 261 """ Verify private dns strict mode 262 263 Steps: 264 1. Set private dns mode to strict mode 265 2. Reset wifi and enable LTE on DUT 266 3. Verify ping works to differnt hostnames 267 4. Verify that all queries go to port 853 268 """ 269 self._test_private_dns_mode(None, PRIVATE_DNS_MODE_STRICT, True, 270 DNS_QUAD9) 271 272 @test_tracker_info(uuid="1426673a-7728-4df7-8de5-dfb3529ada62") 273 def test_dns_server_link_properties_strict_mode(self): 274 """ Verify DNS server in the link properties when set in strict mode 275 276 Steps: 277 1. Set DNS server hostname in Private DNS settings (stict mode) 278 2. Verify that DNS server set in settings is in link properties 279 3. Verify for WiFi as well as LTE 280 """ 281 # start tcpdump on device 282 self._start_tcp_dump(self.dut) 283 284 # set private DNS to strict mode 285 self.dut.droid.setPrivateDnsMode(True, DNS_QUAD9) 286 mode = self.dut.droid.getPrivateDnsMode() 287 specifier = self.dut.droid.getPrivateDnsSpecifier() 288 asserts.assert_true( 289 mode == PRIVATE_DNS_MODE_STRICT and specifier == DNS_QUAD9, 290 "Failed to set private DNS strict mode") 291 292 # connect DUT to wifi network 293 wutils.wifi_connect(self.dut, self.wifi_network_no_dns_tls) 294 for host in self.ping_hosts: 295 wutils.validate_connection(self.dut, host) 296 297 # DNS server in link properties for wifi network 298 link_prop = self.dut.droid.connectivityGetActiveLinkProperties() 299 dns_servers = link_prop['DnsServers'] 300 wifi_dns_servers = [each for lst in dns_servers for each in lst] 301 self.log.info("Link prop: %s" % wifi_dns_servers) 302 303 # DUT is on LTE data 304 wutils.reset_wifi(self.dut) 305 time.sleep(1) # wait till lte network becomes active 306 for host in self.ping_hosts: 307 wutils.validate_connection(self.dut, host) 308 309 # DNS server in link properties for cell network 310 link_prop = self.dut.droid.connectivityGetActiveLinkProperties() 311 dns_servers = link_prop['DnsServers'] 312 lte_dns_servers = [each for lst in dns_servers for each in lst] 313 self.log.info("Link prop: %s" % lte_dns_servers) 314 315 # stop tcpdump on device 316 pcap_file = self._stop_tcp_dump(self.dut) 317 self.log.info("TCPDUMP file is: %s" % pcap_file) 318 319 # Verify DNS server in link properties 320 asserts.assert_true(DNS_QUAD9 in wifi_dns_servers, 321 "Hostname not in link properties - wifi network") 322 asserts.assert_true(DNS_QUAD9 in lte_dns_servers, 323 "Hostname not in link properites - cell network") 324 325 @test_tracker_info(uuid="525a6f2d-9751-474e-a004-52441091e427") 326 def test_dns_over_tls_no_reset_packets(self): 327 """ Verify there are no TCP packets with RST flags 328 329 Steps: 330 1. Enable opportunistic or strict mode 331 2. Ping hosts and verify that there are TCP pkts with RST flags 332 """ 333 # start tcpdump on device 334 self._start_tcp_dump(self.dut) 335 336 # set private DNS to opportunistic mode 337 self.dut.droid.setPrivateDnsMode(True) 338 mode = self.dut.droid.getPrivateDnsMode() 339 asserts.assert_true(mode == PRIVATE_DNS_MODE_OPPORTUNISTIC, 340 "Failed to set private DNS opportunistic mode") 341 342 # connect DUT to wifi network 343 wutils.wifi_connect(self.dut, self.wifi_network_with_dns_tls) 344 for host in self.ping_hosts: 345 wutils.validate_connection(self.dut, host) 346 347 # stop tcpdump on device 348 pcap_file = self._stop_tcp_dump(self.dut) 349 self.log.info("TCPDUMP file is: %s" % pcap_file) 350 351 # check that there no RST TCP packets 352 self._verify_rst_packets(pcap_file) 353 354 @test_tracker_info(uuid="af6e34f1-3ad5-4ab0-b3b9-53008aa08294") 355 def test_private_dns_mode_strict_invalid_hostnames(self): 356 """ Verify that invalid hostnames are not saved for strict mode 357 358 Steps: 359 1. Set private DNS to strict mode with invalid hostname 360 2. Verify that invalid hostname is not saved 361 """ 362 invalid_hostnames = ["!%@&!*", "12093478129", "9.9.9.9", "sdkfjhasdf"] 363 for hostname in invalid_hostnames: 364 self.dut.droid.setPrivateDnsMode(True, hostname) 365 mode = self.dut.droid.getPrivateDnsMode() 366 specifier = self.dut.droid.getPrivateDnsSpecifier() 367 wutils.wifi_connect(self.dut, self.wifi_network_no_dns_tls) 368 asserts.assert_true( 369 mode == PRIVATE_DNS_MODE_STRICT and specifier != hostname, 370 "Able to set invalid private DNS strict mode") 371