Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netflix on Chromecast #22

Open
domsieb opened this issue Nov 23, 2013 · 25 comments
Open

Netflix on Chromecast #22

domsieb opened this issue Nov 23, 2013 · 25 comments

Comments

@domsieb
Copy link

domsieb commented Nov 23, 2013

Hi,
I cannoct connect to Netflix with a similar setup of Chromecast, Laptop, and SniProxy. I point all my DNS request to SniProxy. For Android&Laptop everything works fine, but Chromecast fails then.

Did anybody try to watch netflix via Tunlr-clone/sniproxy with chromecast?

I check the logs of sniproxy and I always get following error when Chromecast request my VPS:

Request from 95.XX.XX.XX:46037 did not include a hostname
Received SSL 3.0 handshake which does not support Server Name Indication.

Do you have any idea how I can resolve this problem. It seems for me that dlundquist/sniproxy#23 describes a similar problem. However, there is no solution proposed.

Best,
hombre168

@reini1989
Copy link

Im experiencing the same problem here.

As I understand the problem is as following:

  • the dns server replaces the correct ip by an wrong one (the one of the sniproxy)
  • the client connects to this ip. in the normal case this would be pretty fine because the ip is the good ip
  • but the sni proxy has to figure out where the client would like to connect to. in http this is no problem: no encryption, take the url, reslove dns again. done. In https this is more complicated as the http header (including) the url belongs to the encrypted part. the real target ip is lost long time ago (first dns server request). so the only point to get the ip from is this server_name_indication extension of the tls-handshake-header. but chromecast seems to use a ssl version which does not support this extension.

tl;dr: chromecast -> ssl version does not support server name -> no resolving -> no proxying -> no netflix

