mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-02-23 20:52:15 +08:00
Merge from remote branch
This commit is contained in:
commit
fbda82218e
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
},
|
},
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user