commit b4a07c4192841ded1906e3e74a5e4fec6b5c3f65 Author: Serene Han keroserene+git@gmail.com Date: Tue Jan 19 17:21:07 2016 -0800
add --meek flag to client to toggle the domain fronted rendezvous --- README.md | 7 +++++++ client/meek-webrtc.go | 34 +++++++++++++++------------------- client/snowflake.go | 46 +++++++++++++++++++++++----------------------- 3 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/README.md b/README.md index 7b6ca9f..f0b7678 100644 --- a/README.md +++ b/README.md @@ -88,4 +88,11 @@ snowflake to just use a default relay.
### More
+To try using the Meek signaling channel (which will soon be fully ready), +add the `--meek` flag like so: + +``` +ClientTransportPlugin snowflake exec ./client --meek +``` + More documentation on the way. diff --git a/client/meek-webrtc.go b/client/meek-webrtc.go index 927d4bf..172c1b5 100644 --- a/client/meek-webrtc.go +++ b/client/meek-webrtc.go @@ -1,5 +1,5 @@ -// Exchange WebRTC SessionDescriptions over meek. -// Much of this source is extracted from meek-client.go. +// Exchange WebRTC SessionDescriptions over a domain-fronted HTTP +// signalling channel. package main
import ( @@ -16,29 +16,26 @@ import ( // roundtrip, including variables that may come from SOCKS args or from the // command line. type RequestInfo struct { - // What to put in the X-Session-ID header. - // SessionID string - // The URL to request. + // What to put in the X-Session-ID header - SessionID string + // The desired potentially filtered URL to request. URL *url.URL // The Host header to put in the HTTP request (optional and may be // different from the host name in URL). Host string }
-func NewRequestInfo(meekUrl string, front string) *RequestInfo { +func NewRequestInfo(targetUrl string, front string) *RequestInfo { info := new(RequestInfo) - requestUrl, err := url.Parse(meekUrl) + requestUrl, err := url.Parse(targetUrl) if nil != err { return nil } info.URL = requestUrl info.Host = front - // info.URL.Host = front - // info.Host = info.URL.Host return info }
-// Meek Signalling Channel +// Meek Signalling Channel. type MeekChannel struct { info *RequestInfo // Used to make all requests. @@ -58,24 +55,23 @@ func NewMeekChannel(info *RequestInfo) *MeekChannel { }
// Do an HTTP roundtrip using the payload data in buf. -func (m *MeekChannel) roundTripHTTP(buf []byte) (*http.Response, error) { +func (mc *MeekChannel) roundTripHTTP(buf []byte) (*http.Response, error) { // Compose an innocent looking request. - req, err := http.NewRequest("POST", m.info.Host+"/reg/123", bytes.NewReader(buf)) + req, err := http.NewRequest("POST", mc.info.Host+"/reg/123", bytes.NewReader(buf)) if nil != err { return nil, err } - // Set actually desired target host. - req.Host = m.info.URL.String() + // Set actually desired host in the request. + req.Host = mc.info.URL.String() // req.Header.Set("X-Session-Id", m.info.SessionID) - return m.transport.RoundTrip(req) + return mc.transport.RoundTrip(req) }
// Send an SDP offer to the meek facilitator, and wait for an SDP answer from // the assigned proxy in the response. -func (m *MeekChannel) Negotiate(offer *webrtc.SessionDescription) ( +func (mc *MeekChannel) Negotiate(offer *webrtc.SessionDescription) ( *webrtc.SessionDescription, error) { - buf := []byte(offer.Serialize()) - resp, err := m.roundTripHTTP(buf) + resp, err := mc.roundTripHTTP([]byte(offer.Serialize())) if nil != err { return nil, err } @@ -85,11 +81,11 @@ func (m *MeekChannel) Negotiate(offer *webrtc.SessionDescription) ( if nil != err { return nil, err } - log.Println("MeekChannel Body: ", string(body)) answer := webrtc.DeserializeSessionDescription(string(body)) return answer, nil }
+ // Simple interim non-fronting HTTP POST negotiation, to be removed when more // general fronting is present. func sendOfferHTTP(url string, offer *webrtc.SessionDescription) (*webrtc.SessionDescription, error) { diff --git a/client/snowflake.go b/client/snowflake.go index 7da1e15..cf08c9e 100644 --- a/client/snowflake.go +++ b/client/snowflake.go @@ -25,14 +25,15 @@ import ( // Hard-coded meek signalling channel for now. // TODO: expose as param const ( - MEEK_URL = "snowflake-reg.appspot.com" - FRONT_DOMAIN = "https://www.google.com" - // FRONT_DOMAIN = "https://www.google.com" + // Go fully requires the protocol to make url spec + FRONT_URL = "https://www.google.com" + BROKER_URL = "snowflake-reg.appspot.com" )
var ptInfo pt.ClientInfo var logFile *os.File var offerURL string +var meekEnabled bool
// When a connection handler starts, +1 is written to this channel; when it // ends, -1 is written. @@ -160,7 +161,6 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( close(openChan) } dc.OnMessage = func(msg []byte) { - // log.Printf("OnMessage channel %d %+q", len(msg), msg) log.Printf("OnMessage <--- %d bytes", len(msg)) n, err := pw.Write(msg) if err != nil { @@ -180,20 +180,22 @@ func dialWebRTC(config *webrtc.Configuration, meek *MeekChannel) ( fmt.Fprintln(logFile, "\n"+offer.Serialize()+"\n") log.Printf("----------------") go func() { - // log.Printf("Sending offer via meek...") - // answer, err := meek.Negotiate(pc.LocalDescription()) - // if nil != err { - // log.Printf("Signalling error: %s", err) - // } - // if nil == answer { - // log.Printf("No answer received from meek channel.") - // } else { - // // TODO: Once this is correct, uncomment and remove copy-paste - // // signalling. - // log.Println("Recieved answer from Meek channel: \n", - // answer.Serialize()) - // // signalChan <- answer - // } + if meekEnabled { + log.Println("Sending offer via meek channel...\nTarget URL: ", BROKER_URL, + "\nFront URL: ", FRONT_URL) + answer, err := meek.Negotiate(pc.LocalDescription()) + if nil != err { + log.Printf("MeekChannel signaling error: %s", err) + } + if nil == answer { + log.Printf("MeekChannel: No answer received.") + } else { + log.Println("Recieved answer from Meek channel: \n\n", + answer.Serialize(), "\n") + // TODO: Once this is correct, uncomment and remove copy-paste stuff. + // signalChan <- answer + } + } if offerURL != "" { answer, err := sendOfferHTTP(offerURL, offer) if err != nil { @@ -253,15 +255,12 @@ func handler(conn *pt.SocksConn) error { }() defer conn.Close()
- // go func() { - // }() // Prepare meek signalling channel. - info := NewRequestInfo(MEEK_URL, FRONT_DOMAIN) + info := NewRequestInfo(BROKER_URL, FRONT_URL) meek := NewMeekChannel(info)
config := webrtc.NewConfiguration( webrtc.OptionIceServer("stun:stun.l.google.com:19302")) - // remote, err := dialWebRTC(config, nil) remote, err := dialWebRTC(config, meek) if err != nil { conn.Reject() @@ -322,7 +321,8 @@ func readSignalingMessages(f *os.File) { func main() { var err error
- flag.StringVar(&offerURL, "url", "", "do signaling through URL") + flag.StringVar(&offerURL, "url", "", "do signalling through URL") + flag.BoolVar(&meekEnabled, "meek", false, "use domain fronted signaling") flag.Parse()
logFile, err = os.OpenFile("snowflake.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)