Friday, 7 February 2014

DIY clone of Netflix Tunlr/Unblock-Us/UnoTelly on cheap US based VPS



TL;DR head to netflix-proxy on GitHub or subscribe to Unzoner VPN service to un-block:





(for posterity) If you are in the UK and would like to access Netflix US catalogue, which is about three times bigger, read on.

There are commercial services out there, such as Unblock-Us and Smart DNS Proxy to name a few, so you could pay for the privilege to use their services or you can knock together a similar solution quickly yourself for a cost of a cheap Virtual Private Server (VPS). How cheap, depends on where you decide to host your VPS.
In essence, the following solution works by selectively proxying only certain requests (*.netflix.com) via a server located in the US, thus bypassing Netflix application level geo-restrictions. This solution does not proxy the actual video delivery, which uses different domain(s).

Please note, this basic solution doesn't work on devices which don't support the use of SNI during SSL handshake (e.g. Netflix on Chromecast). To support such devices, you will need to extend this solution to selectively proxy individual Netflix hosts using something akin to HAProxy, go with a commercial provider or switch to black.box unzoner.

Also, if you are looking how to watch BBC iPlayer abroad, please see the flowing guide: http://blog.belodedenko.me/2014/12/watch-bbc-iplayer-in-australia-for-free.html

Update 04/2015: You can also watch HBO NOW on your Apple TV outside the US using this solution, here's how: http://blog.belodedenko.me/2015/04/watch-hbo-now-in-uk-for-free-apple.html

Update 05/2015: You can also watch Hulu Plus on your Apple TV outside the US using this solution, here's how: http://anton.belodedenko.me/watch-hulu-plus-outside-of-the-us/

However, if you still want to build the system manually, perhaps to understand how it all works, please read on...

Prerequisites


You'll need the following:
  • A working Internet connection at home
  • A Netflix subscription
  • A US based VPS with root access and clean CentOS x86 6.x image
  • Basic knowledge in navigating a Linux console
For my hosting I choose Digital Ocean with the VPS hosted in a New York data centre for $5 USD per month. If you sign up with the above link, you will receive $10 USD credit, which is enough for two months hosting. Note, Netflix has blocked Digital Ocean IP address ranges, so don't expect it to work. Other services may still work though.

Configuration


The configuration depends on the following two components:
  • DNS server
  • HTTP/SSL proxy
For the purpose of this demo, we assume your VPS's public Internet IP is 162.243.x.y and your host is called myhost. We also assume your ISP has assigned 86.144.x.y to your home router.

You can check what your IP is by going to http://www.ifconfig.io/. Note, if you ISP assigns you a dynamic IP, you will need to update your configuration every time this changes. Better ask them for a static IP address. When creating your configuration files, please change the place holder IPs to your actual IPs.

Base VPS Deployment


This step depends on the VPS provider you choose, but broadly consists of the following steps:
  • Create account with VPS provider
  • Deploy a CentOS x64 6.x image to a US based data centre, ideally on the east coast.
Once your VPS server is created, you will get a public IP address and SSH credentials to use to login.

First, establish an SSH session to your server and install additional repositories:
[root@myhost ~]# yum -y install epel-release
[root@myhost ~]# yum -y update

Install certain pre-requisites to make your life a little easier:
[root@myhost ~]# yum install openssl vim git wget curl bind-utils telnet -y

Install development tools to enable you to build packages later:
[root@myhost ~]# yum groupinstall "Development Tools" -y
[root@myhost ~]# yum install rpmbuild autoconf automake curl libev libev-devel pcre pcre-devel perl udns-devel

IP Tables (firewall)


Since our VPS is on a public Internet, we are going to firewall it off from all the unpleasantness out there. Add rules to allow DNS, HTTP and HTTPS inbound from your home's public IP:
[root@myhost ~]# iptables -A INPUT -s 86.144.x.y/32 -p udp -m udp --dport 53 -j ACCEPT
[root@myhost ~]# iptables -A INPUT -s 86.144.x.y/32 -p tcp -m tcp --dport 80 -j ACCEPT
[root@myhost ~]# iptables -A INPUT -s 86.144.x.y/32 -p tcp -m tcp --dport 443 -j ACCEPT
[root@myhost ~]# service iptables save
[root@myhost ~]# service iptables restart

BIND (DNS server)


BIND is going to be our DNS server. It will respond with our VPS IP to DNS requests for netflix.com domain. Note, we are configuring the DSN server to run in a chroot jail and as a non-root user, to provide added security and minimise the potential effects of a security compromise.

Install BIND:
[root@myhost ~]# yum install bind -y

Edit your /etc/named.conf and make it look as follows:
options {
        listen-on port 53 { any; };
        listen-on-v6 port 53 { any; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";

        allow-query { trusted; };
        allow-recursion { trusted; };
        allow-transfer  { none; };
        recursion yes;
        additional-from-auth yes;
        additional-from-cache yes;

        auth-nxdomain no;    # conform to RFC1035
        dnssec-enable yes;
        dnssec-validation yes;
        dnssec-lookaside auto;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";
        managed-keys-directory "/var/named/dynamic";

        forwarders {
                8.8.8.8;
                8.8.4.4;
        };
};

acl "trusted" {
        any;
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

zone "." IN {
        type hint;
        file "named.ca";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
include "/etc/named/zones.override";

Edit your /etc/named/db.override and make it look as follows:
$TTL  86400

@   IN  SOA ns1 root (
            YYYYMMDD01  ; serial
            604800      ; refresh 1w
            86400       ; retry 1d
            2419200     ; expiry 4w
            86400       ; minimum TTL 1d
            )

    IN  NS  ns1
ns1 IN  A   162.243.x.y
@   IN  A   162.243.x.y
*   IN  A   162.243.x.y

* Note, change the above IP address to your the public IP of your VPS and update the datestamp. 

Edit your /etc/named/zones.override and make it look as follows:
zone "netflix.com." {
    type master;
    file "/etc/named/db.override";
};

Note, you may need to change the ownership of the new files you created from root to named:
[root@myhost ~]# chown named:named /etc/named/zones.override
[root@myhost ~]# chown named:named /etc/named/db.override

Install BIND (chroot package):
[root@myhost ~]# yum install bind-chroot -y

Finally, start BIND:
[root@myhost ~]# rndc-confgen -a -r /dev/urandom -t /var/named/chroot
[root@myhost ~]# chkconfig named on
[root@myhost ~]# service named start

From one of your home machines, run the following quick test:
$ nslookup www.netflix.com 162.243.x.y
Server:         162.243.x.y
Address:        162.243.x.y#53

Name:   www.netflix.com
Address: 162.243.x.y

You should get the IP address of your VPS in the DNS response.

SNI Proxy (HTTP/SSL proxy)


SNI Proxy is going to be our HTTP/SSL proxy, which supports for TLS SNI extensions.

Build and install SNI Proxy:
[root@myhost ~]# cd /opt
[root@myhost ~]# git clone https://github.com/dlundquist/sniproxy.git
[root@myhost ~]# cd ./sniproxy
[root@myhost ~]# ./autogen.sh && ./configure && make dist
[root@myhost ~]# rpmbuild --define "_sourcedir `pwd`" -ba --nodeps redhat/sniproxy.spec
[root@myhost ~]# yum install $(ls /root/rpmbuild/RPMS/x86_64/sniproxy-[0-9]*.rpm) -y

Note: if the RPM fails to install, check the exact name of the file in the /root/rpmbuild/RPMS/x86_64/directory.

Also, please review the ./configure command output to make sure LIBUDNS or libudns is detected, if it hasn't, you will not be able to get SNI Proxy to work with the below configuration file. On a Red Hat/CentOS server, the library should be available from EPEL repository (yum install udns-devel), however for other distributions, you will need to build and install it manually.

Edit your sniproxy.conf and make it look as follows:
[root@myhost ~]# vim /etc/sniproxy.conf

user daemon
pidfile /var/tmp/sniproxy.pid

error_log {
        filename /var/log/sniproxy_error.log
        priority notice
}

listener 162.243.x.y 80 {
        proto http
        access_log {
                filename /var/log/sniproxy_access.log
        }
}

listener 162.243.x.y 443 {
        proto tls
        access_log {
                filename /var/log/sniproxy_access.log
        }
}

table {
        netflix\.com *
}

Finally, install the start-up script and start SNI Proxy:
[root@myhost ~]# cp ./redhat/sniproxy.init /etc/init.d/sniproxy
[root@myhost ~]# chmod +x /etc/init.d/sniproxy
[root@myhost ~]# chkconfig sniproxy on
[root@myhost ~]# service sniproxy start

Note, if the proxy complains about ports being in use, check if you got another web server already running and if so, disable it or move it to a different port.

From one of your home machines, run the following quick test:
$ telnet 162.243.x.y 80
Trying 162.243.x.y...
Connected to 162.243.x.y.
Escape character is '^]'.
^C
Connection closed by foreign host.

$ openssl s_client -servername www.netflix.com -connect 162.243.x.y:443
CONNECTED(00000003)
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=CALIFORNIA/L=Los Gatos/O=Netflix, Inc./OU=Operations/CN=www.netflix.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MII...

You should get a socket connection on port 80 and get an SSL handshake with Netflix.

Putting It All Together


The last step is to change the DNS server on the device you are planning to watch US Netflix on. Set it to your VPS public IP (i.e. 162.243.x.y) Fire up Netflix and you should see the US catalogue and if you do - enjoy!

Note, this won't work on devices which don't support the use of SNI during SSL handshake, you'll have no choice but to use a system described in this guide or use black.box unzoner.

References


I've used the following reference material to prepare the solution described in this article. Many thanks to the respective authors.


Friday, 20 September 2013

Archer Season 4 in the UK: A legitimate case for piracy?



Archer Season 4 in the UK: A legitimate case for piracy?

After watching Archer seasons 1-3, my wife and I naturally moved on to season 4. After watching the first four episodes we realised that then next available episode in the sequence was episode 8. So the natural question is where are episodes 6 and 7?

A quick search reveals that neither Netflix UK, blinkbox nor iTunes in the UK currently have these episodes even though they've aired in the US in February according to the Wikipedia article.


Archer Season 4: missing episodes

If you are in the US however, there is no problem - all the episodes are available to download through iTunes store US:


Archer Season 4: full set in iTunes Store (US)

So, why is this content, long available in one region, missing from another and on top of that, aired out of order? A scheduling glitch or some kind of outstanding rights issue? I am going to put my consumer hat on now and stay that "I simply do not care" either way. I'd like to pay for and watch my episodes, in the correct sequence and in timely manner and if I can't, I will take my money elsewhere.

I propose that this is exactly the case where people who would otherwise pay for content, would turn to alternative sourcing methods. In this case, the entire season 4 in full HD can be downloaded in minutes, with your favourite BitTorrent client, using one of the many trackers set up for this purpose.

So, why wait?

-- ab1



Wednesday, 10 July 2013

Dynamic IPv6 updates using ddclient for records hosted on Hurricane Electric DNS



Overview


I have a small home network with a number of internal servers.  After enabling IPv6, all of the internal machines now have a public, DHCP assigned IP.  It would be nice to have these IPs update automatically in the DNS when they change.







Prerequisites


You'll need the following:

Configuration


DDNS

In this section you will create a new AAAA record in your domain hosted with HE DNS service and set it up for DDNS updates.
  1. Login to on Hurricane Electric Hosted DNS service portal.
  2. Edit the zone for your domain name (e.g. mydomain.me).
  3. Create a new AAAA host record for your host (e.g. myddnshost.mydomain.me).
  4. Make sure to tick the box "Enable entry for dynamic dns".
  5. Click the "refresh" icon in the DDNS column next to your AAAA record.
  6. Click "Generate a key", record it somewhere and click "Submit".

DDClient


The current version of ddclient (3.8.1) does not support updating AAAA records.  You will need to patch it using a patch written by Eduardo TrĂ¡pani.

Since the patch cannot be applied in its current form to the present release of ddclient, I've included a patched copy here so you can update your ddclient installation as follows:
$ cd /tmp  
$ wget https://www.dropbox.com/s/fwkjh1jlt4rlu5p/ddclient.ipv6  
$ cp ddclient.ipv6 /usr/sbin  
$ mv /usr/sbin/ddclient /usr/sbin/ddclient.ipv4  
$ ln -s /usr/sbin/ddclient.ipv6 /usr/sbin/ddclient 
$ chmod 755 /usr/sbin/ddclient.ipv6
$ service ddclient restart  

Next, update your ddclient.conf to include a block to update your DDNS record:
# Configuration file for ddclient  
#  
# /etc/ddclient.conf  
   
daemon=300                  # check every 5 minutes  
syslog=yes                  # log update msgs to syslog  
#mail=root                  # mail all msgs to root  
#mail-failure=root          # mail failed update msgs to root  
pid=/var/run/ddclient.pid   # record PID in file.  
   
usev6=if, if=eth0  
protocol=dyndns2,                            \  
server=dyn.dns.he.net,                       \  
login=myddnshost.mydomain.me                 \  
password=myddnshost.mydomain.me's API key    \  
myddnshost.mydomain.me

Note, you can add multiple hosts to update in your ddclient.conf.


Testing


Renew your DHCP lease and somehow force an IP change or just set your host's IP manually in the HE DNS portal to something other than what it is currently.

Then, run a manual ddclient update as follows:

$ ddclient -force  
 SUCCESS: updating myddnshost.mydomain.me: good: IP address set to 2001:470:890a:bcd::1000  

Check to make sure your AAAA record has been updated:
$ dig aaaa myddnshost.mydomain.me  
...  
;; QUESTION SECTION:  
;myddnshost.mydomain.me.      IN   AAAA  
   
;; ANSWER SECTION:  
myddnshost.mydomain.me. 300   IN   AAAA  2001:470:890a:bcd::1000  


References


I've used the following reference material to prepare the solution described in this article.  Many thanks to the respective authors.


Saturday, 29 June 2013

FortiGate with ZTE MF100 3G USB modem and T-Mobile for a backup Internet connection



Overview


I found an old O2 3G USB  broadband Internet dongle sitting around in a box and decided to put it to good use.  Here is how I've used it to act as a backup for my main wired broadband Internet connection at home.


Prerequisites


You will require the following:
  • Properly functioning broadband Internet connection and LAN/WLAN at home.
  • FortiGate firewall running FortiOS 5.0 (I've used v5.0,build0208 GA Patch 3).
  • A mobile broadband Internet dongle (USB) with a valid SIM (I used a ZTE MF100 from O2).
  • Mobile Internet APN, username and password (for T-Mobile APN=everywhere; username=eesecure; password=secure).
Note, your USB modem may be provider locked, like mine was to O2.  If it is, you will need to unlock it first, by either calling your provider and paying them some of your hard-earned cash, or using this software.

Configuration


Insert your 3G USB dongle with a SIM card into one of the spare USB ports on the FortiGate firewall and reboot it.  If you don't reboot the firewall, the USB modem may not get detected properly.

Custom Modem Definition


To enable modem settings, run the following commands on the console:
 config system modem   
  set status enable   
 end  

Unless your modem is on the supported list, you will need to add a custom entry.  Have a look through the list in the GUI first to see if your modem is listed and if it is, select it:
Network -> Modem -> Configure Modem

Otherwise, identify your modem via a USB bus scan:
 # fnsysctl cat /proc/bus/usb/devices    
 ...    
 T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 5 Spd=480 MxCh= 0    
 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1    
 P: Vendor=19d2 ProdID=0017 Rev= 0.00    
 S: Manufacturer=ZTE,Incorporated    
 S: Product=ZTE WCDMA Technologies MSM    
 S: SerialNumber=P671A1ZTED010000    
 C:* #Ifs= 5 Cfg#= 1 Atr=e0 MxPw r=500mA    
 I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial    
 E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms    
 E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms    
 ...   

Then, using the Vendor and ProdID from the output above, create a custom modem:
 config system 3g-modem custom   
  edit 1   
   set vendor "ZTE"   
   set model "MF100"   
   set vendor-id 19d2   
   set product-id 0017   
  next   
 end  

Next, you will need to find the serial port used by your modem, because your modem may actually appear on two different serial ports, possibly due to this related bug.

Scan through all available ports on your FortiGate as follows, by issuing a dial command:
 # diag sys modem com /dev/ttyusb0  
 Serial port: /dev/ttyusb0  
 Press Ctrl+W to exit.  
   
 # diag sys modem com /dev/ttyusb1  
 Serial port: /dev/ttyusb1  
 Press Ctrl+W to exit.    
 atdt*99#  
 NO CARRIER  
   
 # diag sys modem com /dev/ttyusb2  
 Serial port: /dev/ttyusb2  
 Press Ctrl+W to exit.   
 atdt*99#  
 CONNECT 3600000  
   
 # diag sys modem com /dev/ttyusb3  
 Serial port: /dev/ttyusb3  
 Press Ctrl+W to exit.  

In this case the port you want is /dev/ttyusb2, since there is a dial-tone.  Unfortunately I am not quite sure how to hang-up the line correctly after this test, so I end up power cycling the firewall at this point.


Modem Configuration


We can now configure our modem:
 config system modem  
   set status enable  
   set mode redundant  
   set dial-on-demand enable  
   set connect-timeout 30  
   set interface "external"  # your primary Internet interface
   set wireless-port 3  
   set phone1 "*99#"  
   set username1 "APN username"  
   set passwd1 "APN password"
   set extra-init1 "AT+CGDCONT=1,\"IP\",\"your.provider.APN\""  
   set distance 100  
 end

Note, see this Fortinet KB article regarding how to map ttyusbX to wireless-port, which is "3" in this case.


Check to make sure the system can tak to your modem now and there is a dial-tone:
 # diag sys modem detect  
 modem is attached.  
 dialtone is detected.  
   
 # diag sys modem query  
 USB status: Connected  
 manufacturer: ZTE INCORPORATED  
 model: MF100  
 IMEI number: XXXX  
 SIM state: Unknown  
 service status: Unknown  
 signal level: 1/4  
 network name: Orange  
 network type: UTRAN  
 location area code:   
 active profile(AT&V):  
 &C: 2; &D: 2; &E: 0; &F: 0; &S: 0; &W: 0; E: 1; L: 0; M: 0; Q: 0; V: 1;  
 X: 1; Z: 0; \Q: 3; \S: 0; \V: 0; S0: 0; S2: 43; S3: 13; S4: 10; S5: 8;  
 S6: 2; S7: 50; S8: 2; S9: 6; S10: 14; S11: 95; S30: 60; S103: 1; S104: 1;  
 +FCLASS: 0; +ICF: 3,3; +IFC: 2,2; +IPR: 115200; +DR: 0; +DS: 0,0,2048,6;  
 +WS46: 12; +CBST: 0,0,1;  
 +CRLP: (61,61,48,6,0),(61,61,48,6,1),(240,240,52,6,2);  
 +CV120: 1,1,1,0,0,0; +CHSN: 0,0,0,0; +CSSN: 0,0; +CREG: 0; +CGREG: 0;  
 +CFUN:; +CSCS: "IRA"; +CSTA: 129; +CR: 0; +CRC: 0; +CMEE: 2; +CGDCONT: (1,"IP","everywhere","0.0.0.0",0,0)  
 ; +CGDSCONT: ; +CGTFT: ; +CGEQREQ: ; +CGEQMIN: ; +CGQREQ: ; +CGQMIN: ;  
 ...


Dead Gateway Detection


You need to re-configure your primary "external" interface to detect a failed interface condition.  Find your next-hop router first:


 $ traceroute -m 2 -d 1.1.1.1  
 traceroute to 1.1.1.1 (1.1.1.1), 2 hops max, 52 byte packets  
  1 192.168.67.254 (192.168.67.254) 282.554 ms 1.091 ms 0.977 ms  
  2 217.33.154.151 (217.33.154.151) 13.737 ms 15.177 ms 324.736 ms  


Then, configure the gateway detect settings on your primary external interface:
 config router gwdetect  
   edit 1  
     set interface "external"  
     set server "217.33.154.151"  
   next  
 end  
    
 config system interface  
   edit "external"  
     set fail-detect enable  
     set fail-detect-option detectserver  
     ...
   next  
 end  


Finally, adjust the modem interface with some important additional parameters:
 config system interface  
   edit "modem"  
     set distance 100  
     set defaultgw enable  
     set dns-server-override disable  
     ...  
   next  
 end  

Firewall Policy


You need to allow access from your internal network to your backup external interface (i.e. modem).  the best way to do this, is to group your primary external interface and modem into an interface zone as follows:
 config system zone  
   edit "external_zone"  
     set interface "external" "modem"  
   next  
 end  


Then, you can update your existing outbound firewall policy to use the zone as the destination interface:
 config firewall policy  
   edit 1  
     set srcintf "internal"  
     set dstintf "external_zone"  
     set srcaddr "net_192.168.67.0_24"  
     set dstaddr "all"  
     set action accept  
     set schedule "always"  
     set service "ALL"   
     set nat enable  
   next  
 end  


Dynamic DNS (Optional)


You may want to configure DDNS on your 3G interface, if you are planning to connect to services on your internal network during fail-over:
 config system ddns  
   edit 1  
     set ddns-server dyndns.org
     set ddns-domain "yourhostname.dyndns.org"  
     set ddns-username "your username"  
     set ddns-password "your password"  
     set monitor-interface "modem"  
   next  
 end  


Testing


While your monitor an external IP with a ping session from a host on your local network, drop your primary external interface and observe the modem interface take over.

Note, if you have a tunnelled IPv6 configuration on your primary interface, be prepared for network instability once you fail-over to the modem interface.  Since there is no way to specify the modem interface on your sit-tunnel, the tunnel is effectively broken for the duration of the fail-over.

References


I've used the following reference material to prepare the solution described in this article.  Many thanks to the respective authors.


Monday, 24 June 2013

A practical guide to setting up IPv6, NAT64/DNS64 on a FortiGate firewall (FortiOS 5.0) using a consumer broadband Internet connection



Overview


Even though I am a couple of years too late for World IPv6 Launch, I've finally decided to implement IPv6 at home.  The following step by step guide, should help anyone with access to similar hardware in implementing this solution.







Prerequisites


You will require the following:
The following steps should hopefully guide you in setting up a tunneled, but fully functional IPv4/IPv6 configuration, which will further enable you to switch off IPv4 entirely and use NAT64 to continue accessing IPv4 resources from your IPv6-only network.


Configuration


In the subsequent sections, the following example parameters are used.  Make sure to substitute your own settings:

LAN firewall interface: internal
WAN firewall interface: external
Client IPv6 Address: 2001:470:1234:567::2/64
Routed /64 subnet: 2001:470:890a:bcd::/64
LAN IPv6 interface IP: 2001:470:890a:bcd::1/64
DHCP6 scope: 2001:470:890a:bcd::1000/112

IPv6 Tunnel


The first step is to establish a tunnel to your IPv6 provider, which in this case will be tunnelbroker.net.

First, allow tunnelbroker.net ICMP (ping) access to your IPv4 public IP:
 config system accprofile  
   edit "no_access"  
   next  
 end  
 config system admin  
   edit "HE"  
     set trusthost1 66.220.2.74 255.255.255.255  
     set accprofile "no_access"  
     set vdom "root"  
     set password "your_own_secret"  
   next  
 end  

Also make sure your external interface allows ping access:
 config system interface  
  # your external interface name may be different  
  edit "external"  
   set allowaccess ping ...   
  next   
 end   

Next, create a regular tunnel following this link.  Once you've created the tunnel, configure your firewall as follows:

 config system sit-tunnel  
   edit "HE"  
     set destination 216.66.80.26  
     set interface "external"
     set ip6 "client IPv6 address/mask from HE portal (e.g. 2001:470:1234:567::2/64)"
   next  
 end  
 config router static6  
   edit 1  
     set device "HE"  
   next  
 end  

Test your work so far, by pinging your server's IPv6 tunnel end-point IP:
 # exec ping6 2001:470:1234:567::1  
 PING 2001:470:1234:567::1(2001:470:1234:567::1) 56 data bytes  
 64 bytes from 2001:470:1234:567::1: icmp_seq=1 ttl=64 time=13.4 ms  
 64 bytes from 2001:470:1234:567::1: icmp_seq=2 ttl=64 time=13.2 ms  
 ...


Also try pinging an external IPv6 IP (e.g. Google):
 # exec ping6 ipv6.google.com  
 PING ipv6.google.com(2a00:1450:4009:802::1012) 56 data bytes  
 64 bytes from 2a00:1450:4009:802::1012: icmp_seq=1 ttl=59 time=14.3 ms  
 64 bytes from 2a00:1450:4009:802::1012: icmp_seq=2 ttl=59 time=14.0 ms  
 ...  


Public DNS


If you have a dynamic IPv4 IP assigned to you by your Internet service provider, you would probably want a DNS name automatically updated, when it changes.

Using the HE portal, on your Tunnel Details page, click "Edit" next to "rDNS delegation" and click the link titled "Delegate to dns.he.net".

Next, head to dns.he.net and add a new domain, which you have registered with an IPv6 compliant registrar (check with the registra if they support "IPv6 glue records").


Edit the newly added domain zone, create a new A host record (e.g. myip.mydomain.com), making sure to tick "Enable entry for dynamic dns" and set the TTL to 5 minutes.


Click the DDNS icon next to you new record and generate a new API key.


Got to the "Advanced" tab of the tunnelbroker.net tunnel management portal and register your hostname and API key.


Last, go to your domain name registrar's admin portal and delegate your entire domain or a sub-domain to HE.net's name servers (there are five).



Dynamic DNS (DDNS)



Since I do not have a static IP address with my Internet service provider, I've configured FortiOS to update my external IPv4 address, when it changes using dyn.com as follows:
 config system ddns   
  edit 1   
   set ddns-server dyndns.org   
   set ddns-domain "myhost.dyndns.org"   
   set ddns-username "my username"   
   set ddns-password "my password"   
   set monitor-interface "external"   
  next   
 end   

The problem with this approach however, is that your IPv6 tunnel provider doesn't know about those changes and cannot update your tunnel's public IPv4 address.  So, every time you reboot your DSL/cable modem and get a new IP, your IPv6 tunnel will be down.

FotiOS currently only supports the following DDNS services:
 FortiGuardDDNS FortiGuard DDNS service.   
 dhs.org        members.dhs.org   
 dipdns.net     dipdnsserver.dipdns.com   
 dyndns.org     members.dyndns.org and dnsalias.com   
 dyns.net       www.dyns.net   
 easydns.com    members.easydns.com   
 genericDDNS    Generic DDNS based on RFC2136.   
 now.net.cn     ip.todayisp.com   
 ods.org        ods.org   
 tzo.com        rh.tzo.com   
 vavic.com      Peanut Hull   

Note, HE.net is not on the list and since there is no generic dyndns2 protocol option, there is no way to tell your FortiGate firewall to automatically update your tunnel end-point IP.

So a workaround I've put in place, is to configure ddclient according to these instructions, to run on a local Linux server, periodically detect my public IP and update the tunnel end-point if it changes.


For reference, my /etc/ddclient.conf looks like this:
 # Configuration file for ddclient   
 #   
 # /etc/ddclient.conf   
    
 daemon=600                # check every 600 seconds   
 syslog=yes                # log update msgs to syslog   
 #mail=root                # mail all msgs to root   
 #mail-failure=root        # mail failed update msgs to root   
 pid=/var/run/ddclient.pid # record PID in file.   
 ssl=yes                   # use ssl-support. Works with   
                           # ssl-library   
   
 protocol=dyndns2   
 use=web, web=checkip.dyndns.org, web-skip='IP Address'   
 server=ipv4.tunnelbroker.net   
 script=/nic/update   
 login=your_username  
 password=your_password  
 username=#.tunnel.tserv#.lon#.ipv6.he.net    

This process updates your tunnel end-point IPv4 and since you've configured a hostname and API key on the tunnelbroker.net portal previously, it will also perform a chained update to your HE.net DDNS host entry.


In effect you will have two separate DDNS entries which both point to my dynamic IPv4 address:

  • myip.mydomain.com
  • myhost.dyndns.org


Ideally, you would want your firewall/router to do this as part of it's PPPoE interface-up routines, but we are where we are..


EDIT: I've written a very basic script to obtain the current public IP from the FortiGate firewall directly, rather than going out to a remote site.

To use it, save it to your favourite script location and update the "use=" line in your ddclient.conf as follows:
 ...
 use=cmd, cmd=/scripts/use-fg.sh  
 ...


Internal LAN


Now, configure your LAN interface(s) to support IPv6:
 config system interface   
  # your internal interface name may be different   
  edit "internal"   
   ...   
   config ipv6    
   set ip6-allowaccess ping https ssh snmp    
   set ip6-address "first IPv6/mask in the routed/64 prefix from HE portal (e.g. 2001:470:890a:bcd::1/64)"   
   set ip6-send-adv enable    
   set ip6-manage-flag enable    
   set ip6-other-flag enable    
    config ip6-prefix-list    
    edit "routed/64 IPv6 prefix from HE portal e.g. 2001:470:890a:bcd::/64"    
     set autonomous-flag disable  
     set onlink-flag enable    
    next    
    end    
   end    
  next    
 end   

Some notes on important flags:

  • ip6-send-adv enables router advertisement messages.
  • autonomous-flag enables stateless IPv6 configuration (dynamically generated IPv6 addresses within the prefix).
  • ip6-manage-flag means that there is a DHCP6 server on the network handing out IPs (stateful).
  • ip6-other-flag means the DHCP6 server is also handing out DNS information, etc.
  • onlink-flag basically means the prefix is on a local (layer 2) network.


Note, since we are using a stateful configuration where DHCP6 hands out IPv6 addresses, we disable the autonomous-flag to stop a second stateless IPv6 address being assigned.

Configure IPv6 address objects, which you will use later on in your IPv6 firewall policies:
 config firewall address6  
   edit "all"  
   next  
   edit "net_2001:470:890a:bcd::/64"  
     set ip6 2001:470:890a:bcd::/64  
   next  
 end  

Configure IPv6 firewall policies to allow access from your internal network and also to allow ICMP (ping) from hosts on the internet:
 config firewall policy6  
   edit 1  
     set srcintf "HE"  
     set dstintf "internal"  
     set srcaddr "all"  
     set dstaddr "net_2001:470:890a:bcd::/64"  
     set action accept  
     set schedule "always"  
     set service "ALL_ICMP6"  
   next  
   edit 2  
     set srcintf "internal"  
     set dstintf "HE"  
     set srcaddr "net_2001:470:890a:bcd::/64"  
     set dstaddr "all"  
     set action accept  
     set schedule "always"  
     set service "ALL"  
   next  
 end     

Test you work so far, by pinging your LAN IPv6 IP using an online ping tool while watching the tunnel interface with the packet sniffer:
 # diag sniffer packet HE "icmp6" 4   
 interfaces=[HE]   
 filters=[icmp6]   
 pcap_lookupnet: HE: no IPv4 address assigned   
 4.211481 HE -- 2001:1640:3::3 -> 2001:470:890a:bcd::1: icmp6: echo request seq 1   
 4.211575 HE -- 2001:470:890a:bcd::1 -> 2001:1640:3::3: icmp6: echo reply seq 1   
 ...  


DHCP6/DNS


We will be using DHCP6 to hand out IPv6 IPs as well as DNS server information.

Configure local DNS server on the internal firewall interface, which will be handed out by your DHCP server(s):
 config system dns-server  
   edit "internal"  
   next  
 end  

Configure DHCP6 server:
 config system dhcp6 server  
   edit 1  
     set interface "internal"  
       config ip-range  
         edit 1  
           set end-ip 2001:470:890a:bcd::ffff
           set start-ip 2001:470:890a:bcd::1000
         next  
       end  
     set lease-time 3600  
     set rapid-commit enable  
     set subnet 2001:470:890a:bcd::/112
     set dns-server1 2001:470:890a:bcd::1  
   next  
 end  

Assuming you are also running DHCP on your IPv4 network, you may also want to update it to use the local DNS server:
 config system dhcp server  
   edit 1  
     set dns-service local  
   next  
 end  

Renew your DHCP lease on your IPv6 client and check to make sure it obtained a correct IPv6 address from your DHCP6 server:
 $ ifconfig  
 eth0  Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx   
    inet6 addr: 2001:470:890a:bcd::1000/128 Scope:Global   
    inet6 addr: fe80::ba27:ebff:fee9:d775/64 Scope:Link   
    ...   

Note, you will also see a link-local IPv6 address, which is randomly generated.

Next, make sure the local DNS server on the firewall is handed out by your DHCP6 server:

 $ grep 2001 /etc/resolv.conf  
 nameserver 2001:470:890a:bcd::1     

You can also check the leases on the firewall, to see what IPs your IPv6 clients have been issued:
 BeastGate # exec dhcp6 lease-list  
 Interface  DUID                     IAID   IP                         Expiry  
 internal:xx:xx:xx:xx:xx:xx          15     2001:470:890a:bcd::1000    Mon Jun 24 10:48:27 2013  

Now you should be able to ping an external IPv6 IP from your IPv6 enabled client:
 $ ping6 -c 2 ipv6.google.com  
 PING6(56=40+8+8 bytes) 2001:470:890a:bcd::1000 --> 2a00:1450:4009:809::1012  
 16 bytes from 2a00:1450:4009:809::1012, icmp_seq=0 hlim=58 time=22.427 ms  
 16 bytes from 2a00:1450:4009:809::1012, icmp_seq=1 hlim=58 time=31.112 ms  

NAT64/DNS64 (Optional)


NAT64 is used in pure IPv6 networks to allow access to IPv4 resources.  In practical terms, it means you can switch off IPv4 on your internal network and continue accessing IPv4 sites on the Internet via your IPv6 tunnel.  For compatibility reasons however, you would probably want to operate a mixed IPv4/IPv6 environment, until at least your Internet provider is able to support IPv6 natively.

First, re-configure your system settings to use DNS resolvers other than FortiGuard (e.g. Google and HE.net):
 config system dns  
   set primary 8.8.8.8  
   set secondary 8.8.4.4  
   set ip6-primary 2001:470:20::2  
   set ip6-secondary 2001:4860:4860::8888  
 end  

I found, that when the internal FortiGate DNS server is forwarding to the default FortiGuard DNS resolvers upstream, it completely breaks NAT64.


Next, enable and configure NAT64:
 config system nat64  
   set status enable  
   set always-synthesize-aaaa-record disable  
 end  

Note, we are disabing the automatic synthesis of IPv6 addresses, since we dont want a synthetic address generated if a host already has an IPv6 address.  In this case, an address will by synthethised only if the host does not have an IPv6 AAAA record.

Add an IP pool abd firewall policy to support NAT(ing) of IPv6 addresses to IPv4:

config firewall ippool
    edit "nat64-exit-pool"
    next
end

config firewall policy64  
   edit 1  
     set srcintf "internal"  
     set dstintf "external"  
     set srcaddr "net_2001:470:890a:bcd::/64"  
     set dstaddr "all"  
     set action accept  
     set schedule "always"  
     set service "ALL"
     set ippool enable
     set poolname "nat64-exit-pool"
   next  
 end

Now, switch off IPv4 support on your client and make sure you can no longer access an IPv4 only site (e.g. Fortinet):
 $ curl -I -4 www.fortinet.com  
 curl: (7) Failed to connect to 66.171.121.34: No route to host  

This is expected, since we have turned off IPv4, but told cURL to specifically use it to access the web site.

Next, try to resolve the IPv4 only site using an external DNS server (e.g. Google):
 $ dig aaaa www.fortinet.com @8.8.8.8  
 ...
  
 ;; QUESTION SECTION:  
 ;www.fortinet.com.          IN     AAAA  

Note that there are no IPv6 host records (AAAA) returned for www.fortinet.com.


Now try to resolve the same name using your internal DNS server, running on the firewall, which is now DNS64 enabled:



 $ dig aaaa www.fortinet.com  
 ...  
   
 ;; QUESTION SECTION:  
 ;www.fortinet.com.          IN     AAAA  
   
 ;; ANSWER SECTION:  
 www.fortinet.com.     2339     IN     AAAA     64:ff9b::42ab:7922  
 ...

Note an IPv6 address is synthesised from the NAT64 Well-Known Prefix (64:ff9b::/96).


Finally, check to make sure you can access the web site using IPv6:
 $ curl -I -6 www.fortinet.com  
 HTTP/1.1 200 OK  
 Date: Sun, 23 Jun 2013 17:24:26 GMT  
 Server: Apache/2.2.3 (Red Hat)  
 ...  

Testing


To test your IPv6 setup, head to test-ipv6.com, which should get you a similar result:


Note, at the point you should probably re-enable IPv4 and re-run the test.  The only difference will be, that it won't warn you anymore about limited IPv4 connectivity and the use of NAT64/DNS64.

I hope you found this guide useful and if you find any mistakes or have any suggestions  please feel free to comment.



Tuesday, 21 August 2012

A3 air-bag warning light..



The air-bag warning light has been coming on randomly on the instrument cluster in my Audi A3 (8L) for the past 4-5 years. Scanning the airbag controller with VCDS-Lite, revealed the following fault:
01578 - Airbag Deactivation Warning Lamp; Passenger Side (K145)
31-10 - Open or Short to Ground - Intermittent
I didn't worry about it, until my wife got a NR on her driving exam, after the examiner aborted the test seeing the warning light.

I've tried a number of things to fix it, detailed in my post to no avail. After reading some posts about people replacing their seats with airbag-less race seats and putting a resistor across the wires going to airbag controller to stop it warning about missing airbags , I decided to put a 1W 4K7 resistor across the passenger airbag deactivation warning light. This light lives in the top map reading light assembly in my model and looks like this:

A3 8L passenger airbag deactivation warning light














I've highlighted the terminals across which I've soldered the resistor.  This fixed the problem.  The passenger airbag deactivation warning lamp comes on still when the passenger airbag is deactivated via key operated control in the glovebox.

There are no more intermittent errors from the airbag controller module and most importantly, the general airbag warning light on the instrument cluster is quiet.


WARNING: if the warning lamp fully fails, the airbag controller will not know about it and will no longer warn you via the general airbag warning light on the instrument cluster.


-- ab1