Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dnscrypt-proxy/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ func (config *Config) loadSources(proxy *Proxy) error {
if stamp.Proto == stamps.StampProtoTypeDNSCryptRelay || stamp.Proto == stamps.StampProtoTypeODoHRelay {
dlog.Debugf("Adding [%s] to the set of available static relays", name)
registeredServer := RegisteredServer{name: name, stamp: stamp, description: "static relay"}
proxy.registeredRelays = append(proxy.registeredRelays, registeredServer)
proxy.staticRelays = append(proxy.staticRelays, registeredServer)
}
}
}
Expand All @@ -685,7 +685,7 @@ func (config *Config) loadSources(proxy *Proxy) error {
if err != nil {
return fmt.Errorf("Stamp error for the static [%s] definition: [%v]", serverName, err)
}
proxy.registeredServers = append(proxy.registeredServers, RegisteredServer{name: serverName, stamp: stamp})
proxy.staticServers = append(proxy.staticServers, RegisteredServer{name: serverName, stamp: stamp})
}
if err := proxy.updateRegisteredServers(); err != nil {
return err
Expand Down
174 changes: 108 additions & 66 deletions dnscrypt-proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Proxy struct {
serversInfo ServersInfo
questionSizeEstimator QuestionSizeEstimator
registeredServers []RegisteredServer
staticServers []RegisteredServer
dns64Resolvers []string
dns64Prefixes []string
serversBlockingFragments []string
Expand All @@ -35,6 +36,7 @@ type Proxy struct {
sources []*Source
tcpListeners []*net.TCPListener
registeredRelays []RegisteredServer
staticRelays []RegisteredServer
listenAddresses []string
localDoHListenAddresses []string
monitoringUI MonitoringUIConfig
Expand Down Expand Up @@ -336,99 +338,139 @@ func (proxy *Proxy) StartProxy() {
}

func (proxy *Proxy) updateRegisteredServers() error {
registeredServersNew := make([]RegisteredServer, 0)
registeredRelaysNew := make([]RegisteredServer, 0)
for _, source := range proxy.sources {
registeredServers, err := source.Parse()
servers, err := source.Parse()
if err != nil {
if len(registeredServers) == 0 {
if len(servers) == 0 {
dlog.Criticalf("Unable to use source [%s]: [%s]", source.name, err)
return err
}
dlog.Warnf(
"Error in source [%s]: [%s] -- Continuing with reduced server count [%d]",
source.name,
err,
len(registeredServers),
len(servers),
)
}
for _, registeredServer := range registeredServers {
if registeredServer.stamp.Proto != stamps.StampProtoTypeDNSCryptRelay &&
registeredServer.stamp.Proto != stamps.StampProtoTypeODoHRelay {
if len(proxy.ServerNames) > 0 {
if !includesName(proxy.ServerNames, registeredServer.name) {
continue
}
} else if registeredServer.stamp.Props&proxy.requiredProps != proxy.requiredProps {
registeredServersNew, registeredRelaysNew = proxy.buildRegisteredServers(servers, registeredServersNew, registeredRelaysNew)
}
if len(proxy.staticServers) > 0 {
registeredServersNew = append(registeredServersNew, proxy.staticServers...)
}
if len(proxy.staticRelays) > 0 {
registeredRelaysNew = append(registeredRelaysNew, proxy.staticRelays...)
}
if len(registeredServersNew) > 0 {
proxy.registeredServers = registeredServersNew
}
if len(registeredRelaysNew) > 0 {
proxy.registeredRelays = registeredRelaysNew
}
dlog.Debugf("Total count of registered servers %v", len(proxy.registeredServers))
dlog.Debugf("Total count of registered relays %v", len(proxy.registeredRelays))
proxy.serversInfo.registerServers(proxy.registeredServers)
proxy.serversInfo.registerRelays(proxy.registeredRelays)
return nil
}

func (proxy *Proxy) buildRegisteredServers(servers, registeredServersNew, registeredRelaysNew []RegisteredServer) (serversAppended, relaysAppended []RegisteredServer) {
for _, server := range servers {
if server.stamp.Proto != stamps.StampProtoTypeDNSCryptRelay &&
server.stamp.Proto != stamps.StampProtoTypeODoHRelay {
if len(proxy.ServerNames) > 0 {
if !includesName(proxy.ServerNames, server.name) {
continue
}
} else if server.stamp.Props&proxy.requiredProps != proxy.requiredProps {
continue
}
if includesName(proxy.DisabledServerNames, registeredServer.name) {
}
if includesName(proxy.DisabledServerNames, server.name) {
continue
}
if proxy.SourceIPv4 || proxy.SourceIPv6 {
isIPv4, isIPv6 := true, false
if server.stamp.Proto == stamps.StampProtoTypeDoH {
isIPv4, isIPv6 = true, true
}
if strings.HasPrefix(server.stamp.ServerAddrStr, "[") {
isIPv4, isIPv6 = false, true
}
if !(proxy.SourceIPv4 == isIPv4 || proxy.SourceIPv6 == isIPv6) {
continue
}
if proxy.SourceIPv4 || proxy.SourceIPv6 {
isIPv4, isIPv6 := true, false
if registeredServer.stamp.Proto == stamps.StampProtoTypeDoH {
isIPv4, isIPv6 = true, true
}
if strings.HasPrefix(registeredServer.stamp.ServerAddrStr, "[") {
isIPv4, isIPv6 = false, true
}
if !(proxy.SourceIPv4 == isIPv4 || proxy.SourceIPv6 == isIPv6) {
}
if server.stamp.Proto == stamps.StampProtoTypeDNSCryptRelay ||
server.stamp.Proto == stamps.StampProtoTypeODoHRelay {
isNew, stampChanged, dupNewInstance := checkServerForNewBuild(&server, proxy.registeredRelays, registeredRelaysNew)
if dupNewInstance != nil {
dupNewInstance.stamp = server.stamp
} else {
registeredRelaysNew = append(registeredRelaysNew, server)
if isNew {
dlog.Debugf("Adding [%s] to the set of available relays", server.name)
} else if !stampChanged {
continue
}
}
if registeredServer.stamp.Proto == stamps.StampProtoTypeDNSCryptRelay ||
registeredServer.stamp.Proto == stamps.StampProtoTypeODoHRelay {
var found bool
for i, currentRegisteredRelay := range proxy.registeredRelays {
if currentRegisteredRelay.name == registeredServer.name {
found = true
if currentRegisteredRelay.stamp.String() != registeredServer.stamp.String() {
dlog.Infof(
"Updating stamp for [%s] was: %s now: %s",
registeredServer.name,
currentRegisteredRelay.stamp.String(),
registeredServer.stamp.String(),
)
proxy.registeredRelays[i].stamp = registeredServer.stamp
dlog.Debugf("Total count of registered relays %v", len(proxy.registeredRelays))
}
}
}
if !found {
dlog.Debugf("Adding [%s] to the set of available relays", registeredServer.name)
proxy.registeredRelays = append(proxy.registeredRelays, registeredServer)
}
dlog.Debugf("Count of registered relays %v", len(registeredRelaysNew))
} else {
if !((proxy.SourceDNSCrypt && server.stamp.Proto == stamps.StampProtoTypeDNSCrypt) ||
(proxy.SourceDoH && server.stamp.Proto == stamps.StampProtoTypeDoH) ||
(proxy.SourceODoH && server.stamp.Proto == stamps.StampProtoTypeODoHTarget)) {
continue
}
isNew, stampChanged, dupNewInstance := checkServerForNewBuild(&server, proxy.registeredServers, registeredServersNew)
if dupNewInstance != nil {
dupNewInstance.stamp = server.stamp
} else {
if !((proxy.SourceDNSCrypt && registeredServer.stamp.Proto == stamps.StampProtoTypeDNSCrypt) ||
(proxy.SourceDoH && registeredServer.stamp.Proto == stamps.StampProtoTypeDoH) ||
(proxy.SourceODoH && registeredServer.stamp.Proto == stamps.StampProtoTypeODoHTarget)) {
registeredServersNew = append(registeredServersNew, server)
if isNew {
dlog.Debugf("Adding [%s] to the set of wanted resolvers", server.name)
} else if !stampChanged {
continue
}
var found bool
for i, currentRegisteredServer := range proxy.registeredServers {
if currentRegisteredServer.name == registeredServer.name {
found = true
if currentRegisteredServer.stamp.String() != registeredServer.stamp.String() {
dlog.Infof("Updating stamp for [%s] was: %s now: %s", registeredServer.name, currentRegisteredServer.stamp.String(), registeredServer.stamp.String())
proxy.registeredServers[i].stamp = registeredServer.stamp
}
}
}
if !found {
dlog.Debugf("Adding [%s] to the set of wanted resolvers", registeredServer.name)
proxy.registeredServers = append(proxy.registeredServers, registeredServer)
dlog.Debugf("Total count of registered servers %v", len(proxy.registeredServers))
}
}
dlog.Debugf("Count of registered servers %v", len(registeredServersNew))
}
}
for _, registeredServer := range proxy.registeredServers {
proxy.serversInfo.registerServer(registeredServer.name, registeredServer.stamp)
return registeredServersNew, registeredRelaysNew
}

func checkServerForNewBuild(server *RegisteredServer, serversCur, serversNew []RegisteredServer) (isNew, stampChanged bool, dupNewInstance *RegisteredServer) {
foundServer, stampChanged := serverStampChanged(serversCur, server)
if foundServer == nil || stampChanged {
// in case the same name exists in (different) sources
dupNewInstance, stampChanged2 := serverStampChanged(serversNew, server)
isNew = foundServer == nil && dupNewInstance == nil
if dupNewInstance != nil {
foundServer = dupNewInstance
}
stampChanged = stampChanged || stampChanged2
}
for _, registeredRelay := range proxy.registeredRelays {
proxy.serversInfo.registerRelay(registeredRelay.name, registeredRelay.stamp)
if stampChanged {
dlog.Infof(
"Updating stamp for [%s] was: %s now: %s",
server.name,
foundServer.stamp.String(),
server.stamp.String(),
)
}
return nil
return isNew, stampChanged, dupNewInstance
}

func serverStampChanged(servers []RegisteredServer, server *RegisteredServer) (found *RegisteredServer, changed bool) {
for _, s := range servers {
if s.name == server.name {
found = &s
if s.stamp.String() != server.stamp.String() {
changed = true
}
}
}
return found, changed
}

func (proxy *Proxy) udpListener(clientPc *net.UDPConn) {
Expand Down
58 changes: 50 additions & 8 deletions dnscrypt-proxy/serversInfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ func NewServersInfo() ServersInfo {
}
}

func (serversInfo *ServersInfo) registerServers(registeredServers []RegisteredServer) {
rs := make([]RegisteredServer, len(registeredServers))
copy(rs, registeredServers)
serversInfo.Lock()
serversInfo.registeredServers = rs
serversInfo.Unlock()
}

func (serversInfo *ServersInfo) registerServer(name string, stamp stamps.ServerStamp) {
newRegisteredServer := RegisteredServer{name: name, stamp: stamp}
serversInfo.Lock()
Expand All @@ -188,6 +196,14 @@ func (serversInfo *ServersInfo) registerServer(name string, stamp stamps.ServerS
serversInfo.registeredServers = append(serversInfo.registeredServers, newRegisteredServer)
}

func (serversInfo *ServersInfo) registerRelays(registeredRelays []RegisteredServer) {
rr := make([]RegisteredServer, len(registeredRelays))
copy(rr, registeredRelays)
serversInfo.Lock()
serversInfo.registeredRelays = rr
serversInfo.Unlock()
}

func (serversInfo *ServersInfo) registerRelay(name string, stamp stamps.ServerStamp) {
newRegisteredServer := RegisteredServer{name: name, stamp: stamp}
serversInfo.Lock()
Expand All @@ -201,7 +217,7 @@ func (serversInfo *ServersInfo) registerRelay(name string, stamp stamps.ServerSt
serversInfo.registeredRelays = append(serversInfo.registeredRelays, newRegisteredServer)
}

func (serversInfo *ServersInfo) refreshServer(proxy *Proxy, name string, stamp stamps.ServerStamp) error {
func (serversInfo *ServersInfo) initServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp) (*ServerInfo, bool, error) {
serversInfo.RLock()
isNew := true
for _, oldServer := range serversInfo.inner {
Expand All @@ -213,26 +229,33 @@ func (serversInfo *ServersInfo) refreshServer(proxy *Proxy, name string, stamp s
serversInfo.RUnlock()
newServer, err := fetchServerInfo(proxy, name, stamp, isNew)
if err != nil {
return err
return nil, isNew, err
}
if name != newServer.Name {
dlog.Fatalf("[%s] != [%s]", name, newServer.Name)
}
newServer.rtt = ewma.NewMovingAverage(RTTEwmaDecay)
newServer.rtt.Set(float64(newServer.initialRtt))
isNew = true
return &newServer, isNew, err
}

func (serversInfo *ServersInfo) refreshServer(proxy *Proxy, name string, stamp stamps.ServerStamp) error {
newServer, isNew, err := serversInfo.initServerInfo(proxy, name, stamp)
if err != nil {
return err
}
serversInfo.Lock()
for i, oldServer := range serversInfo.inner {
if oldServer.Name == name {
serversInfo.inner[i] = &newServer
serversInfo.inner[i] = newServer
isNew = false
break
}
}
serversInfo.Unlock()
if isNew {
serversInfo.Lock()
serversInfo.inner = append(serversInfo.inner, &newServer)
serversInfo.inner = append(serversInfo.inner, newServer)
serversInfo.Unlock()
proxy.serversInfo.registerServer(name, stamp)
}
Expand All @@ -250,29 +273,48 @@ func (serversInfo *ServersInfo) refresh(proxy *Proxy) (int, error) {
serversInfo.RUnlock()
countChannel := make(chan struct{}, proxy.certRefreshConcurrency)
errorChannel := make(chan error, serversCount)
serverInfoChannel := make(chan *ServerInfo, serversCount)
rebuildInner := len(serversInfo.inner) > 0
for i := range registeredServers {
countChannel <- struct{}{}
go func(registeredServer *RegisteredServer) {
err := serversInfo.refreshServer(proxy, registeredServer.name, registeredServer.stamp)
if err == nil {
proxy.xTransport.internalResolverReady = true
var serverInfo *ServerInfo
var err error
if rebuildInner {
serverInfo, _, err = serversInfo.initServerInfo(proxy, registeredServer.name, registeredServer.stamp)
serverInfoChannel <- serverInfo
} else {
err = serversInfo.refreshServer(proxy, registeredServer.name, registeredServer.stamp)
if err == nil {
proxy.xTransport.internalResolverReady = true
}
}
errorChannel <- err
<-countChannel
}(&registeredServers[i])
}
liveServers := 0
var err error
var innerRefresh []*ServerInfo
for i := 0; i < serversCount; i++ {
err = <-errorChannel
if err == nil {
liveServers++
}
if rebuildInner {
serverInfo := <-serverInfoChannel
if serverInfo != nil {
innerRefresh = append(innerRefresh, serverInfo)
}
}
}
if liveServers > 0 {
err = nil
}
serversInfo.Lock()
if len(innerRefresh) > 0 {
serversInfo.inner = innerRefresh
}
sort.SliceStable(serversInfo.inner, func(i, j int) bool {
return serversInfo.inner[i].initialRtt < serversInfo.inner[j].initialRtt
})
Expand Down