summaryrefslogtreecommitdiff
path: root/pkg/server/hook/proxy.go
diff options
context:
space:
mode:
authorMikhail Osipov <mike.osipov@gmail.com>2020-05-05 20:10:08 +0300
committerMikhail Osipov <mike.osipov@gmail.com>2020-05-05 20:10:08 +0300
commitb089b35f35a14e85d89df69254cc61495d59d3dd (patch)
treeda07e5b015e02f7fa05cf0be181697670af787ed /pkg/server/hook/proxy.go
parentf44d6e1a111154b70aaeac9ffe38beaee2cc5dd7 (diff)
add http connect proxy server
Diffstat (limited to 'pkg/server/hook/proxy.go')
-rw-r--r--pkg/server/hook/proxy.go89
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