Merge from remote branch

This commit is contained in:
yaling888 2021-09-17 15:07:27 +08:00 committed by GitHub
commit fbda82218e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 41 additions and 26 deletions

View File

@ -9,7 +9,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17 go-version: 1.17.x
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
uses: actions/checkout@v2 uses: actions/checkout@v2

View File

@ -9,8 +9,8 @@ import (
) )
// NewHTTP receive normal http request and return HTTPContext // NewHTTP receive normal http request and return HTTPContext
func NewHTTP(target string, source net.Addr, conn net.Conn) *context.ConnContext { func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn) *context.ConnContext {
metadata := parseSocksAddr(socks5.ParseAddr(target)) metadata := parseSocksAddr(target)
metadata.NetWork = C.TCP metadata.NetWork = C.TCP
metadata.Type = C.HTTP metadata.Type = C.HTTP
if ip, port, err := parseAddr(source.String()); err == nil { if ip, port, err := parseAddr(source.String()); err == nil {

View File

@ -23,7 +23,7 @@ import (
R "github.com/Dreamacro/clash/rule" R "github.com/Dreamacro/clash/rule"
T "github.com/Dreamacro/clash/tunnel" T "github.com/Dreamacro/clash/tunnel"
yaml "gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
// General config // General config
@ -206,7 +206,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
}, },
} }
if err := yaml.Unmarshal(buf, &rawCfg); err != nil { if err := yaml.Unmarshal(buf, rawCfg); err != nil {
return nil, err return nil, err
} }

View File

