func (conn *SSHConnection) Request(sess *SessionConnection, ev event.Event) (err error, res event.Event) { f := func(local, remote net.Conn, ch chan int) { io.Copy(remote, local) local.Close() remote.Close() ch <- 1 } switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) if err := conn.initProxyConn(req.RawReq.Host, sess.Type == HTTPS_TUNNEL); nil != err { return err, nil } if sess.Type == HTTPS_TUNNEL { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) sess.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) ch := make(chan int) go f(sess.LocalRawConn, conn.proxy_conn, ch) go f(conn.proxy_conn, sess.LocalRawConn, ch) <-ch <-ch conn.Close() sess.State = STATE_SESSION_CLOSE } else { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) err := req.RawReq.Write(conn.proxy_conn) if nil != err { conn.ssh_conn.CloseConn() return err, nil } conn.proxy_conn.SetReadDeadline(time.Now().Add(10 * time.Second)) resp, err := http.ReadResponse(conn.proxy_conn_reader, req.RawReq) if err != nil { conn.ssh_conn.CloseConn() return err, nil } var zero time.Time conn.proxy_conn.SetReadDeadline(zero) err = resp.Write(sess.LocalRawConn) if nil == err { err = resp.Body.Close() } if nil != err || !util.IsResponseKeepAlive(resp) || !util.IsRequestKeepAlive(req.RawReq) { sess.LocalRawConn.Close() conn.Close() sess.State = STATE_SESSION_CLOSE } else { sess.State = STATE_RECV_HTTP } } default: } return nil, nil }
func (gae *GAEHttpConnection) doRangeFetch(req *http.Request, firstChunkRes *http.Response) { task := new(rangeFetchTask) task.FetchLimit = int(gae_cfg.FetchLimitSize) task.FetchWorkerNum = int(gae_cfg.ConcurrentRangeFetcher) task.SessionID = gae.sess.SessionID // task.TaskValidation = func() bool { // return !util.IsDeadConnection(gae.sess.LocalRawConn) // } gae.rangeWorker = task fetch := func(preq *http.Request) (*http.Response, error) { ev := new(event.HTTPRequestEvent) ev.FromRequest(preq) ev.SetHash(gae.sess.SessionID) err, xres := gae.requestEvent(gaeHttpClient, gae.sess, ev) if nil != err { //try again err, xres = gae.requestEvent(gaeHttpClient, gae.sess, ev) } if nil == err { httpresev := xres.(*event.HTTPResponseEvent) httpres := httpresev.ToResponse() return httpres, err } return nil, err } pres, err := task.SyncGet(req, firstChunkRes, fetch) if nil == err { err = pres.Write(gae.sess.LocalRawConn) if nil != err { task.Close() gae.rangeWorker = nil } if nil != pres.Body { pres.Body.Close() } } if nil != err { log.Printf("Session[%d]Range task failed for reason:%v\n", gae.sess.SessionID, err) } if nil != err || !util.IsResponseKeepAlive(pres) || !util.IsRequestKeepAlive(req) { gae.sess.LocalRawConn.Close() gae.sess.State = STATE_SESSION_CLOSE gae.Close() } }
func (auto *ForwardConnection) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { f := func(local, remote net.Conn) { n, err := io.Copy(remote, local) if nil != err { local.Close() remote.Close() } auto.forwardChan <- int(n) } //L: auto.closed = false switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) addr := req.RawReq.Host if !strings.Contains(addr, ":") { if conn.Type == HTTPS_TUNNEL { addr = net.JoinHostPort(addr, "443") } else { addr = net.JoinHostPort(addr, "80") } } err = auto.initForwardConn(addr, conn.Type == HTTPS_TUNNEL) if nil != err { log.Printf("Failed to connect forward address for %s.\n", addr) return err, nil } if conn.Type == HTTPS_TUNNEL { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if !auto.manager.overProxy || strings.HasPrefix(auto.conn_url.Scheme, "socks") { conn.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) } else { auto.writeHttpRequest(req.RawReq) } go f(conn.LocalRawConn, auto.forward_conn) go f(auto.forward_conn, conn.LocalRawConn) atomic.AddInt32(&total_forwared_routine_num, 2) <-auto.forwardChan <-auto.forwardChan atomic.AddInt32(&total_forwared_routine_num, -2) auto.Close() conn.State = STATE_SESSION_CLOSE } else { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if auto.manager.inject_crlf { log.Printf("Session[%d]Inject CRLF for %s", ev.GetHash(), req.RawReq.Host) auto.forward_conn.Write(CRLFs) } err := auto.writeHttpRequest(req.RawReq) if nil != err { return err, nil } if common.DebugEnable { var tmp bytes.Buffer req.RawReq.Write(&tmp) log.Printf("Session[%d]Send request \n%s\n", ev.GetHash(), tmp.String()) } resp, err := http.ReadResponse(auto.buf_forward_conn, req.RawReq) if err != nil { log.Printf("Session[%d]Recv response with error %v\n", ev.GetHash(), err) return err, nil } //log.Printf("Session[%d]Recv response %v\n", ev.GetHash(), resp) err = resp.Write(conn.LocalRawConn) resp.Body.Close() if common.DebugEnable { var tmp bytes.Buffer resp.Write(&tmp) log.Printf("Session[%d]Recv response \n%s\n", ev.GetHash(), tmp.String()) } if nil != err || !util.IsResponseKeepAlive(resp) || !util.IsRequestKeepAlive(req.RawReq) { conn.LocalRawConn.Close() auto.Close() conn.State = STATE_SESSION_CLOSE } else { conn.State = STATE_RECV_HTTP } } default: } return nil, nil }
func (google *GoogleConnection) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { f := func(local, remote net.Conn, ch chan int) { io.Copy(remote, local) ch <- 1 local.Close() remote.Close() } //L: switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) if conn.Type == HTTPS_TUNNEL { var proxyConn net.Conn if len(googleLocalProxy) > 0 { proxyURL, _ := url.Parse(googleLocalProxy) proxyConn, err = net.Dial("tcp", proxyURL.Host) addr, _ := getLocalHostMapping(GOOGLE_HTTPS) connreq := req.RawReq connreq.Host = addr if nil == err { connreq.Write(proxyConn) } } else { addr := getGoogleHostport(true) proxyConn, err = net.DialTimeout("tcp", addr, connTimeoutSecs) if nil != err { //try again addr = getGoogleHostport(true) proxyConn, err = net.DialTimeout("tcp", addr, connTimeoutSecs) } } log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if nil == err { if len(googleLocalProxy) > 0 { } else { conn.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) } } else { return fmt.Errorf("No google proxy reachable:%v", err), nil } ch := make(chan int) go f(conn.LocalRawConn, proxyConn, ch) go f(proxyConn, conn.LocalRawConn, ch) atomic.AddInt32(&total_google_routine_num, 2) <-ch <-ch atomic.AddInt32(&total_google_routine_num, -2) proxyConn.Close() google.Close() conn.State = STATE_SESSION_CLOSE } else { google.proxyAddr = req.RawReq.Host log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) req.RawReq.URL.Scheme = "http" req.RawReq.RequestURI = "" var resp *http.Response tryProxy := func() (*http.Response, error) { if google.manager == httpGoogleManager { return httpGoogleClient.Do(req.RawReq) } return httpsGoogleClient.Do(req.RawReq) } resp, err = tryProxy() if nil != err && strings.EqualFold(req.Method, "GET") { //try proxy again resp, err = tryProxy() } if nil != err { var tmp bytes.Buffer req.RawReq.Write(&tmp) log.Printf("Session[%d]Request error:%v\n%s\n", req.GetHash(), err, tmp.String()) return err, nil } err = resp.Write(conn.LocalRawConn) if nil != err || !util.IsResponseKeepAlive(resp) || !util.IsRequestKeepAlive(req.RawReq) { conn.LocalRawConn.Close() conn.State = STATE_SESSION_CLOSE } else { log.Printf("Session[%d]Res %d %v\n", req.GetHash(), resp.StatusCode, resp.Header) conn.State = STATE_RECV_HTTP } } default: } return nil, nil }
func (gae *GAEHttpConnection) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { gae.closed = false gae.sess = conn if gae.over_tunnel { return gae.requestOverTunnel(conn, ev) } if nil == gae.gaeAuth { gae.gaeAuth = gae.manager.auths.Select().(*GAEAuth) } if ev.GetType() == event.HTTP_REQUEST_EVENT_TYPE { httpreq := ev.(*event.HTTPRequestEvent) if strings.EqualFold(httpreq.Method, "CONNECT") { // //try https over tunnel // if gae.gaeAuth.support_tunnel { // gae.over_tunnel = true // return gae.requestOverTunnel(conn, ev) // } log.Printf("Session[%d]Request %s\n", httpreq.GetHash(), util.GetURLString(httpreq.RawReq, true)) conn.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) tlscfg, err := common.TLSConfig(httpreq.GetHeader("Host")) if nil != err { return err, nil } conn.LocalRawConn = tls.Server(conn.LocalRawConn, tlscfg) conn.LocalBufferConn = bufio.NewReader(conn.LocalRawConn) conn.State = STATE_RECV_HTTP conn.Type = HTTPS_TUNNEL return nil, nil } else { if httpreq.Content.Len() == 0 { body := make([]byte, httpreq.RawReq.ContentLength) io.ReadFull(httpreq.RawReq.Body, body) httpreq.Content.Write(body) } scheme := "http://" if conn.Type == HTTPS_TUNNEL { scheme = "https://" } if !strings.HasPrefix(httpreq.Url, scheme) { httpreq.Url = scheme + httpreq.RawReq.Host + httpreq.Url } log.Printf("Session[%d]Request %s\n", httpreq.GetHash(), util.GetURLString(httpreq.RawReq, true)) var httpres *http.Response if strings.EqualFold(httpreq.Method, "GET") { if hostPatternMatched(gae_cfg.InjectRange, httpreq.RawReq.Host) || gae.inject_range { //conn.State = STATE_RECV_HTTP gae.doRangeFetch(httpreq.RawReq, nil) return nil, nil } } err, res = gae.requestEvent(gaeHttpClient, conn, ev) if nil != err { //try again err, res = gae.requestEvent(gaeHttpClient, conn, ev) } if nil != err || nil == res { return } conn.State = STATE_RECV_HTTP httpresev := res.(*event.HTTPResponseEvent) if httpresev.Status == 403 { log.Printf("ERROR:Session[%d]Request %s %s is forbidon\n", httpreq.GetHash(), httpreq.Method, httpreq.RawReq.Host) } httpres, err = gae.handleHttpRes(conn, httpreq, httpresev) // if nil != httpres { // log.Printf("Session[%d]Response %d %v\n", httpreq.GetHash(), httpres.StatusCode, httpres.Header) // } if nil != err || !util.IsResponseKeepAlive(httpres) || !util.IsRequestKeepAlive(httpreq.RawReq) { conn.LocalRawConn.Close() conn.State = STATE_SESSION_CLOSE gae.Close() } return err, nil } } return gae.requestEvent(gaeHttpClient, conn, ev) }