rezsez

I recently got a Samsung 'smart' TV which is very nice to look at.

Unfortunately there have been numerous security and privacy issues with smart TVs of all kinds, and Samsung in particular. So being predictably paranoid I immediately blocked the TV’s IP address on my router to stop it getting to the internet.

As it turns out however, the built-in Netflix app on the TV is my only option for 4k Netflix (my HTPC was out due to not having a Kaby Lake chip).

So I ended up allowing the TV get out to the internet, despite my misgivings.

But this got me thinking - could I somehow limit its access to just Netflix? I initally tried an IP-based ACL on the router, but there were some issues with that so I began to wonder was there a DNS-based approach I could take?

Enter DNS RPZ

I am relatively familiar with ISC Bind having used it down through the years, and one feature in particular suggested it might help - Response Policy Zones.

Basically RPZ can be used to create a DNS "firewall," limiting what domains can be resolved. There is plenty of information online about how this can be set up, however I didn’t find anything specifically explaining how to do what I needed (a total blacklist with only a very small whitelist of domains).

Turns out it’s fairly easy to do.

Bind Configuration

The first step is to get a basic Bind resolver up and running. I did this with a Ubuntu 16.04 system.

I then configured a 'response-policy' block in the 'options' section of my named.conf (on my particular system I did it in /etc/bind/named.conf.options). This lists two RPZ zones which are used to define what queries to filter. The key thing here is that RPZ checks zones in the order they are listed - this is key to creating a whitelist as opposed to a blacklist. A single line is required:

response-policy { zone "rpz.whitelist"; zone "rpz"; };

All queries will then be filtered based on the response policy zones listed. If a match is found in the first (rpz.whitelist) then that will be used, otherwise the second one (rpz) will be checked.

The Bind server needs to be configured as authorititive master for these zones, similar to a standard zone, although with "allow-query" set to none. Again this is in named.conf (in my case /etc/bind/named.conf.default-zones):

zone "rpz.whitelist" {
   type master;
   file "/etc/bind/db.rpz.whitelist";
   allow-query { none; };
};
zone "rpz" {
   type master;
   file "/etc/bind/db.rpz";
   allow-query { none; };
};

As can be seen the zone definitions reference the location of the zone files for each. The files are created as follows, using the RPZ syntax. The first zone, rpz.whitelist, is where to define the domains we want to allow. In my case it looks like this:

/etc/bind/db.rpz.whitelist:

$TTL 60
@            IN    SOA  localhost. root.localhost.  (
                      4   ; serial
                      3H  ; refresh
                      1H  ; retry
                      1W  ; expiry
                      1H) ; minimum

                      IN     NS      localhost.

 netflix.com                 CNAME   rpz-passthru.
 *.netflix.com               CNAME   rpz-passthru.

 nflximg.com                 CNAME   rpz-passthru.
 *.nflximg.com               CNAME   rpz-passthru.

 nflximg.net                 CNAME   rpz-passthru.
 *.nflximg.net               CNAME   rpz-passthru.

Note that for each domain I have included a record for the domain itself, and also a wildcard entry to catch all sub-domains. In each case they are listed as CNAME records pointing to rpz-passthru, which is the RPZ syntax to tell Bind to allow queries for them.

The second RPZ zone file is created as follows. This is configured for all sub-domains of the root zone, with a CNAME pointing to "." (which tells RPZ to return NXDOMAIN for such a lookup). As the trailing dot (root zone) is left out of entries in RPZ zones, an asterix on it’s own is all that is needed to represent subdomains of the DNS root:

/etc/bind/db.rpz:

$TTL 60
@            IN    SOA  localhost. root.localhost.  (
                     4   ; serial
                     3H  ; refresh
                     1H  ; retry
                     1W  ; expiry
                     1H) ; minimum

             IN      NS    localhost.

*                    CNAME .

With the config in place I was able to reload Bind and check if it was working.

Results

