mirror of
https://github.com/cmz0228/hysteria-dev.git
synced 2025-08-17 06:41:45 +00:00
.github
cmd
docs
pkg
acl
auth
congestion
core
http
server.go
obfs
relay
socks5
tproxy
utils
.gitignore
ACL.md
ACL.zh.md
Dockerfile
LICENSE.md
README.md
README.zh.md
go.mod
go.sum
75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package http
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/tobyxdd/hysteria/pkg/utils"
|
|
"net"
|
|
"net/http"
|
|
"strconv"
|
|
"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, transport core.Transport, 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{
|
|
Dial: func(network, addr string) (net.Conn, error) {
|
|
// Parse addr string
|
|
host, port, err := utils.SplitHostPort(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// ACL
|
|
action, arg := acl.ActionProxy, ""
|
|
var ipAddr *net.IPAddr
|
|
var resErr error
|
|
if aclEngine != nil {
|
|
action, arg, ipAddr, resErr = aclEngine.ResolveAndMatch(host)
|
|
// Doesn't always matter if the resolution fails, as we may send it through HyClient
|
|
}
|
|
newDialFunc(addr, action, arg)
|
|
// Handle according to the action
|
|
switch action {
|
|
case acl.ActionDirect:
|
|
if resErr != nil {
|
|
return nil, resErr
|
|
}
|
|
return transport.OutDialTCP(nil, &net.TCPAddr{
|
|
IP: ipAddr.IP,
|
|
Port: int(port),
|
|
Zone: ipAddr.Zone,
|
|
})
|
|
case acl.ActionProxy:
|
|
return hyClient.DialTCP(addr)
|
|
case acl.ActionBlock:
|
|
return nil, errors.New("blocked by ACL")
|
|
case acl.ActionHijack:
|
|
return transport.OutDial(network, net.JoinHostPort(arg, strconv.Itoa(int(port))))
|
|
default:
|
|
return nil, fmt.Errorf("unknown action %d", action)
|
|
}
|
|
},
|
|
IdleConnTimeout: idleTimeout,
|
|
// Disable HTTP2 support? ref: https://github.com/elazarl/goproxy/issues/361
|
|
}
|
|
proxy.ConnectDial = nil
|
|
if basicAuthFunc != nil {
|
|
auth.ProxyBasic(proxy, "hysteria client", basicAuthFunc)
|
|
}
|
|
return proxy, nil
|
|
}
|
|
|
|
type nopLogger struct{}
|
|
|
|
func (n *nopLogger) Printf(format string, v ...interface{}) {}
|