• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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