[DnsOverTlsTest] Tests for dns over tls feature
CHERRY PICKED CHANGES FROM AOSP
Bug: 72815111
Test: Verified
Change-Id: Idd686c64c8044a32bc3ad137c3dac008a6c1d651
Merged-In: Ieb0a0eb8b62d797c9fd3a724b7df8b6420678462
diff --git a/acts/tests/google/net/DnsOverTlsTest.py b/acts/tests/google/net/DnsOverTlsTest.py
new file mode 100644
index 0000000..46a6c01
--- /dev/null
+++ b/acts/tests/google/net/DnsOverTlsTest.py
@@ -0,0 +1,370 @@
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import os
+import random
+import socket
+import threading
+import time
+
+from acts import asserts
+from acts import base_test
+from acts import test_runner
+from acts.controllers import adb
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
+from acts.test_utils.tel.tel_test_utils import start_adb_tcpdump
+from acts.test_utils.tel.tel_test_utils import stop_adb_tcpdump
+from acts.test_utils.tel.tel_test_utils import verify_http_connection
+from acts.test_utils.wifi import wifi_test_utils as wutils
+
+from scapy.all import TCP
+from scapy.all import UDP
+from scapy.all import rdpcap
+
+DNS_QUAD9 = "dns.quad9.net"
+PRIVATE_DNS_MODE_OFF = "off"
+PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"
+PRIVATE_DNS_MODE_STRICT = "hostname"
+RST = 0x04
+
+class DnsOverTlsTest(base_test.BaseTestClass):
+ """ Tests for Wifi Tethering """
+
+ def setup_class(self):
+ """ Setup devices for tethering and unpack params """
+
+ self.dut = self.android_devices[0]
+ wutils.reset_wifi(self.dut)
+ self.dut.droid.telephonyToggleDataConnection(True)
+ wait_for_cell_data_connection(self.log, self.dut, True)
+ asserts.assert_true(
+ verify_http_connection(self.log, self.dut),
+ "HTTP verification failed on cell data connection")
+ req_params = ("wifi_network_with_dns_tls", "wifi_network_no_dns_tls",
+ "ping_hosts")
+ self.unpack_userparams(req_params)
+ self.tcpdump_pid = None
+ self.tcpdump_file = None
+
+ """ Helper functions """
+
+ def _start_tcp_dump(self, ad):
+ """ Start tcpdump on the give dut
+
+ Args:
+ 1. ad: dut to run tcpdump on
+ """
+ if self.tcpdump_pid:
+ stop_adb_tcpdump(ad, self.tcpdump_pid, pull_tcpdump=False)
+ self.tcpdump_pid = start_adb_tcpdump(ad, self.test_name, mask='all')
+
+ def _stop_tcp_dump(self, ad):
+ """ Stop tcpdump and pull it to the test run logs
+
+ Args:
+ 1. ad: dut to pull tcpdump from
+ """
+ file_name = ad.adb.shell("ls /sdcard/tcpdump")
+ file_name = os.path.join(ad.log_path, "TCPDUMP_%s" % ad.serial,
+ file_name.split('/')[-1])
+ if self.tcpdump_pid:
+ stop_adb_tcpdump(ad, self.tcpdump_pid, pull_tcpdump=True)
+ self.tcpdump_pid = None
+ return os.path.join(ad.log_path, file_name)
+
+ def _verify_dns_queries_over_tls(self, pcap_file, tls=True):
+ """ Verify if DNS queries were over TLS or not
+
+ Args:
+ 1. pcap_file: tcpdump file
+ 2. tls: if queries should be over TLS or port 853
+ """
+ try:
+ packets = rdpcap(pcap_file)
+ except Scapy_Exception:
+ asserts.fail("Not a valid pcap file")
+ for pkt in packets:
+ summary = "%s" % pkt.summary()
+ if tls and UDP in pkt and pkt[UDP].dport == 53 and \
+ "connectivitycheck.gstatic.com." not in summary and \
+ "www.google.com" not in summary:
+ asserts.fail("Found query to port 53: %s" % summary)
+ elif not tls and TCP in pkt and pkt[TCP].dport == 853 and \
+ not pkt[TCP].flags:
+ asserts.fail("Found query to port 853: %s" % summary)
+
+ def _verify_rst_packets(self, pcap_file):
+ """ Verify if RST packets are found in the pcap file """
+ packets = rdpcap(pcap_file)
+ for pkt in packets:
+ if TCP in pkt and pkt[TCP].flags == RST:
+ asserts.fail("Found RST packets: %s" % pkt.summary())
+
+ def _test_private_dns_mode(self, network, dns_mode, use_tls,
+ hostname = None):
+ """ Test private DNS mode """
+ # connect to wifi
+ wutils.reset_wifi(self.dut)
+ if network:
+ wutils.wifi_connect(self.dut, network)
+ time.sleep(1) # wait till lte network becomes active - network = None
+
+ # start tcpdump on the device
+ self._start_tcp_dump(self.dut)
+
+ # set private dns mode
+ if dns_mode == PRIVATE_DNS_MODE_OFF:
+ self.dut.droid.setPrivateDnsMode(False)
+ elif hostname:
+ self.dut.droid.setPrivateDnsMode(True, hostname)
+ else:
+ self.dut.droid.setPrivateDnsMode(True)
+ mode = self.dut.droid.getPrivateDnsMode()
+ asserts.assert_true(mode == dns_mode,
+ "Failed to set private DNS mode to %s" % dns_mode)
+
+ # ping hosts should pass
+ for host in self.ping_hosts:
+ self.log.info("Pinging %s" % host)
+ asserts.assert_true(wutils.validate_connection(self.dut, host),
+ "Failed to ping host %s" % host)
+
+ # stop tcpdump
+ pcap_file = self._stop_tcp_dump(self.dut)
+ self.log.info("TCPDUMP file is: %s" % pcap_file)
+
+ # verify DNS queries
+ self._verify_dns_queries_over_tls(pcap_file, use_tls)
+
+ """ Test Cases """
+
+ @test_tracker_info(uuid="2957e61c-d333-45fb-9ff9-2250c9c8535a")
+ def test_private_dns_mode_off_wifi_no_dns_tls_server(self):
+ """ Verify private dns mode off
+
+ Steps:
+ 1. Set private dns mode off
+ 2. Connect to wifi network. DNS/TLS server is not set
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 53
+ """
+ self._test_private_dns_mode(self.wifi_network_no_dns_tls,
+ PRIVATE_DNS_MODE_OFF, False)
+
+ @test_tracker_info(uuid="ea036d22-25af-4df0-b6cc-0027bc1efbe9")
+ def test_private_dns_mode_off_wifi_with_dns_tls_server(self):
+ """ Verify private dns mode off
+
+ Steps:
+ 1. Set private dns mode off
+ 2. Connect to wifi network. DNS server is set to 9.9.9.9, 8.8.8.8
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 53
+ """
+ self._test_private_dns_mode(self.wifi_network_with_dns_tls,
+ PRIVATE_DNS_MODE_OFF, False)
+
+ @test_tracker_info(uuid="4227abf4-0a75-4b4d-968c-dfc63052f5db")
+ def test_private_dns_mode_opportunistic_wifi_no_dns_tls_server(self):
+ """ Verify private dns opportunistic mode
+
+ Steps:
+ 1. Set private dns mode to opportunistic
+ 2. Connect to wifi network. DNS/TLS server is not set
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 53
+ """
+ self._test_private_dns_mode(self.wifi_network_no_dns_tls,
+ PRIVATE_DNS_MODE_OPPORTUNISTIC, False)
+
+ @test_tracker_info(uuid="0c97cfef-4313-4346-b05b-395de63c5c3f")
+ def test_private_dns_mode_opportunistic_wifi_with_dns_tls_server(self):
+ """ Verify private dns opportunistic mode
+
+ Steps:
+ 1. Set private dns mode to opportunistic
+ 2. Connect to wifi network. DNS server is set to 9.9.9.9, 8.8.8.8
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 853
+ """
+ self._test_private_dns_mode(self.wifi_network_with_dns_tls,
+ PRIVATE_DNS_MODE_OPPORTUNISTIC, True)
+
+ @test_tracker_info(uuid="b70569f1-2613-49d0-be49-fd3464dde305")
+ def test_private_dns_mode_strict_wifi_no_dns_tls_server(self):
+ """ Verify private dns strict mode
+
+ Steps:
+ 1. Set private dns mode to strict
+ 2. Connect to wifi network. DNS/TLS server is not set
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 853
+ """
+ self._test_private_dns_mode(self.wifi_network_no_dns_tls,
+ PRIVATE_DNS_MODE_STRICT, True,
+ DNS_QUAD9)
+
+ @test_tracker_info(uuid="85738b52-823b-4c59-a0d5-219e2fab2929")
+ def test_private_dns_mode_strict_wifi_with_dns_tls_server(self):
+ """ Verify private dns strict mode
+
+ Steps:
+ 1. Set private dns mode to strict
+ 2. Connect to wifi network. DNS server is set to 9.9.9.9, 8.8.8.8
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 853
+ """
+ self._test_private_dns_mode(self.wifi_network_with_dns_tls,
+ PRIVATE_DNS_MODE_STRICT, True,
+ DNS_QUAD9)
+
+ @test_tracker_info(uuid="727e280a-d2bd-463f-b2a1-653d4b3f7f29")
+ def test_private_dns_mode_off_lte(self):
+ """ Verify private dns off mode
+
+ Steps:
+ 1. Set private dns mode to off
+ 2. Reset wifi and enable LTE on DUT
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 53
+ """
+ self._test_private_dns_mode(None, PRIVATE_DNS_MODE_OFF, False)
+
+ @test_tracker_info(uuid="b16f6e2c-a24f-4efe-9003-2bfaf28b8d5e")
+ def test_private_dns_mode_opportunistic_lte(self):
+ """ Verify private dns opportunistic mode
+
+ Steps:
+ 1. Set private dns mode to opportunistic mode
+ 2. Reset wifi and enable LTE on DUT
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 853
+ """
+ self._test_private_dns_mode(None, PRIVATE_DNS_MODE_OPPORTUNISTIC, True)
+
+ @test_tracker_info(uuid="edfa7bfe-3e52-46b4-9d72-7c6c300b3680")
+ def test_private_dns_mode_strict_lte(self):
+ """ Verify private dns strict mode
+
+ Steps:
+ 1. Set private dns mode to strict mode
+ 2. Reset wifi and enable LTE on DUT
+ 3. Verify ping works to differnt hostnames
+ 4. Verify that all queries go to port 853
+ """
+ self._test_private_dns_mode(None, PRIVATE_DNS_MODE_STRICT, True,
+ DNS_QUAD9)
+
+ @test_tracker_info(uuid="1426673a-7728-4df7-8de5-dfb3529ada62")
+ def test_dns_server_link_properties_strict_mode(self):
+ """ Verify DNS server in the link properties when set in strict mode
+
+ Steps:
+ 1. Set DNS server hostname in Private DNS settings (stict mode)
+ 2. Verify that DNS server set in settings is in link properties
+ 3. Verify for WiFi as well as LTE
+ """
+ # start tcpdump on device
+ self._start_tcp_dump(self.dut)
+
+ # set private DNS to strict mode
+ self.dut.droid.setPrivateDnsMode(True, DNS_QUAD9)
+ mode = self.dut.droid.getPrivateDnsMode()
+ specifier = self.dut.droid.getPrivateDnsSpecifier()
+ asserts.assert_true(
+ mode == PRIVATE_DNS_MODE_STRICT and specifier == DNS_QUAD9,
+ "Failed to set private DNS strict mode")
+
+ # connect DUT to wifi network
+ wutils.wifi_connect(self.dut, self.wifi_network_no_dns_tls)
+ for host in self.ping_hosts:
+ wutils.validate_connection(self.dut, host)
+
+ # DNS server in link properties for wifi network
+ link_prop = self.dut.droid.connectivityGetActiveLinkProperties()
+ dns_servers = link_prop['DnsServers']
+ wifi_dns_servers = [each for lst in dns_servers for each in lst]
+ self.log.info("Link prop: %s" % wifi_dns_servers)
+
+ # DUT is on LTE data
+ wutils.reset_wifi(self.dut)
+ time.sleep(1) # wait till lte network becomes active
+ for host in self.ping_hosts:
+ wutils.validate_connection(self.dut, host)
+
+ # DNS server in link properties for cell network
+ link_prop = self.dut.droid.connectivityGetActiveLinkProperties()
+ dns_servers = link_prop['DnsServers']
+ lte_dns_servers = [each for lst in dns_servers for each in lst]
+ self.log.info("Link prop: %s" % lte_dns_servers)
+
+ # stop tcpdump on device
+ pcap_file = self._stop_tcp_dump(self.dut)
+ self.log.info("TCPDUMP file is: %s" % pcap_file)
+
+ # Verify DNS server in link properties
+ asserts.assert_true(DNS_QUAD9 in wifi_dns_servers,
+ "Hostname not in link properties - wifi network")
+ asserts.assert_true(DNS_QUAD9 in lte_dns_servers,
+ "Hostname not in link properites - cell network")
+
+ @test_tracker_info(uuid="525a6f2d-9751-474e-a004-52441091e427")
+ def test_dns_over_tls_no_reset_packets(self):
+ """ Verify there are no TCP packets with RST flags
+
+ Steps:
+ 1. Enable opportunistic or strict mode
+ 2. Ping hosts and verify that there are TCP pkts with RST flags
+ """
+ # start tcpdump on device
+ self._start_tcp_dump(self.dut)
+
+ # set private DNS to opportunistic mode
+ self.dut.droid.setPrivateDnsMode(True)
+ mode = self.dut.droid.getPrivateDnsMode()
+ asserts.assert_true(mode == PRIVATE_DNS_MODE_OPPORTUNISTIC,
+ "Failed to set private DNS opportunistic mode")
+
+ # connect DUT to wifi network
+ wutils.wifi_connect(self.dut, self.wifi_network_with_dns_tls)
+ for host in self.ping_hosts:
+ wutils.validate_connection(self.dut, host)
+
+ # stop tcpdump on device
+ pcap_file = self._stop_tcp_dump(self.dut)
+ self.log.info("TCPDUMP file is: %s" % pcap_file)
+
+ # check that there no RST TCP packets
+ self._verify_rst_packets(pcap_file)
+
+ @test_tracker_info(uuid="af6e34f1-3ad5-4ab0-b3b9-53008aa08294")
+ def test_private_dns_mode_strict_invalid_hostnames(self):
+ """ Verify that invalid hostnames are not saved for strict mode
+
+ Steps:
+ 1. Set private DNS to strict mode with invalid hostname
+ 2. Verify that invalid hostname is not saved
+ """
+ invalid_hostnames = ["!%@&!*", "12093478129", "9.9.9.9", "sdkfjhasdf"]
+ for hostname in invalid_hostnames:
+ self.dut.droid.setPrivateDnsMode(True, hostname)
+ mode = self.dut.droid.getPrivateDnsMode()
+ specifier = self.dut.droid.getPrivateDnsSpecifier()
+ wutils.wifi_connect(self.dut, self.wifi_network_no_dns_tls)
+ asserts.assert_true(
+ mode == PRIVATE_DNS_MODE_STRICT and specifier != hostname,
+ "Able to set invalid private DNS strict mode")