Ctrl K
ComunidadGuías…

src/models/constants.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package models

import (
	"context"
	"fmt"
	"net"
	"os"
	"path"
	"time"

	log "github.com/schollz/croc/v11/src/logger"
	"github.com/schollz/croc/v11/src/utils"
)

// TCP_BUFFER_SIZE is the maximum packet size
const TCP_BUFFER_SIZE = 1024 * 64

// Default relay addresses retain their hostnames until dialing so proxies can
// resolve them remotely. DEFAULT_RELAY can be overridden using --relay.
var (
	DEFAULT_RELAY      = "croc.schollz.com:9009"
	DEFAULT_RELAY6     = "croc6.schollz.com:9009"
	DEFAULT_PORT       = "9009"
	DEFAULT_PASSPHRASE = "pass123"
	INTERNAL_DNS       = false
)

// publicDNS are servers to be queried if a local lookup fails
var publicDNS = []string{
	"1.0.0.1",                // Cloudflare
	"1.1.1.1",                // Cloudflare
	"[2606:4700:4700::1111]", // Cloudflare
	"[2606:4700:4700::1001]", // Cloudflare
	"8.8.4.4",                // Google
	"8.8.8.8",                // Google
	"[2001:4860:4860::8844]", // Google
	"[2001:4860:4860::8888]", // Google
	"9.9.9.9",                // Quad9
	"149.112.112.112",        // Quad9
	"[2620:fe::fe]",          // Quad9
	"[2620:fe::fe:9]",        // Quad9
	"8.26.56.26",             // Comodo
	"8.20.247.20",            // Comodo
	"208.67.220.220",         // Cisco OpenDNS
	"208.67.222.222",         // Cisco OpenDNS
	"[2620:119:35::35]",      // Cisco OpenDNS
	"[2620:119:53::53]",      // Cisco OpenDNS
}

func getConfigFile(requireValidPath bool) (fname string, err error) {
	configFile, err := utils.GetConfigDir(requireValidPath)
	if err != nil {
		return
	}
	fname = path.Join(configFile, "internal-dns")
	return
}

func init() {
	log.SetLevel("info")
	log.SetOutput(os.Stderr)
	doRemember := false
	for _, flag := range os.Args {
		if flag == "--internal-dns" {
			INTERNAL_DNS = true
			break
		}
		if flag == "--remember" {
			doRemember = true
		}
	}
	if doRemember {
		// save in config file
		fname, err := getConfigFile(true)
		if err == nil {
			f, _ := os.Create(fname)
			f.Close()
		}
	}
	if !INTERNAL_DNS {
		fname, err := getConfigFile(false)
		if err == nil {
			INTERNAL_DNS = utils.Exists(fname)
		}
	}
	log.Trace("Using internal DNS: ", INTERNAL_DNS)
}

// ResolveRelayAddress applies the optional built-in DNS resolver to a direct
// connection. Proxy connections must keep the hostname for proxy-side DNS.
func ResolveRelayAddress(ctx context.Context, address string) (string, error) {
	if !INTERNAL_DNS {
		return address, nil
	}
	host, port, err := net.SplitHostPort(address)
	if err != nil {
		return "", err
	}
	if net.ParseIP(host) != nil {
		return address, nil
	}
	ip, err := lookup(ctx, host)
	if err != nil {
		return "", err
	}
	return net.JoinHostPort(ip, port), nil
}

// Resolve a hostname to an IP address using DNS.
func lookup(ctx context.Context, address string) (ipaddress string, err error) {
	if err := ctx.Err(); err != nil {
		return "", err
	}
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	if !INTERNAL_DNS {
		log.Tracef("Using local DNS to resolve %s", address)
		return localLookupIPContext(ctx, address)
	}
	type Result struct {
		s   string
		err error
	}
	result := make(chan Result, len(publicDNS))
	for _, dns := range publicDNS {
		go func(dns string) {
			var r Result
			r.s, r.err = remoteLookupIPContext(ctx, address, dns)
			log.Tracef("Resolved %s to %s using %s", address, r.s, dns)
			result <- r
		}(dns)
	}
	for range publicDNS {
		select {
		case <-ctx.Done():
			return "", ctx.Err()
		case resolved := <-result:
			ipaddress = resolved.s
		}
		log.Tracef("Resolved %s to %s", address, ipaddress)
		if ipaddress != "" {
			return
		}
	}
	err = fmt.Errorf("failed to resolve %s: all DNS servers exhausted", address)
	return
}

// localLookupIP returns a host's IP address using the local DNS configuration.
func localLookupIP(address string) (ipaddress string, err error) {
	return localLookupIPContext(context.Background(), address)
}

func localLookupIPContext(ctx context.Context, address string) (ipaddress string, err error) {
	ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
	defer cancel()

	r := &net.Resolver{}

	// Use the context with timeout in the LookupHost function
	ip, err := r.LookupHost(ctx, address)
	if err != nil {
		return
	}
	ipaddress = ip[0]
	return
}

// remoteLookupIP returns a host's IP address based on a remote DNS server.
func remoteLookupIP(address, dns string) (ipaddress string, err error) {
	return remoteLookupIPContext(context.Background(), address, dns)
}

func remoteLookupIPContext(ctx context.Context, address, dns string) (ipaddress string, err error) {
	ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
	defer cancel()

	r := &net.Resolver{
		PreferGo: true,
		Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
			d := new(net.Dialer)
			return d.DialContext(ctx, network, dns+":53")
		},
	}
	ip, err := r.LookupHost(ctx, address)
	if err != nil {
		return
	}
	ipaddress = ip[0]
	return
}