corporate-gadfly / Tunlr-Clone

302 stars 57 forks source link

Netflix on Chromecast #22

Open domsieb opened 11 years ago

domsieb commented 11 years ago

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 https://github.com/dlundquist/sniproxy/issues/23 describes a similar problem. However, there is no solution proposed.

Best, hombre168

reini1989 commented 10 years ago

Im experiencing the same problem here.

As I understand the problem is as following:

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.

reini1989 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

Wonder if someone wants to play around with transparent proxying.

reini1989 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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

Emredrum commented 10 years ago

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 commented 10 years ago

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

ryanchapman commented 10 years ago

@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 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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:

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 commented 10 years ago

@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 commented 10 years ago

@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 commented 10 years ago

Did some capturing this afternoon.

SNI-Proxy-Setup:

Unblock-US-Setup:

Conclusions:

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:

reini1989 commented 10 years ago

New approach:

My network setup:

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

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

edit:

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

victorhooi commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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

toadyus commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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.