anyway... unblock-us seems to have resolved this problem somehow.
There is a post on xda-developers how to setup the environment for chromecast & unblock us (http://forum.xda-developers.com/showthread.php?t=2435579).
In lack of a unblock-us account I havent tried it yet.

But maybe we could do some kind of brainstorming.

  • maybe there is some message in the ssl handshake which says "i can't do ssl 3.0, i force you to do tls 1.0" ?
  • Maybe there is some kind of default entry point for chromecast requests at netflix
  • completely different soloution: Instead of faking dns responses we could make a tool which adds a new route/iptables-rule when a dns request/response for netflix is "captured"

@reini1989
Copy link

When I understand it right there is in fact something in the tls protocol: http://tools.ietf.org/html/rfc5246#section-7.4.1.3
If SNI-Proxy would (instead of just dropping the connection) send a faked server hello message with server_version == TLS 1.0 the client should switch to this version, right?

It would be great if someone could confirm this. I am no expert in tls/ssl. But if someone could confirm that this approach could theoretically work, I could try to make a fork of sni-proxy to implement this.

@corporate-gadfly
Copy link
Owner

When I understand it right there is in fact something in the tls protocol: http://tools.ietf.org/html/rfc5246#section-7.4.1.3
If SNI-Proxy would (instead of just dropping the connection) send a faked server hello message with server_version == TLS 1.0 the client should switch to this version, right?

It would be great if someone could confirm this. I am no expert in tls/ssl. But if someone could confirm that this approach could theoretically work, I could try to make a fork of sni-proxy to implement this.

Worth a shot @reini1989. Might even be worth it to file a new issue with Dustin at https://github.com/dlundquist/sniproxy/issues.

@corporate-gadfly
Copy link
Owner

Wonder if someone wants to play around with transparent proxying.

@reini1989
Copy link

Wonder if someone wants to play around with transparent proxying.

As far as I can see in the source code of this any_proxy thing, @ryanchapman extracts the IP from the client request: https://github.com/ryanchapman/go-any-proxy/blob/master/any_proxy.go
But in our scenario the original IP is removed and replaced by the one of SNI-Proxy.

Anyway we could throw away the DNS faking part and simply add the iptables rules as suggested for any_proxy. But Then either all https traffic would be routed through the proxy (which I don't want to) or we need to know all of netflix' IP addresses (which is hard to figure out, new addresses may come from time to time, others go away).

Issue at sniproxy is filed but so far no response from dustin. I have some time this afternoon so I think I'm going to play a little bit with this down negotiation idea.

@reini1989
Copy link

Status so far:

Chromecast sends it's SSL 3.0 "Client Helo":
screenshot

I managed it to respond to those Messages with a "Protocol Version" alert:
screenshot2

Then Chromecast sends a second "Client Helo" - with TLS 1.0 and the SNI extension:
screenshot3

Conversation seems to work:
screenshot4

But Chromecast says:
img_20131205_200125

:'-(

@themickman007
Copy link

Does wireshark show any new connections which fail after the changes you've made above?

@Emredrum
Copy link

Emredrum commented Dec 7, 2013

This is how I used to find if my ISP used a transparent proxy. http://stuff.daniel15.com/php/testproxy.php

https://github.com/elia/corkscrew

http://www.dotmana.com/weblog/2011/03/tunnel-ssh-through-proxy-web-with-dns/

I also have some ideas/questions if the proxy can also be used for socat/netcat and tcp manipulation.

http://www.aionsource.com/topic/67664-guide-to-lowering-your-latency-with-a-virtual-machine-linux/

In addition to Geo loc issues, for some non streaming uses, manipulation of the tcp_ack, nodealy at the proxy level can result in a reduced ping. (Gaming)

@themickman007
Copy link

Wouldn't corkscrew need to create it's own ssl certificate for forwarding ssl connections?

@ryanchapman
Copy link

@reini1989, one way I think this could work is to build a server like any_proxy that also has a dns server ("proxier") built in that runs on the tomato router. So the proxier would listen on port 53 for dns and port 3129 for traffic that should be proxied. On the tomato router, configure iptables to REDIRECT all port 80/443 traffic to port 3129. The chromecast would set it's DNS server to the tomato router. When a DNS request comes in for a site that should be proxied (e.g. hulu) the proxier returns the DNS of the real ip address of hulu (e.g. 1.2.3.4), and adds an entry in its internal proxy table to indicate that when traffic comes in for 1.2.3.4, send it to the VPS. Another proxier instance runs on the VPS which doesn't have a proxy table and instead transparently proxies all traffic. When a packet arrives on the VPS, the VPS proxier uses getsockopt(SO_ORIGINAL_DST, ...) to determine where to forward the traffic and does so.

This provides a transparent proxy solution operating at layer 4 (tcp), so it does not need to understand the layer 7 protocols (http/https/ssh/etc).

I don't know if such a solution exists, but if there is interest in such a thing, I would be willing to do it. I think it would take a week to code up.

@corporate-gadfly
Copy link
Owner

If someone has the time and resources and also has the requisite skills for looking at wireshark SSL traffic, you could sign up for Unlocator (which is running a free beta, at the moment). They also have a page for setting up Chromecast. Hopefully it can give some insight into how they managed to proxy Chromecast SSL traffic.

@victorhooi
Copy link

Hi,

I've signed up for Unlocator and I have a Chromecast and a NetFlix account.

I can confirm that I was able to get it working, essentially by following this guide here:

http://forum.xda-developers.com/showthread.php?t=2435579

I'm willing to give it a go to see if I can capture it using Wireshark.

Is there any chance you might be able to give me more specific instructions on what I should capture?

Do you want me to just watch a stream on Netflix, and capture all traffic going to Unlocator or Netflix? Should I filter that based on some kind of IP range?

If I capture all traffic on my box, I'm guessing that's going to be a fairly large capture file.

Cheers,
Victor

@reini1989
Copy link

I'm a bit out of time at the moment. I will try to do some further investigations later this week.

The next thing I will try is to use tls 1.2 in my protocol_alert-message instead of tls 1.0.
If this won't change anything I will setup my chromecast via unblock-us trial or unlocator beta to do some wireshark capturing.

@victorhooi
if you want wo capture: you will need to capture on your router using tcpdump or at least from a wireless notebook/pc within the same wifi network as chromecast.
I/We need to see one complete successful stream start:

  • Power off your chromecast by pulling usb cable off
  • Start capturing
  • Power on your chromecast
  • Go to netflix.com
  • Start a movie

Besides the .pcap file it would be useful to know which is the local IP of your remote (the device you use to start the video on chromecast), the local IP of your chromecast, the local ip of your catpuring device (if differen from remote), the local ip of your router.

@reini1989
Copy link

@ryanchapman
Yeah, I'm pretty sure that would work.
If you have time to work this out feel free to give it a shot

@ryanchapman
Copy link

@reini1989 I'll see what I can do on the coding. This weekend, I took at look at how unblock-us is pulling netflix off, and found that they don't use vhosts, instead allocating an IP address for every service (one for Netflix-US, one for Netflix-Mexico, etc) therefore they have no need for SNI. Unlocator seemed to be sending Netflix traffic directly to the appropriate Netflix server instead of proxying. They were proxying Hulu traffic to an Amazon virtual machine, but that is the only https service they seem to support via proxy. The same Unlocator Amazon virtual machine was running squid on port 80 and had no trouble proxying several other services. That's all I had time to figure out.

@reini1989
Copy link

Did some capturing this afternoon.

SNI-Proxy-Setup:

  • No aborted connections
  • No connecting fails
  • Successful down negotiation to TLS 1.0
  • Netflix fail for unknown reason

Unblock-US-Setup:

  • Some more SSL 3.0 connections
  • No dns requests to domains that should be proxied, too
  • Successful chromecasting

Conclusions:

  • Something in Netflix and Chromecasts first encrypted communication must lead to the error

A rooted chromecast would be nice to do have a look at it's log files but no chance due to applied updates...

If anyone wants to do some capturing, too, here's what I did:

  • On my machine
    • Started a netcat server which redirects it's output to a file: netcat -l 1234 > capture.pcap
  • On my router
    • Created a named pipe: mknod /tmp/mypipe p
    • Started a netcat client which reads from the pipe: netcat 192.168.1.222 1234 < /tmp/mypipe
    • Started tcpdump, capturing all lan traffic, writing the output to the pipe: tcpdump -i br-lan -w /tmp/mypipe
  • After capturing was done I was able to open the pcap file with wireshark (file was > 100mb for all my captures)

@reini1989
Copy link

New approach:

  • Hook up to the dns server
  • add netfilter rules on thy fly

My network setup:

  • Router: 192.168.1.1
    • TP-Link TL-WR1043N/ND v1
    • OpenWrt Barrier Breaker r38999
    • DNSMASQ dns server, running with --log-query option
    • ebtables installed (mac / ethernet version of iptables)
  • RaspberryPI: 192.168.1.173
    • Raspbian 2013-09-25
    • Active VPN Tunnel on interface tun0 (IP 10.8.0.10)

On the router there is the following script:
netflix.lua

while true do
        local line = io.read()
        if line == nil then break end

        if string.find(line, "dnsmasq.*reply.*netflix%.com") or
           string.find(line, "dnsmasq.*config.*netflix%.com") or
           string.find(line, "dnsmasq.*cached.*netflix%.com")
        then
                local ip
                ip = string.match(line, "(%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?)")
                if ip then
                        print(line)
                        local handle = io.popen("ebtables -t nat -L PREROUTING")
                        local result = handle:read("*a"):find(ip)
                        handle:close()
                        if not result then
                                print("Adding Rule for: " .. ip)
                                os.execute("/root/ebtables.rules " .. ip)
                        else
                                print("Rule already exists for:" .. ip)
                        end
                end
        end
end

ebtables.rules

KERNEL_VERSION=`uname -r`
EBTABLES=/usr/sbin/ebtables
MAC_RBPI=b8:27:eb:3c:aa:0d

insmod ebtables
insmod ebtable_filter
insmod /lib/modules/$KERNEL_VERSION/ebt_ip.ko
insmod /lib/modules/$KERNEL_VERSION/ebt_arp
insmod /lib/modules/$KERNEL_VERSION/ebt_arp.ko
insmod /lib/modules/$KERNEL_VERSION/ebt_dnat.ko
insmod /lib/modules/$KERNEL_VERSION/ebt_snat.ko
#insmod /lib/modulse/$KERNEL_VERSION/ebt_pkttype.ko
insmod /lib/modulse/$KERNEL_VERSION/ebtable_nat.ko

$EBTABLES -t nat -A PREROUTING -p ipv4 --ip-dst $1 -j dnat --to-destination $MAC_RBPI

The lua script is running by:
logread -f | lua netflix.lua
So everytime dnsmasq puts a new log-entry to the syslog like Wed Dec 11 21:55:30 2013 daemon.info dnsmasq[953]: cached netflix.com is 69.53.236.17 lua extracts the ip and adds a ebtables rule
The ebtable rule says: Replace the destination MAC by the Raspberry's one

On the Raspberry I did the following changes:
/proc/sys/net/ipv4/ip_forward set to 1
iptables -t nat -A POSTROUTING -j SNAT --to-source 10.8.0.10
So all incoming traffic is routed through the VPN tunnel

The good news: It works
The bad news: Not very well

I'm experiencing the following issues

  • sometimes the MAC DNAT seems not to work and I get error messages on netflix.com. I don't know yet why. I could imagine that my method of adding rules only adds one ip - but the most dns replys include more than 1 ip
  • on chromecast I get to the loading sceen - but after ~15% buffering something fails and an error pops up
  • I'm not sure if *.netflix.com is a good pattern - i could imagine my current script adds rules for the video-channels too (but we want only the meta-information-channels to be redirected)

I think I'm quitting for today. Maybe anyone of you has some further ideas :-)

edit:

  • updated the script
  • forgot iptables rule for the router: override dns-calls from chromecast to keep track of the requested domains
    • iptables -t nat -A PREROUTING -s 192.168.1.126 -d 8.8.8.8 -j DNAT --to-destination 192.168.1.1
    • iptables -t nat -A PREROUTING -s 192.168.1.126 -d 8.8.4.4 -j DNAT --to-destination 192.168.1.1
  • traceroute shows: netflix.com is routed via vpn, the ip for the video-stream (got from chrome -> F12 -> Network) is not routed via VPN

Currently stable on PC.
No change on chromecast.
Tablet seems not working at all.

@victorhooi
Copy link

Hi,

I did a capture last night with Unlocator and the Chromecast (sorry it took a while - I bought the Chromecast as a present for my parents - had to head back to their place to test).

The capture file is here:

https://mega.co.nz/#!9ssRCSBA!A6-E5U-ctAw60HGP4c-ftTMmtZh-QSJDP7r-vo2fAnk

Also - had to add the -p (flag) to your Netcat listening line.

The router (OpenWRT) is 192.168.3.1.

(I'll chase up the other IPs in a bit).

Cheers,
Victor

@fniephaus
Copy link

I have also tried to find out why Chromecast does not work with dlundquist's sniproxy. I don't understand why, but it looks like the proxy sends "Change Cipher Spec" packets after the "Server Key Exchange" which results in Chromecast sending a new (SSL 3.0) "Client Hello".

Successful connection:
1

Unsuccessful connection via sniproxy:
2

@shadoom
Copy link

shadoom commented Aug 7, 2014

any news? unblock-us works with chromecast, i'd like to run it on my own server though :\

@toadyus
Copy link

toadyus commented Sep 4, 2014

You need 3-4 static Ip's to get netflix to work with chromecast depending what countries you want to use it on..and unless your chromecast is unlocked/rooted you will also have to redirect all traffic to your own dns server with your router because chromecast is setup to send all netflix queries to 8.8.8.8 and 4.4.2.2.

As you can see it's not easy...and 3-4 IP's on a vps unless you get lucky and find a cheap deal will cost you $40-$60/year....

@shadoom
Copy link

shadoom commented Sep 4, 2014

I have it working on windows and android running through my rpi with dnsmasq to a vps that has haproxy running in the US.

Why does chromecast need more ips than windows/android? I think its a missing rule/filter in the settings of either netmasq or haproxy

@toadyus
Copy link

toadyus commented Sep 4, 2014

That's because Windows and android support SNI in the netflix app...chromecast doesn't.

There is no setting or change to config file to get around the lack of SNI in a device....well none that I know of or have found.

@shadoom
Copy link

shadoom commented Sep 5, 2014

toadyus thanks for your replies

I am running the non-sni version of this https://github.com/trick77/tunlr-style-dns-unblocking

some content works with the non-sni on the chromecast, most content doesnt work though
Arrested Development and Fargo works.
The Office, Bobs Burger, Waynes World did not work.

Here the queries from my pi:
Short: http://hastebin.com/ajawoduduv
Long: http://hastebin.com/debaqejazo
192.168.1.20 to .62 are virtual interfaces on the pi
192.168.1.1 is [ROUTER]
192.168.1.5 is [CHROMECAST]
192.168.1.6 is [ANDROID]

@wmertens
Copy link

If you use the HTML5 player of Netflix on Chrome and then cast to ChromeCast, it will use a new client that has SNI but is still a bit rough around the edges - it doesn't go to the next episode in a series post-play, no biggie.
The HTML5 player is soo much nicer than the silverlight one, at least on a Mac - it uses less CPU, loads faster, jumps faster etc. Very cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests