hysteria/pkg/http/server.go
mritd ca1f1fdcab
feat(client): add http basic auth
add http basic auth

ref tobyxdd/hysteria#15

Signed-off-by: mritd <mritd@linux.com>
2020-08-07 14:12:01 +08:00

62 lines
1.6 KiB
Go

package http
import (
"errors"
"fmt"
"net"
"net/http"
"time"
"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(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response)) (*goproxy.ProxyHttpServer, error) {
proxy := goproxy.NewProxyHttpServer()
proxy.Logger = &nopLogger{}
proxy.NonproxyHandler = http.NotFoundHandler()
proxy.OnRequest().DoFunc(basicAuthFunc)
proxy.Tr = &http.Transport{
Dial: func(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,
}
proxy.ConnectDial = nil
return proxy, nil
}
type nopLogger struct{}
func (n *nopLogger) Printf(format string, v ...interface{}) {}