hysteria/pkg/http/server.go
mritd fad7cf0206
feat(client): support https proxy
support https proxy
use the built-in basic auth extension

ref tobyxdd/hysteria#14 tobyxdd/hysteria#15

Signed-off-by: mritd <mritd@linux.com>
2020-08-07 18:11:44 +08:00

67 lines
1.8 KiB
Go

package http
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"time"
"github.com/elazarl/goproxy/ext/auth"
"github.com/elazarl/goproxy"
"github.com/tobyxdd/hysteria/pkg/acl"
"github.com/tobyxdd/hysteria/pkg/core"
)
func NewProxyHTTPServer(hyClient core.Client, idleTimeout time.Duration, aclEngine *acl.Engine,
newDialFunc func(reqAddr string, action acl.Action, arg string),
basicAuthFunc func(user, password string) bool) (*goproxy.ProxyHttpServer, error) {
proxy := goproxy.NewProxyHttpServer()
proxy.Logger = &nopLogger{}
proxy.NonproxyHandler = http.NotFoundHandler()
proxy.Tr = &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
// Parse addr string
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
ip := net.ParseIP(host)
if ip != nil {
host = ""
}
// ACL
action, arg := acl.ActionProxy, ""
if aclEngine != nil {
action, arg = aclEngine.Lookup(host, ip)
}
newDialFunc(addr, action, arg)
// Handle according to the action
switch action {
case acl.ActionDirect:
return net.Dial(network, addr)
case acl.ActionProxy:
return hyClient.Dial(false, addr)
case acl.ActionBlock:
return nil, errors.New("blocked in ACL")
case acl.ActionHijack:
return net.Dial(network, net.JoinHostPort(arg, port))
default:
return nil, fmt.Errorf("unknown action %d", action)
}
},
IdleConnTimeout: idleTimeout,
// TODO: Disable HTTP2 support? ref: https://github.com/elazarl/goproxy/issues/361
//TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
}
proxy.ConnectDial = nil
auth.ProxyBasic(proxy, "hysteria client", basicAuthFunc)
return proxy, nil
}
type nopLogger struct{}
func (n *nopLogger) Printf(format string, v ...interface{}) {}