mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-29 01:18:48 +02:00
Merge pull request #28 from Control-D-Inc/release-branch-v1.1.2
Release branch v1.1.2
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy
|
||||||
|
builds:
|
||||||
|
- id: ctrld
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
flags:
|
||||||
|
- -trimpath
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
tags:
|
||||||
|
- qf
|
||||||
|
main: ./cmd/ctrld
|
||||||
|
hooks:
|
||||||
|
post: /bin/sh ./scripts/upx.sh {{ .Path }}
|
||||||
|
archives:
|
||||||
|
- format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: zip
|
||||||
|
strip_parent_binary_folder: true
|
||||||
|
wrap_in_directory: true
|
||||||
|
files:
|
||||||
|
- README.md
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}-next"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^docs:'
|
||||||
+2
-1
@@ -70,7 +70,7 @@ func initCLI() {
|
|||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
Use: "ctrld",
|
Use: "ctrld",
|
||||||
Short: strings.TrimLeft(rootShortDesc, "\n"),
|
Short: strings.TrimLeft(rootShortDesc, "\n"),
|
||||||
Version: "1.1.1",
|
Version: "1.1.2",
|
||||||
}
|
}
|
||||||
rootCmd.PersistentFlags().CountVarP(
|
rootCmd.PersistentFlags().CountVarP(
|
||||||
&verbose,
|
&verbose,
|
||||||
@@ -112,6 +112,7 @@ func initCLI() {
|
|||||||
if err := v.Unmarshal(&cfg); err != nil {
|
if err := v.Unmarshal(&cfg); err != nil {
|
||||||
log.Fatalf("failed to unmarshal config: %v", err)
|
log.Fatalf("failed to unmarshal config: %v", err)
|
||||||
}
|
}
|
||||||
|
fmt.Println("starting ctrld...")
|
||||||
// Wait for network up.
|
// Wait for network up.
|
||||||
if !ctrldnet.Up() {
|
if !ctrldnet.Up() {
|
||||||
log.Fatal("network is not up yet")
|
log.Fatal("network is not up yet")
|
||||||
|
|||||||
+31
-18
@@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/Control-D-Inc/ctrld"
|
"github.com/Control-D-Inc/ctrld"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/dnscache"
|
"github.com/Control-D-Inc/ctrld/internal/dnscache"
|
||||||
@@ -20,7 +21,7 @@ import (
|
|||||||
|
|
||||||
const staleTTL = 60 * time.Second
|
const staleTTL = 60 * time.Second
|
||||||
|
|
||||||
func (p *prog) serveUDP(listenerNum string) error {
|
func (p *prog) serveDNS(listenerNum string) error {
|
||||||
listenerConfig := p.cfg.Listener[listenerNum]
|
listenerConfig := p.cfg.Listener[listenerNum]
|
||||||
// make sure ip is allocated
|
// make sure ip is allocated
|
||||||
if allocErr := p.allocateIP(listenerConfig.IP); allocErr != nil {
|
if allocErr := p.allocateIP(listenerConfig.IP); allocErr != nil {
|
||||||
@@ -55,27 +56,38 @@ func (p *prog) serveUDP(listenerNum string) error {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// On Windows, there's no easy way for disabling/removing IPv6 DNS resolver, so we check whether we can
|
g := new(errgroup.Group)
|
||||||
// listen on ::1, then spawn a listener for receiving DNS requests.
|
for _, proto := range []string{"udp", "tcp"} {
|
||||||
if runtime.GOOS == "windows" && ctrldnet.SupportsIPv6ListenLocal() {
|
proto := proto
|
||||||
go func() {
|
// On Windows, there's no easy way for disabling/removing IPv6 DNS resolver, so we check whether we can
|
||||||
|
// listen on ::1, then spawn a listener for receiving DNS requests.
|
||||||
|
if runtime.GOOS == "windows" && ctrldnet.SupportsIPv6ListenLocal() {
|
||||||
|
g.Go(func() error {
|
||||||
|
s := &dns.Server{
|
||||||
|
Addr: net.JoinHostPort("::1", strconv.Itoa(listenerConfig.Port)),
|
||||||
|
Net: proto,
|
||||||
|
Handler: handler,
|
||||||
|
}
|
||||||
|
if err := s.ListenAndServe(); err != nil {
|
||||||
|
mainLog.Error().Err(err).Msg("could not serving on ::1")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
g.Go(func() error {
|
||||||
s := &dns.Server{
|
s := &dns.Server{
|
||||||
Addr: net.JoinHostPort("::1", strconv.Itoa(listenerConfig.Port)),
|
Addr: net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port)),
|
||||||
Net: "udp",
|
Net: proto,
|
||||||
Handler: handler,
|
Handler: handler,
|
||||||
}
|
}
|
||||||
if err := s.ListenAndServe(); err != nil {
|
if err := s.ListenAndServe(); err != nil {
|
||||||
mainLog.Error().Err(err).Msg("could not serving on ::1")
|
mainLog.Error().Err(err).Msgf("could not listen and serve on: %s", s.Addr)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}()
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
return g.Wait()
|
||||||
s := &dns.Server{
|
|
||||||
Addr: net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port)),
|
|
||||||
Net: "udp",
|
|
||||||
Handler: handler,
|
|
||||||
}
|
|
||||||
return s.ListenAndServe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prog) upstreamFor(ctx context.Context, defaultUpstreamNum string, lc *ctrld.ListenerConfig, addr net.Addr, domain string) ([]string, bool) {
|
func (p *prog) upstreamFor(ctx context.Context, defaultUpstreamNum string, lc *ctrld.ListenerConfig, addr net.Addr, domain string) ([]string, bool) {
|
||||||
@@ -330,6 +342,7 @@ func ttlFromMsg(msg *dns.Msg) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var osUpstreamConfig = &ctrld.UpstreamConfig{
|
var osUpstreamConfig = &ctrld.UpstreamConfig{
|
||||||
Name: "OS resolver",
|
Name: "OS resolver",
|
||||||
Type: ctrld.ResolverTypeOS,
|
Type: ctrld.ResolverTypeOS,
|
||||||
|
Timeout: 2000,
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -85,7 +85,7 @@ func (p *prog) run() {
|
|||||||
}
|
}
|
||||||
addr := net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port))
|
addr := net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port))
|
||||||
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, addr)
|
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, addr)
|
||||||
err := p.serveUDP(listenerNum)
|
err := p.serveDNS(listenerNum)
|
||||||
if err != nil && !defaultConfigWritten && cdUID == "" {
|
if err != nil && !defaultConfigWritten && cdUID == "" {
|
||||||
mainLog.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
|
mainLog.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
|
||||||
return
|
return
|
||||||
@@ -109,7 +109,7 @@ func (p *prog) run() {
|
|||||||
p.cfg.Service.AllocateIP = true
|
p.cfg.Service.AllocateIP = true
|
||||||
p.preRun()
|
p.preRun()
|
||||||
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, net.JoinHostPort(ip, strconv.Itoa(port)))
|
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, net.JoinHostPort(ip, strconv.Itoa(port)))
|
||||||
if err := p.serveUDP(listenerNum); err != nil {
|
if err := p.serveDNS(listenerNum); err != nil {
|
||||||
mainLog.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
|
mainLog.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,11 +165,15 @@ func (uc *UpstreamConfig) SetupBootstrapIP() {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver := &osResolver{nameservers: nameservers()}
|
resolver := &osResolver{nameservers: availableNameservers()}
|
||||||
resolver.nameservers = append([]string{net.JoinHostPort(bootstrapDNS, "53")}, resolver.nameservers...)
|
resolver.nameservers = append([]string{net.JoinHostPort(bootstrapDNS, "53")}, resolver.nameservers...)
|
||||||
ProxyLog.Debug().Msgf("Resolving %q using bootstrap DNS %q", uc.Domain, resolver.nameservers)
|
ProxyLog.Debug().Msgf("Resolving %q using bootstrap DNS %q", uc.Domain, resolver.nameservers)
|
||||||
|
timeoutMs := 2000
|
||||||
|
if uc.Timeout > 0 && uc.Timeout < timeoutMs {
|
||||||
|
timeoutMs = uc.Timeout
|
||||||
|
}
|
||||||
do := func(dnsType uint16) {
|
do := func(dnsType uint16) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(uc.Timeout)*time.Millisecond)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutMs)*time.Millisecond)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion(uc.Domain+".", dnsType)
|
m.SetQuestion(uc.Domain+".", dnsType)
|
||||||
@@ -203,7 +207,7 @@ func (uc *UpstreamConfig) SetupBootstrapIP() {
|
|||||||
uc.nextBootstrapIP.Add(1)
|
uc.nextBootstrapIP.Add(1)
|
||||||
|
|
||||||
// If this is an ipv6, and ipv6 is not available, don't use it as bootstrap ip.
|
// If this is an ipv6, and ipv6 is not available, don't use it as bootstrap ip.
|
||||||
if !ctrldnet.IPv6Available(ctx) && ctrldnet.IsIPv6(ip) {
|
if !ctrldnet.SupportsIPv6() && ctrldnet.IsIPv6(ip) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
uc.BootstrapIP = ip
|
uc.BootstrapIP = ip
|
||||||
@@ -349,3 +353,18 @@ func defaultPortFor(typ string) string {
|
|||||||
}
|
}
|
||||||
return "53"
|
return "53"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func availableNameservers() []string {
|
||||||
|
nss := nameservers()
|
||||||
|
n := 0
|
||||||
|
for _, ns := range nss {
|
||||||
|
ip, _, _ := net.SplitHostPort(ns)
|
||||||
|
// skipping invalid entry or ipv6 nameserver if ipv6 not available.
|
||||||
|
if ip == "" || (ctrldnet.IsIPv6(ip) && !ctrldnet.SupportsIPv6()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
nss[n] = ns
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
return nss[:n]
|
||||||
|
}
|
||||||
|
|||||||
+10
-3
@@ -28,6 +28,13 @@ var Dialer = &net.Dialer{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const probeStackTimeout = 2 * time.Second
|
||||||
|
|
||||||
|
var probeStackDialer = &net.Dialer{
|
||||||
|
Resolver: Dialer.Resolver,
|
||||||
|
Timeout: probeStackTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stackOnce atomic.Pointer[sync.Once]
|
stackOnce atomic.Pointer[sync.Once]
|
||||||
ipv4Enabled bool
|
ipv4Enabled bool
|
||||||
@@ -41,12 +48,12 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func supportIPv4() bool {
|
func supportIPv4() bool {
|
||||||
_, err := Dialer.Dial("tcp4", net.JoinHostPort(controldIPv4Test, "80"))
|
_, err := probeStackDialer.Dial("tcp4", net.JoinHostPort(controldIPv4Test, "80"))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func supportIPv6(ctx context.Context) bool {
|
func supportIPv6(ctx context.Context) bool {
|
||||||
_, err := Dialer.DialContext(ctx, "tcp6", net.JoinHostPort(controldIPv6Test, "80"))
|
_, err := probeStackDialer.DialContext(ctx, "tcp6", net.JoinHostPort(controldIPv6Test, "80"))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +68,7 @@ func supportListenIPv6Local() bool {
|
|||||||
func probeStack() {
|
func probeStack() {
|
||||||
b := backoff.NewBackoff("probeStack", func(format string, args ...any) {}, time.Minute)
|
b := backoff.NewBackoff("probeStack", func(format string, args ...any) {}, time.Minute)
|
||||||
for {
|
for {
|
||||||
if _, err := Dialer.Dial("udp", bootstrapDNS); err == nil {
|
if _, err := probeStackDialer.Dial("udp", bootstrapDNS); err == nil {
|
||||||
hasNetworkUp = true
|
hasNetworkUp = true
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProbeStackTimeout(t *testing.T) {
|
||||||
|
done := make(chan struct{})
|
||||||
|
started := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
close(started)
|
||||||
|
supportIPv6(context.Background())
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-started
|
||||||
|
select {
|
||||||
|
case <-time.After(probeStackTimeout + time.Second):
|
||||||
|
t.Error("probeStack timeout is not enforce")
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,10 @@ case "$binary" in
|
|||||||
echo >&2 "upx does not work with windows arm/arm64 binary yet"
|
echo >&2 "upx does not work with windows arm/arm64 binary yet"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
*_darwin_*)
|
||||||
|
echo >&2 "upx claims to work with darwin binary, but testing show that it is broken"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
upx -- "$binary"
|
upx -- "$binary"
|
||||||
|
|||||||
Reference in New Issue
Block a user