Skip to content

Instantly share code, notes, and snippets.

@simonbru
Forked from cdhowie/README.md
Created June 6, 2016 09:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonbru/5ec4359166d961d095b77541be699f7d to your computer and use it in GitHub Desktop.
Save simonbru/5ec4359166d961d095b77541be699f7d to your computer and use it in GitHub Desktop.
DNS proxy to fix Netflix stupidity

fix-netflix-dns

This is a DNS server that intentionally returns an empty result set for any AAAA query for netflix.com or any subdomain thereof. The intent is to force Netflix to use IPv4 in cases where Netflix has blocked IPv6 access -- specifically, for Hurricane Electric users who find Netflix giving them the error:

You seem to be using an unblocker or proxy. Please turn off any of these services and try again. For more help, visit netflix.com/proxy.

Note that this server does not in any way circumvent Netflix's block against these IPv6 address ranges; all it does is force Netflix to use the IPv4 Internet.

I also considered null-routing the Netflix IPv6 address ranges, but many (all?) Netflix services are deployed in Amazon Web Services, so there's no good way to reliably null-route Netflix without null-routing all of AWS. Dealing with the problem in the DNS process allows us to precisely block exactly what we want blocked (*.netflix.com) and nothing that we don't want blocked.

Dependencies

The only dependency is Twisted Names for Python.

Configuration

Open server.py and configure the OPTIONS dict according to the comments. Here you will be able to configure which address and port this server binds to, as well as which DNS server it will forward requests to.

Note that if you are using dnsmasq and its built-in DHCP server, and you reconfigure it to listen on a port other than 53 for DNS, it will stop advertising itself as a DNS server to DHCP clients. Put dhcp-option=6,$IP in dnsmasq.conf (changing $IP to the server's LAN IP) to fix this. Note that this will not work when dnsmasq is serving multiple different DHCP ranges, unless you use an IP address that is reachable from all of those networks.

Installation

Clone this repository into /opt/fix-netflix-dns. (You can clone as any user, but the server must be run as root in order to bind to port 53.)

Run the following commands to install the systemd service:

cd /etc/systemd/system
ln -s /opt/fix-netflix-dns/fix-netflix-dns.service
systemctl enable fix-netflix-dns.service
systemctl start fix-netflix-dns.service
[Unit]
Description=DNS server that intentionally fails to resolve AAAA for Netflix
After=network.target
Wants=network.target
[Service]
ExecStart=/opt/fix-netflix-dns/server.py
Restart=always
RestartSec=5
[Install]
WantedBy=default.target
#!/usr/bin/env python
OPTIONS = {
# Port to bind to.
'listen-port': 53,
# Address to bind to. '::' will bind IPv6; make sure bindv6only is 0 in
# your sysctl configuration for this binding to service IPv4 clients, too.
# ("cat /proc/sys/net/ipv6/bindv6only" to verify.)
'listen-address': '::',
# Here is where you configure what DNS server to proxy to. You must
# specify exactly one of the following options; comment out the other.
# Specify one or more servers to proxy to. Note that Twisted may not be
# happy if you use an IPv6 address.
# 'upstream-dns': [('127.0.0.1', 10053)],
# Specify a resolv.conf file from which to read upstream nameservers. As
# noted above, if you have any upstream IPv6 servers, Twisted may not be
# happy about that.
# 'resolv-conf': '/etc/resolv.conf',
}
from twisted.internet import reactor, defer
from twisted.names import client, dns, error, server
class BlockNetflixAAAAResolver(object):
def __shouldBlock(self, query):
penultimateDomainPart = query.name.name.split('.')[-2]
return query.type == dns.AAAA and penultimateDomainPart in ('netflix', 'nflximg')
def query(self, query, timeout=None):
if self.__shouldBlock(query):
return defer.succeed(([], [], []))
else:
return defer.fail(error.DomainError())
def main():
factory = server.DNSServerFactory(
clients=[
BlockNetflixAAAAResolver(),
client.Resolver(
servers=OPTIONS.get('upstream-dns', None),
resolv=OPTIONS.get('resolv-conf', None)
)
]
)
protocol = dns.DNSDatagramProtocol(controller=factory)
reactor.listenUDP(OPTIONS['listen-port'], protocol, interface=OPTIONS['listen-address'])
reactor.listenTCP(OPTIONS['listen-port'], factory, interface=OPTIONS['listen-address'])
reactor.run()
if __name__ == '__main__':
raise SystemExit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment