diff options
| author | Mikhail Osipov <mike.osipov@gmail.com> | 2020-05-05 20:10:08 +0300 |
|---|---|---|
| committer | Mikhail Osipov <mike.osipov@gmail.com> | 2020-05-05 20:10:08 +0300 |
| commit | b089b35f35a14e85d89df69254cc61495d59d3dd (patch) | |
| tree | da07e5b015e02f7fa05cf0be181697670af787ed /pkg/server/hook/proxy.go | |
| parent | f44d6e1a111154b70aaeac9ffe38beaee2cc5dd7 (diff) | |
add http connect proxy server
Diffstat (limited to 'pkg/server/hook/proxy.go')
| -rw-r--r-- | pkg/server/hook/proxy.go | 89 |
1 files changed, 15 insertions, 74 deletions
diff --git a/pkg/server/hook/proxy.go b/pkg/server/hook/proxy.go index 64db784..26be2d0 100644 --- a/pkg/server/hook/proxy.go +++ b/pkg/server/hook/proxy.go @@ -1,23 +1,17 @@ package hook import ( - "bufio" "bytes" - "encoding/base64" "errors" "fmt" - "io" "regexp" - "strconv" + "tunnel/pkg/http" "tunnel/pkg/server/env" "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) var addrRe = regexp.MustCompile("^[0-9a-zA-Z-.]+:[0-9]+$") -var respRe = regexp.MustCompile("^([^ ]+) +([0-9]+) +(.*)$") - -var errBadHttpResponse = errors.New("bad HTTP response") type proxyHook struct { addr string @@ -27,93 +21,41 @@ type proxyHook struct { type proxy struct { addr string auth string - ok chan struct{} - fail chan struct{} + c chan bool } func (p *proxy) Send(rq, wq queue.Q) error { var out bytes.Buffer - fmt.Fprintf(&out, "CONNECT %s HTTP/1.0\r\n", p.addr) + fmt.Fprintf(&out, "CONNECT %s HTTP/1.1\r\n", p.addr) if p.auth != "" { - encoded := base64.StdEncoding.EncodeToString([]byte(p.auth)) - fmt.Fprintf(&out, "Proxy-Authorization: Basic %s\r\n", encoded) + encoded := http.BasicAuthEncode(p.auth) + fmt.Fprintf(&out, "Proxy-Authorization: %s\r\n", encoded) } fmt.Fprintf(&out, "\r\n") wq <- out.Bytes() - select { - case <-p.fail: + if !<-p.c { return nil - case <-p.ok: } return queue.Copy(rq, wq) } -func parseProxyResponse(s string) error { - var version string - var code int - var desc string - - if m := respRe.FindStringSubmatch(s); m == nil { - return errBadHttpResponse - } else { - version = m[1] - if c, err := strconv.Atoi(m[2]); err != nil { - return errBadHttpResponse - } else { - code = c - } - desc = m[3] - } - - if version != "HTTP/1.0" && version != "HTTP/1.1" { - return errBadHttpResponse - } - - if code != 200 { - return fmt.Errorf("connect failed: %d %s", code, desc) - } - - return nil -} - -func (p *proxy) Recv(rq, wq queue.Q) (err error) { - defer func() { - if err != nil { - close(p.fail) - } - }() - - s := bufio.NewScanner(rq.Reader()) - - var resp bool - - for s.Scan() { - line := s.Text() - - if !resp { - if err := parseProxyResponse(line); err != nil { - return err - } - resp = true - continue - } +func (p *proxy) Recv(rq, wq queue.Q) error { + resp, err := http.ParseResponse(rq.Reader()) - if line == "" { - break - } + if err == nil && resp.Code != http.OK { + err = fmt.Errorf("connect failed: %d %s", resp.Code, resp.Desc) } - if err := s.Err(); err != nil { + if err != nil { + p.c <- false return err - } else if !resp { - return io.ErrUnexpectedEOF } - close(p.ok) + p.c <- true return queue.Copy(rq, wq) } @@ -122,12 +64,11 @@ func (h *proxyHook) Open(env env.Env) (interface{}, error) { p := &proxy{ addr: h.addr, auth: h.auth, - ok: make(chan struct{}), - fail: make(chan struct{}), + c: make(chan bool), } if p.auth == "" { - p.auth = getHookVar(env, "proxy.auth") + p.auth = env.GetLocal("proxy.auth") } return p, nil |
