Creating a Netflix USA Proxy on Azure

Here we go. A Simple guide to setting up a Netflix DNS/Proxy using Azure.

First how it works, Netflix, Hulu etc all use 3rd party content delivery networks (CDN), Akamai in most cases, but the ‘checks’ for country location are done at the service hosts servers. So they check who you are, where you are and then pass you off to the CDN to actually get the content. So the checks are done only once (well multiple times actually, but hey) on specific DNS Names. So if we ‘look’ like we are in the right country when we speak to those services, we an get the CDN content directly.

This has a benefit that the large amounts of data (Video/Music content) that’s delivered by the CDN gets sent directly to the client machine/console/TV directly, with no proxy in the way to slow things down, however the dns names that actually do the check get proxied via a machine that’s in the country it needs to be.

Let’s get going then.

1First lets create an Azure Linux VM. I’ve selected the Ununtu LTS Server

Setup the settings, I picked a fixed external IP Address is it will make life easier in the long run.

2After it’s all installed, bring up the settings and add the required endpoints, we need UDP 53 (DNS) and TCP 80/443 added. There should already be the SSH port 22 TCP one created, but if not add that one too.

Next we need Putty Downloaded so we can SSH into the VM. So fire that up, create a new profile with the service name as the connection and login.

Lets make sure everything is upto date, so sudo apt-get update then sudo apt-get upgrade then sudo apt-get install dpkg-dev cdbs debhelper dh-autoreconf libev-dev libpcre3-dev pkg-config libudns-dev git

Next we need to install Bind, so sudo apt-get install bind9

Now we need to mod the config for bind, so sudo nano /etc/bind/named.conf.options

options {
directory “/var/cache/bind”;

forwarders {
8.8.8.8;
8.8.4.4;
};

auth-nxdomain no; # conform to RFC1035
listen-on-v6 { any; };
allow-query { trusted; };
allow-recursion { trusted; };
recursion yes;
dnssec-enable no;
dnssec-validation no;
};

That should setup the server to use the Google DNS Servers.

Then we need to setup some security, so sudo nano /etc/bind/named.conf.local

//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include “/etc/bind/zones.rfc1918”;

include “/etc/bind/rndc.key”;

acl “trusted” {
10.0.0.4; // Local IP address of VM
127.0.0.1;
104.45.147.52; // External Ip address of the VM
86.0/24; // Client – Add the IP address of the client range (ISP Range).
};

include “/etc/bind/zones.override”;

logging {
channel bind_log {
file “/var/log/named/named.log” versions 5 size 30m;
severity info;
print-time yes;
print-severity yes;
print-category yes;
};
category default { bind_log; };
category queries { bind_log; };
};

Next up lets setup the overides sudo nano /etc/bind/zones.override

zone “hulu.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “huluim.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “netflix.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “abc.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “abc.go.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “fox.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “link.theplatform.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “nbc.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “nbcuni.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “pandora.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “broadband.espn.go.com.” {
type master;
file “/etc/bind/db.override”;
};
zone “ip2location.com.” {
type master;
file “/etc/bind/db.override”;
};

Then sudo nano /etc/bind/db.override

;
; BIND data file for overridden IPs
;
$TTL 86400
@ IN SOA ns1 root (
2012100401 ; serial
604800 ; refresh 1w
86400 ; retry 1d
2419200 ; expiry 4w
86400 ; minimum TTL 1d
)

; need at least a nameserver
IN NS ns1
; specify nameserver IP address
ns1 IN A 104.x.x.x ; external IP from Azure
; provide IP address for domain itself
@ IN A 104.x.x.x ; external IP from Azure
; resolve everything with the same IP address as ns1
* IN A 104.x.x.x ; external IP from Azure

Righto, now lets install the SNI-Proxy, this does the initial conversation with the overridden DNS names.

Lets make sure we are in our home so cd ~ Then lets sudo git clone http://github.com/dlundquist/sniproxy.git then cd sniproxy/

Now lets build the package so we can install it, we build it with sudo dpkg-buildpackage then install it with cd ~ then sudo dpkg -i sniproxy_0.4.0_amd64.deb (obviously change version number if you have later release than I used here)

Then let’s turn it on, sudo nano /etc/default/sniproxy and change ENABLED from 0 to 1 and then sudo nano /etc/sniproxy.conf and make sure that the listener for port 80 and 443 is defined (ive used a * listener and then add the hosts we need to cache to the table, so my config looks like this (bolded the changes)

# sniproxy example configuration file
# lines that start with # are comments
# lines with only white space are ignored

user daemon

# PID file
pidfile /var/run/sniproxy.pid

error_log {
# Log to the daemon syslog facility
syslog daemon

# Alternatively we could log to file
#filename /var/log/sniproxy/sniproxy.log

# Control the verbosity of the log
priority notice
}

# blocks are delimited with {…}
listen 80 {
proto http
table http_hosts
# Fallback backend server to use if we can not parse the client request
fallback localhost:8080

access_log {
filename /var/log/sniproxy/http_access.log
priority notice
}
}

listen 443 {
proto tls
table https_hosts

filename /var/log/sniproxy/https_access.log
priority notice
}
}

# named tables are defined with the table directive
table http_hosts {
example.com 192.0.2.10:8001
example.net 192.0.2.10:8002
example.org 192.0.2.10:8003

# pattern:
# valid Perl-compatible Regular Expression that matches the
# hostname
#
# target:
# – a DNS name
# – an IP address (with optional port)
# – ‘*’ to use the hostname that the client requested
#
# pattern target
#.*\.itunes\.apple\.com$ *:443
#.* 127.0.0.1:4443
}

# named tables are defined with the table directive
table https_hosts {
# When proxying to local sockets you should use different tables since the
# local socket server most likely will not autodetect which protocol is
# being used
example.org unix:/var/run/server.sock
}

# if no table specified the default ‘default’ table is defined
table {
# if no port is specified default HTTP (80) and HTTPS (443) ports are
# assumed based on the protocol of the listen block using this table

#
# pattern target
#.*\.itunes\.apple\.com$ *:443
#.* 127.0.0.1:4443
}

# named tables are defined with the table directive
table https_hosts {
# When proxying to local sockets you should use different tables since the
# local socket server most likely will not autodetect which protocol is
# being used
example.org unix:/var/run/server.sock
}

# if no table specified the default ‘default’ table is defined
table {
# if no port is specified default HTTP (80) and HTTPS (443) ports are
# assumed based on the protocol of the listen block using this table

(hulu|huluim)\.com *
abc\.(go\.)?com *
(nbc|nbcuni)\.com *
netflix\.com *
ip2location\.com *

}

That should do it, now we just need to start the relevant services, so sudo service sniproxy start and sudo service bind9 start

That should get you up and running, now all you need to do is set the DNS server of the device you want to look like it’s coming from the USA to the external IP address of your Azure host, and hey presto, Magically your in the USA…. or whatever country you have the Azure server hosted in that is.