So does it work. If I try to resolve a random domain I get an NXDOMAIN response:

topranks@dnsvm:~$ dig A www.samsung.com @localhost

; <<>> DiG 9.10.3-P4-Ubuntu <<>> A www.samsung.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 14003
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.samsung.com.		IN	A

But if I try for a sub-domain of netflix.com I get a valid response:

topranks@dnsvm:~$ dig A www.netflix.com @localhost

; <<>> DiG 9.10.3-P4-Ubuntu <<>> A www.netflix.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59390
;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.netflix.com.		IN	A

;; ANSWER SECTION:
www.netflix.com.	1800	IN	CNAME	www.geo.netflix.com.
www.geo.netflix.com.	1800	IN	CNAME	www.eu-west-1.prodaa.netflix.com.
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.209.165.126
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.19.164.15
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.208.178.51
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.209.156.83
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.208.202.184
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.208.15.72
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.208.81.52
www.eu-west-1.prodaa.netflix.com. 60 IN	A	52.208.174.58

Additions for my Smart TV case

In addition to the above I changed the ACL for traffic coming from the TV to only allow TCP on ports 80 and 443. This is enough for Netflix, but importantly blocks the TV from using any external DNS (even in normal circumstances it looks like it uses 8.8.8.8 in addition to any DNS server you give it yourself.)

Finally on the TV I changed the DNS server and sure enough the TV thinks something is wrong with DNS:

Samsung Error Message

So far so good, and yes the Netflix app still works fine. Looking closely at my Bind logs I can see what’s happening:

Apr 20 17:42:27 dnsvm named[7369]: 20-Apr-2017 17:42:27.003 queries: info: client 192.168.240.42#40665 (art-0.nflximg.net): query: art-0.nflximg.net IN A + (192.168.240.32)
Apr 20 17:42:27 dnsvm named[7369]: 20-Apr-2017 17:42:27.003 rpz: info: client 192.168.240.42#40665 (art-0.nflximg.net): rpz QNAME PASSTHRU rewrite art-0.nflximg.net via art-0.nflximg.net.rpz.whitelist
Apr 20 17:42:27 dnsvm named[7369]: 20-Apr-2017 17:42:27.766 queries: info: client 192.168.240.42#34179 (ns11.whois.co.kr): query: ns11.whois.co.kr IN A + (192.168.240.32)
Apr 20 17:42:27 dnsvm named[7369]: 20-Apr-2017 17:42:27.766 rpz: info: client 192.168.240.42#34179 (ns11.whois.co.kr): rpz QNAME NXDOMAIN rewrite ns11.whois.co.kr via ns11.whois.co.kr.rpz
Apr 20 17:42:29 dnsvm named[7369]: 20-Apr-2017 17:42:29.031 queries: info: client 192.168.240.42#59989 (time.samsungcloudsolution.com): query: time.samsungcloudsolution.com IN A + (192.168.240.32)
Apr 20 17:42:29 dnsvm named[7369]: 20-Apr-2017 17:42:29.031 rpz: info: client 192.168.240.42#59989 (time.samsungcloudsolution.com): rpz QNAME NXDOMAIN rewrite time.samsungcloudsolution.com via time.samsungcloudsolution.com.rpz
Apr 20 17:42:29 dnsvm named[7369]: 20-Apr-2017 17:42:29.033 queries: info: client 192.168.240.42#36357 (time.samsungcloudsolution.com): query: time.samsungcloudsolution.com IN A + (192.168.240.32)
Apr 20 17:42:29 dnsvm named[7369]: 20-Apr-2017 17:42:29.033 rpz: info: client 192.168.240.42#36357 (time.samsungcloudsolution.com): rpz QNAME NXDOMAIN rewrite time.samsungcloudsolution.com via time.samsungcloudsolution.com.rpz

So yeah, probably not ideal as the TV can still get out to the internet, at least on 80 and 443 TCP, but without DNS I’ve hopefully limited how much it can do.

comments powered by Disqus