feat: initial goget release — modern IPv6-first download utility

This commit is contained in:
2026-06-26 21:21:58 +02:00
commit 53db81e1f7
147 changed files with 45931 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
//go:build linux || freebsd
// +build linux freebsd
package transport
import (
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"fmt"
"os"
"strings"
)
// TLSConfig configures TLS
type TLSConfig struct {
// Minimum TLS version
MinVersion uint16
// Maximum TLS version
MaxVersion uint16
// Path to CA certificates
CACertFile string
// Skip certificate verification
InsecureSkipVerify bool
// Client certificate for mTLS
CertFile string
// Client private key for mTLS
KeyFile string
// Certificate pinning (SHA-256 hash of certificate)
PinnedCertHash string
// TLSServerNameOverride forces the SNI server name and the hostname used
// for certificate verification. Leave empty (the default) so that Go's
// stdlib derives the server name from the dial target, which is the safe
// behavior. Setting this to a value that does not match the host you are
// connecting to enables a man-in-the-middle attacker with a valid cert
// for the overridden name to impersonate the target. Only set this when
// you genuinely need to override SNI (e.g. connecting to an IP address
// whose certificate carries a different hostname).
TLSServerNameOverride string
// Path to SSLKEYLOGFILE for Wireshark debugging
KeyLogFile string
}
// DefaultTLSConfig returns a safe default configuration
func DefaultTLSConfig() *TLSConfig {
return &TLSConfig{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
InsecureSkipVerify: false,
}
}
// ToTLSConfig converts to tls.Config
func (c *TLSConfig) ToTLSConfig() (*tls.Config, error) {
tlsCfg := &tls.Config{
MinVersion: c.MinVersion,
MaxVersion: c.MaxVersion,
InsecureSkipVerify: c.InsecureSkipVerify,
}
// Only apply the override if explicitly set. When empty, Go's net/http
// transport derives ServerName from the dial address, which matches the
// certificate the server is expected to present.
if c.TLSServerNameOverride != "" {
tlsCfg.ServerName = c.TLSServerNameOverride
}
// Load custom CA certificates
if c.CACertFile != "" {
caCert, err := os.ReadFile(c.CACertFile)
if err != nil {
return nil, fmt.Errorf("failed to read ca cert: %w", err)
}
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
return nil, fmt.Errorf("failed to parse ca cert")
}
tlsCfg.RootCAs = caCertPool
}
// Certificate pinning: verify SHA-256 hash of server certificate
if c.PinnedCertHash != "" {
expectedHash := strings.ToLower(strings.TrimSpace(c.PinnedCertHash))
tlsCfg.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
for _, rawCert := range rawCerts {
cert, err := x509.ParseCertificate(rawCert)
if err != nil {
continue
}
hash := sha256.Sum256(cert.Raw)
actual := hex.EncodeToString(hash[:])
if actual == expectedHash {
return nil
}
}
return fmt.Errorf("certificate pinning failed: no certificate matches sha-256 %s", expectedHash)
}
}
// Load client certificate for mTLS
if c.CertFile != "" && c.KeyFile != "" {
cert, err := tls.LoadX509KeyPair(c.CertFile, c.KeyFile)
if err != nil {
return nil, fmt.Errorf("failed to load client certificate: %w", err)
}
tlsCfg.Certificates = []tls.Certificate{cert}
}
// SSLKEYLOGFILE for Wireshark/TLS debugging
if c.KeyLogFile != "" {
f, err := os.OpenFile(c.KeyLogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
if err != nil {
return nil, fmt.Errorf("failed to open keylog file: %w", err)
}
tlsCfg.KeyLogWriter = f
}
return tlsCfg, nil
}
// GetTLSVersionName returns a human-readable TLS version name
func GetTLSVersionName(version uint16) string {
switch version {
case tls.VersionTLS10:
return "TLS 1.0"
case tls.VersionTLS11:
return "TLS 1.1"
case tls.VersionTLS12:
return "TLS 1.2"
case tls.VersionTLS13:
return "TLS 1.3"
default:
return fmt.Sprintf("TLS 0x%04X", version)
}
}