1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
package socket
import (
"bytes"
"errors"
"fmt"
"tunnel/pkg/http"
"tunnel/pkg/server/env"
"tunnel/pkg/server/queue"
)
type status struct {
code int
desc string
}
type proxySocket struct {
proto string
}
type proxyServer struct {
sock *proxySocket
addr string
auth string
wait chan status
env env.Env
conn Conn
}
func newProxySocket(proto string) (S, error) {
return &proxySocket{proto}, nil
}
func (sock *proxySocket) Open(env env.Env) (Conn, error) {
s := &proxyServer{
sock: sock,
auth: env.GetLocal("proxy.auth"),
wait: make(chan status),
env: env,
}
return s, nil
}
func (sock *proxySocket) Close() {
}
func (s *proxyServer) String() string {
return "proxy"
}
func (s *proxyServer) Send(wq queue.Q) error {
var out bytes.Buffer
status := <-s.wait
fmt.Fprintf(&out, "HTTP/1.0 %d %s\r\n", status.code, status.desc)
switch status.code {
case http.OK:
fmt.Fprintf(&out, "Proxy-Agent: tunnel\r\n")
case 407:
fmt.Fprintf(&out, "Proxy-Authenticate: Basic realm=\"tunnel\"\r\n")
fallthrough
default:
fmt.Fprintf(&out, "Server: tunnel\r\n")
fmt.Fprintf(&out, "Connection: close\r\n")
}
fmt.Fprintf(&out, "\r\n")
wq <- out.Bytes()
if status.code != http.OK {
return nil
}
return s.conn.Send(wq)
}
func (s *proxyServer) initConn(addr string) error {
dial, err := newDialSocket(s.sock.proto, addr)
if err != nil {
return err
}
conn, err := dial.Open(s.env)
if err != nil {
dial.Close()
return err
}
s.conn = conn
return nil
}
func (s *proxyServer) Recv(rq queue.Q) error {
req, err := http.ParseRequest(rq.Reader())
if err != nil {
s.wait <- status{400, "Bad Request"}
return err
}
if req.Method != "CONNECT" {
s.wait <- status{400, "Bad Request"}
return errors.New("bad method")
}
if s.auth != "" {
if auth, ok := req.Header["Proxy-Authorization"]; !ok {
s.wait <- status{407, "Proxy Authentication Required"}
return errors.New("auth required")
} else if !http.BasicAuthCheck(s.auth, auth) {
s.wait <- status{401, "Unauthorized"}
return errors.New("auth failed")
}
}
if err := s.initConn(req.URI); err != nil {
s.wait <- status{500, "Unable to connect"}
return err
}
s.wait <- status{200, "Connection established"}
return s.conn.Recv(rq)
}
func (s *proxyServer) Close() (err error) {
if s.conn != nil {
err = s.conn.Close()
}
return
}
|