Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package dnsproxy for openSUSE:Factory checked in at 2023-10-23 23:41:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dnsproxy (Old) and /work/SRC/openSUSE:Factory/.dnsproxy.new.1945 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dnsproxy" Mon Oct 23 23:41:33 2023 rev:11 rq:1119708 version:0.56.3 Changes: -------- --- /work/SRC/openSUSE:Factory/dnsproxy/dnsproxy.changes 2023-10-19 22:50:06.404497619 +0200 +++ /work/SRC/openSUSE:Factory/.dnsproxy.new.1945/dnsproxy.changes 2023-10-23 23:41:38.088988141 +0200 @@ -1,0 +2,6 @@ +Mon Oct 23 16:31:11 UTC 2023 - eyadlore...@gmail.com + +- Update to version 0.56.3: + * Pull request 287: 4977-proxy-multiple-reserved-upstreams + +------------------------------------------------------------------- Old: ---- dnsproxy-0.56.2.obscpio New: ---- dnsproxy-0.56.3.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dnsproxy.spec ++++++ --- /var/tmp/diff_new_pack.01EmJH/_old 2023-10-23 23:41:39.265030833 +0200 +++ /var/tmp/diff_new_pack.01EmJH/_new 2023-10-23 23:41:39.265030833 +0200 @@ -17,7 +17,7 @@ Name: dnsproxy -Version: 0.56.2 +Version: 0.56.3 Release: 0 Summary: A DNS proxy server License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.01EmJH/_old 2023-10-23 23:41:39.293031849 +0200 +++ /var/tmp/diff_new_pack.01EmJH/_new 2023-10-23 23:41:39.297031995 +0200 @@ -2,7 +2,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://github.com/AdguardTeam/dnsproxy.git</param> - <param name="revision">v0.56.2</param> + <param name="revision">v0.56.3</param> <param name="match-tag">*</param> <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param> <param name="versionformat">@PARENT_TAG@</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.01EmJH/_old 2023-10-23 23:41:39.313032576 +0200 +++ /var/tmp/diff_new_pack.01EmJH/_new 2023-10-23 23:41:39.317032720 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/AdguardTeam/dnsproxy.git</param> - <param name="changesrevision">46b2b1cb22104b4380f32986e783caac7a795223</param></service></servicedata> + <param name="changesrevision">39f15ce27a0ad226a083fe0f3102366d85e561c4</param></service></servicedata> (No newline at EOF) ++++++ dnsproxy-0.56.2.obscpio -> dnsproxy-0.56.3.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dnsproxy-0.56.2/README.md new/dnsproxy-0.56.3/README.md --- old/dnsproxy-0.56.2/README.md 2023-10-17 15:09:58.000000000 +0200 +++ new/dnsproxy-0.56.3/README.md 2023-10-19 14:09:51.000000000 +0200 @@ -292,6 +292,8 @@ **Syntax:** `[/[domain1][/../domainN]/]upstreamString` +Where `upstreamString` is one or many upstreams separated by space (e.g. `1.1.1.1` or `1.1.1.1 2.2.2.2`). + If one or more domains are specified, that upstream (`upstreamString`) is used only for those domains. Usually, it is used for private nameservers. For instance, if you have a nameserver on your network which deals with `xxx.internal.local` at `192.168.0.1` then you can specify `[/internal.local/]192.168.0.1`, and dnsproxy will send all queries to that nameserver. Everything else will be sent to the default upstreams (which are mandatory!). 1. An empty domain specification, // has the special meaning of "unqualified names only" ie names without any dots in them. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dnsproxy-0.56.2/proxy/upstreams.go new/dnsproxy-0.56.3/proxy/upstreams.go --- old/dnsproxy-0.56.2/proxy/upstreams.go 2023-10-17 15:09:58.000000000 +0200 +++ new/dnsproxy-0.56.3/proxy/upstreams.go 2023-10-19 14:09:51.000000000 +0200 @@ -34,111 +34,250 @@ // type check var _ io.Closer = (*UpstreamConfig)(nil) -// ParseUpstreamsConfig returns UpstreamConfig and error if upstreams configuration is invalid -// default upstream syntax: <upstreamString> -// reserved upstream syntax: [/domain1/../domainN/]<upstreamString> -// subdomains only upstream syntax: [/*.domain1/../*.domainN]<upstreamString> -// More specific domains take priority over less specific domains, -// To exclude more specific domains from reserved upstreams querying you should use the following syntax: [/domain1/../domainN/]# -// So the following config: ["[/host.com/]1.2.3.4", "[/www.host.com/]2.3.4.5", "[/maps.host.com/]#", "3.4.5.6"] -// will send queries for *.host.com to 1.2.3.4, except for *.www.host.com, which will go to 2.3.4.5 and *.maps.host.com, -// which will go to default server 3.4.5.6 with all other domains. -// To exclude top level domain from reserved upstreams querying you could use the following: [/*.domain.com/]<upstreamString> -// So the following config: ["[/*.domain.com/]1.2.3.4", "3.4.5.6"] will send queries for all subdomains *.domain.com to 1.2.3.4, -// but domain.com query will be sent to default server 3.4.5.6 as every other query. +// ParseUpstreamsConfig returns UpstreamConfig and error if upstreams +// configuration is invalid. // -// TODO(e.burkov): Refactor this mess. +// # Simple upstreams +// +// Single upstream per line. For example: +// +// 1.2.3.4 +// 3.4.5.6 +// +// # Domain specific upstreams +// +// - reserved upstreams: [/domain1/../domainN/]<upstreamString> +// - subdomains only upstreams: [/*.domain1/../*.domainN]<upstreamString> +// +// Where <upstreamString> is one or many upstreams separated by space (e.g. +// `1.1.1.1` or `1.1.1.1 2.2.2.2`). +// +// More specific domains take priority over less specific domains. To exclude +// more specific domains from reserved upstreams querying you should use the +// following syntax: +// +// [/domain1/../domainN/]# +// +// So the following config: +// +// [/host.com/]1.2.3.4 +// [/www.host.com/]2.3.4.5" +// [/maps.host.com/news.host.com/]# +// 3.4.5.6 +// +// will send queries for *.host.com to 1.2.3.4. Except for *.www.host.com, +// which will go to 2.3.4.5. And *.maps.host.com or *.news.host.com, which +// will go to default server 3.4.5.6 with all other domains. +// +// To exclude top level domain from reserved upstreams querying you could use +// the following: +// +// '[/*.domain.com/]<upstreamString>' +// +// So the following config: +// +// [/*.domain.com/]1.2.3.4 +// 3.4.5.6 +// +// will send queries for all subdomains *.domain.com to 1.2.3.4, but domain.com +// query will be sent to default server 3.4.5.6 as every other query. +// +// TODO(e.burkov): Consider supporting multiple upstreams in a single line for +// default upstream syntax. func ParseUpstreamsConfig(upstreamConfig []string, options *upstream.Options) (*UpstreamConfig, error) { if options == nil { options = &upstream.Options{} } - if len(options.Bootstrap) > 0 { - log.Debug("Bootstraps: %v", options.Bootstrap) + log.Debug("Bootstraps: %s", options.Bootstrap) + + p := &configParser{ + options: options, + upstreamsIndex: map[string]upstream.Upstream{}, + domainReservedUpstreams: map[string][]upstream.Upstream{}, + specifiedDomainUpstreams: map[string][]upstream.Upstream{}, + subdomainsOnlyUpstreams: map[string][]upstream.Upstream{}, + subdomainsOnlyExclusions: stringutil.NewSet(), } - var upstreams []upstream.Upstream - // We use this index to avoid creating duplicates of upstreams - upstreamsIndex := map[string]upstream.Upstream{} + return p.parse(upstreamConfig) +} + +// configParser collects the results of parsing an upstream config. +type configParser struct { + // options contains upstream properties. + options *upstream.Options + + // upstreamsIndex is used to avoid creating duplicates of upstreams. + upstreamsIndex map[string]upstream.Upstream + + // domainReservedUpstreams is a map of reserved domains and lists of + // corresponding upstreams. + domainReservedUpstreams map[string][]upstream.Upstream + + // specifiedDomainUpstreams is a map of excluded domains and lists of + // corresponding upstreams. + specifiedDomainUpstreams map[string][]upstream.Upstream + + // subdomainsOnlyUpstreams is a map of wildcard subdomains and lists of + // corresponding upstreams. + subdomainsOnlyUpstreams map[string][]upstream.Upstream - domainReservedUpstreams := map[string][]upstream.Upstream{} - specifiedDomainUpstreams := map[string][]upstream.Upstream{} - subdomainsOnlyUpstreams := map[string][]upstream.Upstream{} - subdomainsOnlyExclusions := stringutil.NewSet() + // subdomainsOnlyExclusions is set of domains with subdomains exclusions. + subdomainsOnlyExclusions *stringutil.Set - for i, l := range upstreamConfig { - u, hosts, err := parseUpstreamLine(l) - if err != nil { - return &UpstreamConfig{}, err + // upstreams is a list of default upstreams. + upstreams []upstream.Upstream +} + +// parse returns UpstreamConfig and error if upstreams configuration is invalid. +func (p *configParser) parse(conf []string) (c *UpstreamConfig, err error) { + for i, l := range conf { + if err = p.parseLine(i, l); err != nil { + return nil, err } + } - // # excludes more specific domain from reserved upstreams querying - if u == "#" && len(hosts) > 0 { - for _, host := range hosts { - if strings.HasPrefix(host, "*.") { - host = host[len("*."):] - - subdomainsOnlyExclusions.Add(host) - subdomainsOnlyUpstreams[host] = nil - } else { - domainReservedUpstreams[host] = nil - specifiedDomainUpstreams[host] = nil - } - } - } else { - dnsUpstream, ok := upstreamsIndex[u] - if !ok { - // create an upstream - dnsUpstream, err = upstream.AddressToUpstream(u, options.Clone()) + for host, ups := range p.subdomainsOnlyUpstreams { + // Rewrite ups for wildcard subdomains to remove upper level domains + // specs. + p.domainReservedUpstreams[host] = ups + } + + return &UpstreamConfig{ + Upstreams: p.upstreams, + DomainReservedUpstreams: p.domainReservedUpstreams, + SpecifiedDomainUpstreams: p.specifiedDomainUpstreams, + SubdomainExclusions: p.subdomainsOnlyExclusions, + }, nil +} + +// parseLine returns an error if upstream configuration line is invalid. +func (p *configParser) parseLine(idx int, confLine string) (err error) { + upstreams, domains, err := splitConfigLine(idx, confLine) + if err != nil { + // Don't wrap the error since it's informative enough as is. + return err + } + + if upstreams[0] == "#" && len(domains) > 0 { + p.excludeFromReserved(domains) - if err != nil { - err = fmt.Errorf("cannot prepare the upstream %s (%s): %s", l, options.Bootstrap, err) + return nil + } + + for _, u := range upstreams { + err = p.specifyUpstream(domains, u, idx, confLine) + if err != nil { + // Don't wrap the error since it's informative enough as is. + return err + } + } - return &UpstreamConfig{}, err - } + return nil +} - // save to the index - upstreamsIndex[u] = dnsUpstream - } +// splitConfigLine parses upstream configuration line and returns list upstream +// addresses (one or many), list of domains for which this upstream is reserved +// (may be nil) or error if something went wrong. +func splitConfigLine(idx int, confLine string) (upstreams, domains []string, err error) { + if !strings.HasPrefix(confLine, "[/") { + return []string{confLine}, nil, nil + } - if len(hosts) == 0 { - log.Debug("Upstream %d: %s", i, dnsUpstream.Address()) - upstreams = append(upstreams, dnsUpstream) + domainsLine, upstreamsLine, found := strings.Cut(confLine[len("[/"):], "/]") + if !found || upstreamsLine == "" { + return nil, nil, fmt.Errorf("wrong upstream specification %d %q", idx, confLine) + } - continue - } + // split domains list + for _, confHost := range strings.Split(domainsLine, "/") { + if confHost == "" { + // empty domain specification means `unqualified names only` + domains = append(domains, UnqualifiedNames) - for _, host := range hosts { - if strings.HasPrefix(host, "*.") { - host = host[len("*."):] + continue + } - subdomainsOnlyExclusions.Add(host) - log.Debug("domain %s is added to exclusions list", host) + host := strings.TrimPrefix(confHost, "*.") + if err = netutil.ValidateDomainName(host); err != nil { + return nil, nil, err + } - subdomainsOnlyUpstreams[host] = append(subdomainsOnlyUpstreams[host], dnsUpstream) - } else { - specifiedDomainUpstreams[host] = append(specifiedDomainUpstreams[host], dnsUpstream) - } + domains = append(domains, strings.ToLower(confHost+".")) + } - domainReservedUpstreams[host] = append(domainReservedUpstreams[host], dnsUpstream) - } + return strings.Fields(upstreamsLine), domains, nil +} - log.Debug("Upstream %d: %s is reserved for next domains: %s", - i, dnsUpstream.Address(), strings.Join(hosts, ", ")) +// specifyUpstream specifies the upstream for domains. +func (p *configParser) specifyUpstream( + domains []string, + u string, + idx int, + confLine string, +) (err error) { + dnsUpstream, ok := p.upstreamsIndex[u] + // TODO(e.burkov): Improve identifying duplicate upstreams. + if !ok { + // create an upstream + dnsUpstream, err = upstream.AddressToUpstream(u, p.options.Clone()) + if err != nil { + return fmt.Errorf("cannot prepare the upstream %d %q (%s): %s", + idx, confLine, p.options.Bootstrap, err) } + + // save to the index + p.upstreamsIndex[u] = dnsUpstream } - for host, ups := range subdomainsOnlyUpstreams { - // Rewrite ups for wildcard subdomains to remove upper level domains specs. - domainReservedUpstreams[host] = ups + if len(domains) == 0 { + log.Debug("Upstream %d: %s", idx, dnsUpstream.Address()) + p.upstreams = append(p.upstreams, dnsUpstream) + + return nil } - return &UpstreamConfig{ - Upstreams: upstreams, - DomainReservedUpstreams: domainReservedUpstreams, - SpecifiedDomainUpstreams: specifiedDomainUpstreams, - SubdomainExclusions: subdomainsOnlyExclusions, - }, nil + p.includeToReserved(dnsUpstream, domains) + + log.Debug("Upstream %d: %s is reserved for next domains: %s", + idx, dnsUpstream.Address(), domains) + + return nil +} + +// excludeFromReserved excludes more specific domains from reserved upstreams +// querying. +func (p *configParser) excludeFromReserved(domains []string) { + for _, host := range domains { + if trimmed := strings.TrimPrefix(host, "*."); trimmed != host { + p.subdomainsOnlyExclusions.Add(trimmed) + p.subdomainsOnlyUpstreams[trimmed] = nil + + continue + } + + p.domainReservedUpstreams[host] = nil + p.specifiedDomainUpstreams[host] = nil + } +} + +// includeToReserved includes domains to reserved upstreams querying. +func (p *configParser) includeToReserved(dnsUpstream upstream.Upstream, domains []string) { + for _, host := range domains { + if strings.HasPrefix(host, "*.") { + host = host[len("*."):] + + p.subdomainsOnlyExclusions.Add(host) + log.Debug("domain %q is added to exclusions list", host) + + p.subdomainsOnlyUpstreams[host] = append(p.subdomainsOnlyUpstreams[host], dnsUpstream) + } else { + p.specifiedDomainUpstreams[host] = append(p.specifiedDomainUpstreams[host], dnsUpstream) + } + + p.domainReservedUpstreams[host] = append(p.domainReservedUpstreams[host], dnsUpstream) + } } // errNoDefaultUpstreams is returned when no default upstreams specified within @@ -162,41 +301,6 @@ } } -// parseUpstreamLine - parses upstream line and returns the following: -// upstream address -// list of domains for which this upstream is reserved (may be nil) -// error if something went wrong -func parseUpstreamLine(l string) (string, []string, error) { - var hosts []string - u := l - - if strings.HasPrefix(l, "[/") { - // split domains and upstream string - domainsAndUpstream := strings.Split(strings.TrimPrefix(l, "[/"), "/]") - if len(domainsAndUpstream) != 2 { - return "", nil, fmt.Errorf("wrong upstream specification: %s", l) - } - - // split domains list - for _, confHost := range strings.Split(domainsAndUpstream[0], "/") { - if confHost != "" { - host := strings.TrimPrefix(confHost, "*.") - if err := netutil.ValidateDomainName(host); err != nil { - return "", nil, err - } - - hosts = append(hosts, strings.ToLower(confHost+".")) - } else { - // empty domain specification means `unqualified names only` - hosts = append(hosts, UnqualifiedNames) - } - } - u = domainsAndUpstream[1] - } - - return u, hosts, nil -} - // getUpstreamsForDomain looks for a domain in the reserved domains map and // returns a list of corresponding upstreams. It returns default upstreams list // if the domain was not found in the map. More specific domains take priority diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dnsproxy-0.56.2/proxy/upstreams_test.go new/dnsproxy-0.56.3/proxy/upstreams_test.go --- old/dnsproxy-0.56.2/proxy/upstreams_test.go 2023-10-17 15:09:58.000000000 +0200 +++ new/dnsproxy-0.56.3/proxy/upstreams_test.go 2023-10-19 14:09:51.000000000 +0200 @@ -16,6 +16,7 @@ "[/maps.google.com/]#", "[/www.google.com/]tls://1.1.1.1", "[/_acme-challenge.example.org/]#", + "[/example.com/]1.1.1.1 2.2.2.2 3.3.3.3", } config, err := ParseUpstreamsConfig( @@ -56,6 +57,10 @@ name: "another_default", in: "maps.google.com.", want: []string{}, + }, { + name: "multiple_reserved", + in: "example.com.", + want: []string{"1.1.1.1:53", "2.2.2.2:53", "3.3.3.3:53"}, }} for _, tc := range testCases { ++++++ dnsproxy.obsinfo ++++++ --- /var/tmp/diff_new_pack.01EmJH/_old 2023-10-23 23:41:39.457037803 +0200 +++ /var/tmp/diff_new_pack.01EmJH/_new 2023-10-23 23:41:39.461037948 +0200 @@ -1,5 +1,5 @@ name: dnsproxy -version: 0.56.2 -mtime: 1697548198 -commit: 46b2b1cb22104b4380f32986e783caac7a795223 +version: 0.56.3 +mtime: 1697717391 +commit: 39f15ce27a0ad226a083fe0f3102366d85e561c4 ++++++ vendor.tar.zstd ++++++ Binary files /var/tmp/diff_new_pack.01EmJH/_old and /var/tmp/diff_new_pack.01EmJH/_new differ