コード例 #1
0
ファイル: ssh.go プロジェクト: juju2013/gsnova
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
}
コード例 #2
0
ファイル: gfwlist.go プロジェクト: juju2013/gsnova
func (r *urlRegexRule) match(req *http.Request) bool {
	ret := r.url_reg.MatchString(util.GetURLString(req, false))
	//	if ret{
	//	   log.Printf("url is %s, rule is %s\n", util.GetURLString(req, false), r.url_reg.String())
	//	}
	return ret
}
コード例 #3
0
ファイル: gae_tunnel.go プロジェクト: juju2013/gsnova
func (gae *GAEHttpConnection) requestOverTunnel(conn *SessionConnection, ev event.Event) (err error, res event.Event) {
	if nil == gae.tunnelChannel {
		gae.tunnelChannel = make(chan event.Event)
		go gae.tunnel_write(conn)
		//go gae.tunnel_read(conn)
	}
	switch ev.GetType() {
	case event.HTTP_REQUEST_EVENT_TYPE:
		req := ev.(*event.HTTPRequestEvent)
		default_port := "80"
		if strings.EqualFold(req.RawReq.Method, "CONNECT") {
			conn.State = STATE_RECV_HTTP_CHUNK
			default_port = "443"
		} else {
			conn.State = STATE_RECV_HTTP
		}
		log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true))
		scd := &event.SocketConnectWithDataEvent{}
		scd.Content, err = httputil.DumpRequest(req.RawReq, true)
		if nil != err {
			log.Printf("Session[%d]Failed to encode request to bytes", req.GetHash())
			return
		}
		scd.SetHash(ev.GetHash())
		scd.Net = "tcp"
		scd.Addr = req.RawReq.Host
		if !strings.Contains(scd.Addr, ":") {
			scd.Addr = net.JoinHostPort(req.RawReq.Host, default_port)
		}
		gae.tunnel_remote_addr = scd.Addr
		gae.tunnelChannel <- scd
	case event.HTTP_CHUNK_EVENT_TYPE:
		chunk := ev.(*event.HTTPChunkEvent)
		tcp_chunk := &event.TCPChunkEvent{Content: chunk.Content}
		tcp_chunk.SetHash(ev.GetHash())
		gae.tunnelChannel <- tcp_chunk
		conn.State = STATE_RECV_HTTP_CHUNK
	}
	return nil, nil
}
コード例 #4
0
ファイル: forward.go プロジェクト: juju2013/gsnova
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
}
コード例 #5
0
ファイル: gfwlist.go プロジェクト: juju2013/gsnova
func (r *urlWildcardRule) match(req *http.Request) bool {
	return util.WildcardMatch(util.GetURLString(req, false), r.url_rule)
}
コード例 #6
0
ファイル: google.go プロジェクト: juju2013/gsnova
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
}
コード例 #7
0
ファイル: gae.go プロジェクト: juju2013/gsnova
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)
}
コード例 #8
0
ファイル: c4.go プロジェクト: juju2013/gsnova
func (c4 *C4RemoteSession) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) {
	c4.sess = conn
	if len(c4.server) == 0 {
		c4.server = c4.manager.servers.Select().(string)
	}
	c4.sess = conn
	c4.closed = false
	setC4SessionTable(c4)
	switch ev.GetType() {
	case event.HTTP_REQUEST_EVENT_TYPE:
		req := ev.(*event.HTTPRequestEvent)
		default_port := "80"
		if strings.EqualFold(req.RawReq.Method, "CONNECT") {
			conn.State = STATE_RECV_HTTP_CHUNK
			default_port = "443"
		} else {
			conn.State = STATE_RECV_HTTP
		}
		log.Printf("Session[%d] Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true))
		if nil != err {
			log.Printf("Session[%d]Failed to encode request to bytes", req.GetHash())
			return
		}
		remote_addr := req.RawReq.Host
		if !strings.Contains(remote_addr, ":") {
			remote_addr = net.JoinHostPort(req.RawReq.Host, default_port)
		}
		if strings.Contains(req.Url, "http://") {
			req.Url = req.Url[7+len(req.RawReq.Host):]
		}
		c4.rangeWorker = nil
		c4.remote_proxy_addr = remote_addr
		if strings.EqualFold(req.Method, "GET") && c4_cfg.MultiRangeFetchEnable {
			if c4.injectRange || hostPatternMatched(c4_cfg.InjectRange, req.RawReq.Host) {
				if nil == c4.doRangeFetch(req.RawReq) {
					return nil, nil
				}
			}
		}

		c4.offerRequestEvent(req)
		rest := req.RawReq.ContentLength
		tmpbuf := make([]byte, 8192)
		for rest > 0 {
			n, err := req.RawReq.Body.Read(tmpbuf)
			if nil == err {
				rest = rest - int64(n)
				chunk := &event.TCPChunkEvent{Content: tmpbuf[0:n]}
				chunk.SetHash(req.GetHash())
				c4.offerRequestEvent(chunk)
			} else {
				break
			}
		}
		req.RawReq.Body.Close()
	case event.HTTP_CHUNK_EVENT_TYPE:
		//log.Printf("Session[%d]Offer chunk\n", conn.SessionID)
		chunk := ev.(*event.HTTPChunkEvent)
		tcp_chunk := &event.TCPChunkEvent{Content: chunk.Content}
		tcp_chunk.SetHash(ev.GetHash())
		c4.offerRequestEvent(tcp_chunk)
		conn.State = STATE_RECV_HTTP_CHUNK
	}
	return nil, nil
}