@ -20,15 +20,20 @@ type client struct {
host string host string
} }
func (c *client) Exchange(m *D.Msg) (msg *D.Msg, err error) { func (c *client) Exchange(m *D.Msg) (*D.Msg, error) {
return c.ExchangeContext(context.Background(), m) return c.ExchangeContext(context.Background(), m)
} }
func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) {
var ip net.IP var (
ip net.IP
err error
)
if c.r == nil { if c.r == nil {
// a default ip dns // a default ip dns
ip = net.ParseIP(c.host) if ip = net.ParseIP(c.host); ip == nil {
return nil, fmt.Errorf("dns %s not a valid ip", c.host)
}
} else { } else {
if ip, err = resolver.ResolveIPWithResolver(c.host, c.r); err != nil { if ip, err = resolver.ResolveIPWithResolver(c.host, c.r); err != nil {
return nil, fmt.Errorf("use default dns resolve failed: %w", err) return nil, fmt.Errorf("use default dns resolve failed: %w", err)
@ -58,7 +63,7 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err
conn = tls.Client(conn, c.Client.TLSConfig) conn = tls.Client(conn, c.Client.TLSConfig)
} }
msg, _, err = c.Client.ExchangeWithConn(m, &D.Conn{ msg, _, err := c.Client.ExchangeWithConn(m, &D.Conn{
Conn: conn, Conn: conn,
UDPSize: c.Client.UDPSize, UDPSize: c.Client.UDPSize,
TsigSecret: c.Client.TsigSecret, TsigSecret: c.Client.TsigSecret,

View File

@ -9,6 +9,7 @@ import (
"github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/adapter/inbound"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/transport/socks5"
) )
func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client { func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client {
@ -25,9 +26,14 @@ func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client {
return nil, errors.New("unsupported network " + network) return nil, errors.New("unsupported network " + network)
} }
dstAddr := socks5.ParseAddr(address)
if dstAddr == nil {
return nil, socks5.ErrAddressNotSupported
}
left, right := net.Pipe() left, right := net.Pipe()
in <- inbound.NewHTTP(address, source, right) in <- inbound.NewHTTP(dstAddr, source, right)
return left, nil return left, nil
}, },

View File

@ -63,8 +63,8 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
request.RequestURI = "" request.RequestURI = ""
RemoveHopByHopHeaders(request.Header) removeHopByHopHeaders(request.Header)
RemoveExtraHTTPHostPort(request) removeExtraHTTPHostPort(request)
if request.URL.Scheme == "" || request.URL.Host == "" { if request.URL.Scheme == "" || request.URL.Host == "" {
resp = responseWith(http.StatusBadRequest) resp = responseWith(http.StatusBadRequest)
@ -74,9 +74,9 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
resp = responseWith(http.StatusBadGateway) resp = responseWith(http.StatusBadGateway)
} }
} }
}
RemoveHopByHopHeaders(resp.Header) removeHopByHopHeaders(resp.Header)
}
if keepAlive { if keepAlive {
resp.Header.Set("Proxy-Connection", "keep-alive") resp.Header.Set("Proxy-Connection", "keep-alive")
@ -98,7 +98,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
func authenticate(request *http.Request, cache *cache.Cache) *http.Response { func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
authenticator := authStore.Authenticator() authenticator := authStore.Authenticator()
if authenticator != nil { if authenticator != nil {
credential := ParseBasicProxyAuthorization(request) credential := parseBasicProxyAuthorization(request)
if credential == "" { if credential == "" {
resp := responseWith(http.StatusProxyAuthRequired) resp := responseWith(http.StatusProxyAuthRequired)
resp.Header.Set("Proxy-Authenticate", "Basic") resp.Header.Set("Proxy-Authenticate", "Basic")
@ -107,7 +107,7 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
var authed interface{} var authed interface{}
if authed = cache.Get(credential); authed == nil { if authed = cache.Get(credential); authed == nil {
user, pass, err := DecodeBasicProxyAuthorization(credential) user, pass, err := decodeBasicProxyAuthorization(credential)
authed = err == nil && authenticator.Verify(user, pass) authed = err == nil && authenticator.Verify(user, pass)
cache.Put(credential, authed, time.Minute) cache.Put(credential, authed, time.Minute)
} }

View File

@ -8,8 +8,8 @@ import (
"strings" "strings"
) )
// RemoveHopByHopHeaders remove hop-by-hop header // removeHopByHopHeaders remove hop-by-hop header
func RemoveHopByHopHeaders(header http.Header) { func removeHopByHopHeaders(header http.Header) {
// Strip hop-by-hop header based on RFC: // Strip hop-by-hop header based on RFC:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
// https://www.mnot.net/blog/2011/07/11/what_proxies_must_do // https://www.mnot.net/blog/2011/07/11/what_proxies_must_do
@ -32,9 +32,9 @@ func RemoveHopByHopHeaders(header http.Header) {
} }
} }
// RemoveExtraHTTPHostPort remove extra host port (example.com:80 --> example.com) // removeExtraHTTPHostPort remove extra host port (example.com:80 --> example.com)
// It resolves the behavior of some HTTP servers that do not handle host:80 (e.g. baidu.com) // It resolves the behavior of some HTTP servers that do not handle host:80 (e.g. baidu.com)
func RemoveExtraHTTPHostPort(req *http.Request) { func removeExtraHTTPHostPort(req *http.Request) {
host := req.Host host := req.Host
if host == "" { if host == "" {
host = req.URL.Host host = req.URL.Host
@ -48,8 +48,8 @@ func RemoveExtraHTTPHostPort(req *http.Request) {
req.URL.Host = host req.URL.Host = host
} }
// ParseBasicProxyAuthorization parse header Proxy-Authorization and return base64-encoded credential // parseBasicProxyAuthorization parse header Proxy-Authorization and return base64-encoded credential
func ParseBasicProxyAuthorization(request *http.Request) string { func parseBasicProxyAuthorization(request *http.Request) string {
value := request.Header.Get("Proxy-Authorization") value := request.Header.Get("Proxy-Authorization")
if !strings.HasPrefix(value, "Basic ") { if !strings.HasPrefix(value, "Basic ") {
return "" return ""
@ -58,8 +58,8 @@ func ParseBasicProxyAuthorization(request *http.Request) string {
return value[6:] // value[len("Basic "):] return value[6:] // value[len("Basic "):]
} }
// DecodeBasicProxyAuthorization decode base64-encoded credential // decodeBasicProxyAuthorization decode base64-encoded credential
func DecodeBasicProxyAuthorization(credential string) (string, string, error) { func decodeBasicProxyAuthorization(credential string) (string, string, error) {
plain, err := base64.StdEncoding.DecodeString(credential) plain, err := base64.StdEncoding.DecodeString(credential)
if err != nil { if err != nil {
return "", "", err return "", "", err

View File

@ -91,6 +91,7 @@ func ServerHandshake(rw io.ReadWriter, authenticator auth.Authenticator) (addr s
code = RequestGranted code = RequestGranted
} else { } else {
code = RequestIdentdMismatched code = RequestIdentdMismatched
err = ErrRequestIdentdMismatched
} }
var reply [8]byte var reply [8]byte
@ -99,7 +100,10 @@ func ServerHandshake(rw io.ReadWriter, authenticator auth.Authenticator) (addr s
copy(reply[4:8], dstIP) copy(reply[4:8], dstIP)
copy(reply[2:4], dstPort) copy(reply[2:4], dstPort)
_, err = rw.Write(reply[:]) _, wErr := rw.Write(reply[:])
if err == nil {
err = wErr
}
return return
} }