improve http tunnel

This commit is contained in:
rui.zheng 2015-06-05 11:37:30 +08:00
parent 907f39a43d
commit 30159a1d08
3 changed files with 62 additions and 45 deletions

View File

@ -107,7 +107,7 @@ func cliHandle(conn net.Conn) {
var c net.Conn var c net.Conn
var err error var err error
if !UseHttp { if UseWebsocket || !UseHttp {
c, err = ConnectProxy(Saddr, Proxy) c, err = ConnectProxy(Saddr, Proxy)
} else { } else {
addr := Saddr addr := Saddr
@ -123,10 +123,7 @@ func cliHandle(conn net.Conn) {
defer c.Close() defer c.Close()
if UseWebsocket { if UseWebsocket {
url := &url.URL{ ws, resp, err := websocket.NewClient(c, &url.URL{Host: Saddr}, nil, 8192, 8192)
Host: Saddr,
}
ws, resp, err := websocket.NewClient(c, url, nil, 8192, 8192)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return return

98
http.go
View File

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"code.google.com/p/go-uuid/uuid" "code.google.com/p/go-uuid/uuid"
"errors"
"github.com/ginuerzh/gosocks5" "github.com/ginuerzh/gosocks5"
"io" "io"
"io/ioutil" "io/ioutil"
@ -20,9 +21,9 @@ const (
) )
type HttpClientConn struct { type HttpClientConn struct {
c net.Conn c net.Conn
url *url.URL token string
r io.ReadCloser r io.ReadCloser
} }
func NewHttpClientConn(conn net.Conn) *HttpClientConn { func NewHttpClientConn(conn net.Conn) *HttpClientConn {
@ -32,12 +33,11 @@ func NewHttpClientConn(conn net.Conn) *HttpClientConn {
} }
func (conn *HttpClientConn) Handshake() (err error) { func (conn *HttpClientConn) Handshake() (err error) {
log.Println("remote", conn.c.RemoteAddr().String()) //log.Println("remote", conn.c.RemoteAddr().String())
req := &http.Request{ req := &http.Request{
Method: "Get", Method: "GET",
Host: Saddr,
URL: &url.URL{ URL: &url.URL{
Host: "ignored", Host: Saddr,
Scheme: "http", Scheme: "http",
Path: s2cUri, Path: s2cUri,
}, },
@ -60,59 +60,52 @@ func (conn *HttpClientConn) Handshake() (err error) {
if _, err = io.ReadFull(resp.Body, b); err != nil { if _, err = io.ReadFull(resp.Body, b); err != nil {
return err return err
} }
if uuid.Parse(string(b)) == nil {
q := url.Values{} return errors.New("wrong token")
q.Set("token", string(b))
conn.url = &url.URL{
Scheme: "http",
Host: Saddr,
Path: c2sUri,
RawQuery: q.Encode(),
} }
conn.token = string(b)
conn.r = resp.Body conn.r = resp.Body
//log.Println(conn.token, "connected")
log.Println(conn.url.String())
return nil return nil
} }
func (conn *HttpClientConn) Read(b []byte) (n int, err error) { func (conn *HttpClientConn) Read(b []byte) (n int, err error) {
n, err = conn.r.Read(b) n, err = conn.r.Read(b)
log.Println("http r:", n) //log.Println("http r:", n)
return return
} }
func (conn *HttpClientConn) Write(b []byte) (n int, err error) { func (conn *HttpClientConn) Write(b []byte) (n int, err error) {
var c net.Conn q := url.Values{}
if len(Proxy) == 0 { q.Set("token", conn.token)
c, err = Connect(Saddr) req := &http.Request{
} else { Method: "POST",
c, err = Connect(Proxy) Body: ioutil.NopCloser(bytes.NewReader(b)),
ContentLength: int64(len(b)),
URL: &url.URL{
Host: Saddr,
Scheme: "http",
Path: c2sUri,
RawQuery: q.Encode(),
},
} }
resp, err := doRequest(req, Proxy)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return return
} }
resp.Body.Close()
request, err := http.NewRequest("POST", conn.url.String(), bytes.NewReader(b)) if resp.StatusCode != http.StatusOK {
if err != nil { return 0, errors.New(resp.Status)
log.Println(err)
return
} }
if len(Proxy) == 0 { //log.Println("http w:", len(b))
err = request.Write(c)
} else {
err = request.WriteProxy(c)
}
if err != nil {
log.Println(err)
return
}
log.Println("http w:", len(b))
return len(b), nil return len(b), nil
} }
func (conn *HttpClientConn) Close() error { func (conn *HttpClientConn) Close() error {
conn.Write(nil)
return conn.r.Close() return conn.r.Close()
} }
@ -159,7 +152,7 @@ func (conn *HttpServerConn) Read(b []byte) (n int, err error) {
n = copy(b, conn.rb) n = copy(b, conn.rb)
conn.rb = conn.rb[n:] conn.rb = conn.rb[n:]
log.Println("http r:", n) //log.Println("http r:", n)
return return
} }
@ -169,7 +162,7 @@ func (conn *HttpServerConn) Write(b []byte) (n int, err error) {
if f, ok := conn.w.(http.Flusher); ok { if f, ok := conn.w.(http.Flusher); ok {
f.Flush() f.Flush()
} }
log.Println("http w:", n) //log.Println("http w:", n)
return return
} }
@ -235,6 +228,7 @@ func (s *HttpServer) c2s(w http.ResponseWriter, r *http.Request) {
if err != nil || len(b) == 0 { if err != nil || len(b) == 0 {
close(ch) close(ch)
delete(s.chans, token) delete(s.chans, token)
//log.Println(token, "disconnected")
return return
} }
ch <- b ch <- b
@ -246,3 +240,29 @@ func (s *HttpServer) ListenAndServe() error {
http.HandleFunc(c2sUri, s.c2s) http.HandleFunc(c2sUri, s.c2s)
return http.ListenAndServe(s.Addr, nil) return http.ListenAndServe(s.Addr, nil)
} }
func doRequest(req *http.Request, proxy string) (*http.Response, error) {
if len(proxy) > 0 {
c, err := Connect(proxy)
if err != nil {
log.Println(err)
return nil, err
}
defer c.Close()
if err := req.WriteProxy(c); err != nil {
log.Println(err)
return nil, err
}
/*
b, err := ioutil.ReadAll(c)
if err != nil {
log.Println(err)
return nil, err
}
*/
return http.ReadResponse(bufio.NewReader(c), req)
}
return http.DefaultClient.Do(req)
}

View File

@ -175,7 +175,7 @@ func socks5Handle(conn net.Conn) {
switch req.Cmd { switch req.Cmd {
case gosocks5.CmdConnect: case gosocks5.CmdConnect:
log.Println("connect", req.Addr.String()) //log.Println("connect", req.Addr.String())
tconn, err := ConnectProxy(req.Addr.String(), Proxy) tconn, err := ConnectProxy(req.Addr.String(), Proxy)
if err != nil { if err != nil {
gosocks5.NewReply(gosocks5.HostUnreachable, nil).Write(conn) gosocks5.NewReply(gosocks5.HostUnreachable, nil).Write(conn)