mirror of
https://github.com/cmz0228/hysteria-dev.git
synced 2025-06-12 07:19:53 +00:00
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>
This commit is contained in:
parent
c35adc2d73
commit
fad7cf0206
@ -3,14 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/elazarl/goproxy"
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/lucas-clemente/quic-go/congestion"
|
"github.com/lucas-clemente/quic-go/congestion"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -157,44 +154,22 @@ func proxyClient(args []string) {
|
|||||||
"dst": reqAddr,
|
"dst": reqAddr,
|
||||||
}).Debug("New HTTP request")
|
}).Debug("New HTTP request")
|
||||||
},
|
},
|
||||||
func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
|
func(user, password string) bool {
|
||||||
if config.HTTPUser == "" || config.HTTPPassword == "" {
|
if config.HTTPUser == "" || config.HTTPPassword == "" {
|
||||||
return req, nil
|
return true
|
||||||
}
|
}
|
||||||
|
return config.HTTPUser == user && config.HTTPPassword == password
|
||||||
resp := goproxy.NewResponse(req, goproxy.ContentTypeText, http.StatusUnauthorized, "401 - Forbidden: Unauthorized")
|
|
||||||
// RFC7617 section 2.1
|
|
||||||
pa := req.Header.Get("Proxy-Authorization")
|
|
||||||
if pa == "" {
|
|
||||||
return req, resp
|
|
||||||
}
|
|
||||||
authStr := strings.Fields(pa)
|
|
||||||
if len(authStr) != 2 || authStr[0] != "Basic" {
|
|
||||||
return req, resp
|
|
||||||
}
|
|
||||||
decodeBytes, err := base64.StdEncoding.DecodeString(authStr[1])
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithFields(logrus.Fields{
|
|
||||||
"error": err,
|
|
||||||
"cred": authStr[1],
|
|
||||||
}).Debug("Failed to decode base64 auth string")
|
|
||||||
return req, resp
|
|
||||||
}
|
|
||||||
userAndPassword := strings.Split(string(decodeBytes), ":")
|
|
||||||
if len(userAndPassword) != 2 {
|
|
||||||
return req, resp
|
|
||||||
}
|
|
||||||
if userAndPassword[0] != config.HTTPUser || userAndPassword[1] != config.HTTPPassword {
|
|
||||||
return req, resp
|
|
||||||
}
|
|
||||||
|
|
||||||
return req, nil
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithField("error", err).Fatal("HTTP server initialization failed")
|
logrus.WithField("error", err).Fatal("HTTP server initialization failed")
|
||||||
}
|
}
|
||||||
logrus.WithField("addr", config.HTTPAddr).Info("HTTP server up and running")
|
if config.HTTPSCert != "" && config.HTTPSKey != "" {
|
||||||
errChan <- http.ListenAndServe(config.HTTPAddr, proxy)
|
logrus.WithField("addr", config.HTTPAddr).Info("HTTPS server up and running")
|
||||||
|
errChan <- http.ListenAndServeTLS(config.HTTPAddr, config.HTTPSCert, config.HTTPSKey, proxy)
|
||||||
|
} else {
|
||||||
|
logrus.WithField("addr", config.HTTPAddr).Info("HTTP server up and running")
|
||||||
|
errChan <- http.ListenAndServe(config.HTTPAddr, proxy)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ type proxyClientConfig struct {
|
|||||||
HTTPTimeout int `json:"http_timeout" desc:"HTTP connection timeout in seconds"`
|
HTTPTimeout int `json:"http_timeout" desc:"HTTP connection timeout in seconds"`
|
||||||
HTTPUser string `json:"http_user" desc:"HTTP basic auth username"`
|
HTTPUser string `json:"http_user" desc:"HTTP basic auth username"`
|
||||||
HTTPPassword string `json:"http_password" desc:"HTTP basic auth password"`
|
HTTPPassword string `json:"http_password" desc:"HTTP basic auth password"`
|
||||||
|
HTTPSCert string `json:"https_cert" desc:"HTTPS cert file"`
|
||||||
|
HTTPSKey string `json:"https_key" desc:"HTTPS cert key"`
|
||||||
ACLFile string `json:"acl" desc:"Access control list"`
|
ACLFile string `json:"acl" desc:"Access control list"`
|
||||||
ServerAddr string `json:"server" desc:"Server address"`
|
ServerAddr string `json:"server" desc:"Server address"`
|
||||||
Username string `json:"username" desc:"Authentication username"`
|
Username string `json:"username" desc:"Authentication username"`
|
||||||
|
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.14
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/elazarl/goproxy v0.0.0-20200426045556-49ad98f6dac1
|
github.com/elazarl/goproxy v0.0.0-20200426045556-49ad98f6dac1
|
||||||
|
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2
|
||||||
github.com/golang/protobuf v1.4.0
|
github.com/golang/protobuf v1.4.0
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
github.com/lucas-clemente/quic-go v0.16.1
|
github.com/lucas-clemente/quic-go v0.16.1
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/elazarl/goproxy/ext/auth"
|
||||||
|
|
||||||
"github.com/elazarl/goproxy"
|
"github.com/elazarl/goproxy"
|
||||||
"github.com/tobyxdd/hysteria/pkg/acl"
|
"github.com/tobyxdd/hysteria/pkg/acl"
|
||||||
"github.com/tobyxdd/hysteria/pkg/core"
|
"github.com/tobyxdd/hysteria/pkg/core"
|
||||||
@ -14,13 +17,12 @@ import (
|
|||||||
|
|
||||||
func NewProxyHTTPServer(hyClient core.Client, idleTimeout time.Duration, aclEngine *acl.Engine,
|
func NewProxyHTTPServer(hyClient core.Client, idleTimeout time.Duration, aclEngine *acl.Engine,
|
||||||
newDialFunc func(reqAddr string, action acl.Action, arg string),
|
newDialFunc func(reqAddr string, action acl.Action, arg string),
|
||||||
basicAuthFunc func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response)) (*goproxy.ProxyHttpServer, error) {
|
basicAuthFunc func(user, password string) bool) (*goproxy.ProxyHttpServer, error) {
|
||||||
proxy := goproxy.NewProxyHttpServer()
|
proxy := goproxy.NewProxyHttpServer()
|
||||||
proxy.Logger = &nopLogger{}
|
proxy.Logger = &nopLogger{}
|
||||||
proxy.NonproxyHandler = http.NotFoundHandler()
|
proxy.NonproxyHandler = http.NotFoundHandler()
|
||||||
proxy.OnRequest().DoFunc(basicAuthFunc)
|
|
||||||
proxy.Tr = &http.Transport{
|
proxy.Tr = &http.Transport{
|
||||||
Dial: func(network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
// Parse addr string
|
// Parse addr string
|
||||||
host, port, err := net.SplitHostPort(addr)
|
host, port, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -51,8 +53,11 @@ func NewProxyHTTPServer(hyClient core.Client, idleTimeout time.Duration, aclEngi
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
IdleConnTimeout: idleTimeout,
|
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
|
proxy.ConnectDial = nil
|
||||||
|
auth.ProxyBasic(proxy, "hysteria client", basicAuthFunc)
|
||||||
return proxy, nil
|
return proxy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user