mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-05-13 21:48:02 +08:00
feat: doh client support plain http and skip-cert-verify
This commit is contained in:
parent
13b7ab8da3
commit
4b9fdacbad
@ -1090,13 +1090,16 @@ func parseNameServer(servers []string, respectRules bool, preferH3 bool) ([]dns.
|
|||||||
case "tls":
|
case "tls":
|
||||||
addr, err = hostWithDefaultPort(u.Host, "853")
|
addr, err = hostWithDefaultPort(u.Host, "853")
|
||||||
dnsNetType = "tcp-tls" // DNS over TLS
|
dnsNetType = "tcp-tls" // DNS over TLS
|
||||||
case "https":
|
case "http", "https":
|
||||||
addr, err = hostWithDefaultPort(u.Host, "443")
|
addr, err = hostWithDefaultPort(u.Host, "443")
|
||||||
|
dnsNetType = "https" // DNS over HTTPS
|
||||||
|
if u.Scheme == "http" {
|
||||||
|
addr, err = hostWithDefaultPort(u.Host, "80")
|
||||||
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
proxyName = ""
|
proxyName = ""
|
||||||
clearURL := url.URL{Scheme: "https", Host: addr, Path: u.Path, User: u.User}
|
clearURL := url.URL{Scheme: u.Scheme, Host: addr, Path: u.Path, User: u.User}
|
||||||
addr = clearURL.String()
|
addr = clearURL.String()
|
||||||
dnsNetType = "https" // DNS over HTTPS
|
|
||||||
if len(u.Fragment) != 0 {
|
if len(u.Fragment) != 0 {
|
||||||
for _, s := range strings.Split(u.Fragment, "&") {
|
for _, s := range strings.Split(u.Fragment, "&") {
|
||||||
arr := strings.Split(s, "=")
|
arr := strings.Split(s, "=")
|
||||||
|
46
dns/doh.go
46
dns/doh.go
@ -61,10 +61,12 @@ type dnsOverHTTPS struct {
|
|||||||
// for this upstream.
|
// for this upstream.
|
||||||
quicConfig *quic.Config
|
quicConfig *quic.Config
|
||||||
quicConfigGuard sync.Mutex
|
quicConfigGuard sync.Mutex
|
||||||
|
|
||||||
url *url.URL
|
url *url.URL
|
||||||
httpVersions []C.HTTPVersion
|
httpVersions []C.HTTPVersion
|
||||||
dialer *dnsDialer
|
dialer *dnsDialer
|
||||||
addr string
|
addr string
|
||||||
|
skipCertVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
@ -93,6 +95,10 @@ func newDoHClient(urlString string, r *Resolver, preferH3 bool, params map[strin
|
|||||||
httpVersions: httpVersions,
|
httpVersions: httpVersions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if params["skip-cert-verify"] == "true" {
|
||||||
|
doh.skipCertVerify = true
|
||||||
|
}
|
||||||
|
|
||||||
runtime.SetFinalizer(doh, (*dnsOverHTTPS).Close)
|
runtime.SetFinalizer(doh, (*dnsOverHTTPS).Close)
|
||||||
|
|
||||||
return doh
|
return doh
|
||||||
@ -102,6 +108,7 @@ func newDoHClient(urlString string, r *Resolver, preferH3 bool, params map[strin
|
|||||||
func (doh *dnsOverHTTPS) Address() string {
|
func (doh *dnsOverHTTPS) Address() string {
|
||||||
return doh.addr
|
return doh.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doh *dnsOverHTTPS) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
func (doh *dnsOverHTTPS) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
||||||
// Quote from https://www.rfc-editor.org/rfc/rfc8484.html:
|
// Quote from https://www.rfc-editor.org/rfc/rfc8484.html:
|
||||||
// In order to maximize HTTP cache friendliness, DoH clients using media
|
// In order to maximize HTTP cache friendliness, DoH clients using media
|
||||||
@ -178,19 +185,9 @@ func (doh *dnsOverHTTPS) closeClient(client *http.Client) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// exchangeHTTPS logs the request and its result and calls exchangeHTTPSClient.
|
// exchangeHTTPS sends the DNS query to a DoH resolver using the specified
|
||||||
func (doh *dnsOverHTTPS) exchangeHTTPS(ctx context.Context, client *http.Client, req *D.Msg) (resp *D.Msg, err error) {
|
|
||||||
resp, err = doh.exchangeHTTPSClient(ctx, client, req)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// exchangeHTTPSClient sends the DNS query to a DoH resolver using the specified
|
|
||||||
// http.Client instance.
|
// http.Client instance.
|
||||||
func (doh *dnsOverHTTPS) exchangeHTTPSClient(
|
func (doh *dnsOverHTTPS) exchangeHTTPS(ctx context.Context, client *http.Client, req *D.Msg) (resp *D.Msg, err error) {
|
||||||
ctx context.Context,
|
|
||||||
client *http.Client,
|
|
||||||
req *D.Msg,
|
|
||||||
) (resp *D.Msg, err error) {
|
|
||||||
buf, err := req.Pack()
|
buf, err := req.Pack()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("packing message: %w", err)
|
return nil, fmt.Errorf("packing message: %w", err)
|
||||||
@ -373,9 +370,21 @@ func (doh *dnsOverHTTPS) createClient(ctx context.Context) (*http.Client, error)
|
|||||||
// HTTP3 is enabled in the upstream options). If this attempt is successful,
|
// HTTP3 is enabled in the upstream options). If this attempt is successful,
|
||||||
// it returns an HTTP3 transport, otherwise it returns the H1/H2 transport.
|
// it returns an HTTP3 transport, otherwise it returns the H1/H2 transport.
|
||||||
func (doh *dnsOverHTTPS) createTransport(ctx context.Context) (t http.RoundTripper, err error) {
|
func (doh *dnsOverHTTPS) createTransport(ctx context.Context) (t http.RoundTripper, err error) {
|
||||||
|
transport := &http.Transport{
|
||||||
|
DisableCompression: true,
|
||||||
|
DialContext: doh.dialer.DialContext,
|
||||||
|
IdleConnTimeout: transportDefaultIdleConnTimeout,
|
||||||
|
MaxConnsPerHost: dohMaxConnsPerHost,
|
||||||
|
MaxIdleConns: dohMaxIdleConns,
|
||||||
|
}
|
||||||
|
|
||||||
|
if doh.url.Scheme == "http" {
|
||||||
|
return transport, nil
|
||||||
|
}
|
||||||
|
|
||||||
tlsConfig := ca.GetGlobalTLSConfig(
|
tlsConfig := ca.GetGlobalTLSConfig(
|
||||||
&tls.Config{
|
&tls.Config{
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: doh.skipCertVerify,
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
SessionTicketsDisabled: false,
|
SessionTicketsDisabled: false,
|
||||||
})
|
})
|
||||||
@ -384,6 +393,7 @@ func (doh *dnsOverHTTPS) createTransport(ctx context.Context) (t http.RoundTripp
|
|||||||
nextProtos = append(nextProtos, string(v))
|
nextProtos = append(nextProtos, string(v))
|
||||||
}
|
}
|
||||||
tlsConfig.NextProtos = nextProtos
|
tlsConfig.NextProtos = nextProtos
|
||||||
|
transport.TLSClientConfig = tlsConfig
|
||||||
|
|
||||||
if slices.Contains(doh.httpVersions, C.HTTPVersion3) {
|
if slices.Contains(doh.httpVersions, C.HTTPVersion3) {
|
||||||
// First, we attempt to create an HTTP3 transport. If the probe QUIC
|
// First, we attempt to create an HTTP3 transport. If the probe QUIC
|
||||||
@ -402,18 +412,10 @@ func (doh *dnsOverHTTPS) createTransport(ctx context.Context) (t http.RoundTripp
|
|||||||
return nil, errors.New("HTTP1/1 and HTTP2 are not supported by this upstream")
|
return nil, errors.New("HTTP1/1 and HTTP2 are not supported by this upstream")
|
||||||
}
|
}
|
||||||
|
|
||||||
transport := &http.Transport{
|
|
||||||
TLSClientConfig: tlsConfig,
|
|
||||||
DisableCompression: true,
|
|
||||||
DialContext: doh.dialer.DialContext,
|
|
||||||
IdleConnTimeout: transportDefaultIdleConnTimeout,
|
|
||||||
MaxConnsPerHost: dohMaxConnsPerHost,
|
|
||||||
MaxIdleConns: dohMaxIdleConns,
|
|
||||||
// Since we have a custom DialContext, we need to use this field to
|
// Since we have a custom DialContext, we need to use this field to
|
||||||
// make golang http.Client attempt to use HTTP/2. Otherwise, it would
|
// make golang http.Client attempt to use HTTP/2. Otherwise, it would
|
||||||
// only be used when negotiated on the TLS level.
|
// only be used when negotiated on the TLS level.
|
||||||
ForceAttemptHTTP2: true,
|
transport.ForceAttemptHTTP2 = true
|
||||||
}
|
|
||||||
|
|
||||||
// Explicitly configure transport to use HTTP/2.
|
// Explicitly configure transport to use HTTP/2.
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user