Pull request: 3013 querylog idna

Merge in DNS/adguard-home from 3013-idna to master

Closes #3013.

Squashed commit of the following:

commit 567d4c3beef3cf3ee995ad9d8c3aba6616c74c6c
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Jun 29 13:11:10 2021 +0300

    client: mv punycode label

commit 6585dcaece9f590d7f02afb5aa25953ab0c2555b
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Jun 29 12:32:40 2021 +0300

    client: handle unicode name

commit c0f61bfbb9bdf919be7b07c112c4b7a52f3ad6a1
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Jun 28 20:00:57 2021 +0300

    all: imp log of changes

commit 41388abc8770ce164bcba327fcf0013133b5e6f7
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Jun 28 19:52:23 2021 +0300

    scripts: imp hooks

commit 9c4ba933fbd9340e1de061d4f451218238650c0f
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Jun 28 19:47:27 2021 +0300

    all: imp code, docs

commit 61bd6d6f926480cb8c2f9bd3cd2b61e1532f71cf
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Jun 28 16:09:25 2021 +0300

    querylog: add ascii hostname, convert to unicode
This commit is contained in:
Eugene Burkov
2021-06-29 13:36:52 +03:00
parent 9d1656b5c1
commit 16e5e09c2e
11 changed files with 139 additions and 52 deletions

View File

@@ -127,7 +127,7 @@ func getDoubleQuotesEnclosedValue(s *string) bool {
}
// parseSearchCriterion parses a search criterion from the query parameter.
func (l *queryLog) parseSearchCriterion(q url.Values, name string, ct criterionType) (bool, searchCriterion, error) {
func (l *queryLog) parseSearchCriterion(q url.Values, name string, ct criterionType) (ok bool, sc searchCriterion, err error) {
val := q.Get(name)
if len(val) == 0 {
return false, searchCriterion{}, nil
@@ -176,7 +176,7 @@ func (l *queryLog) parseSearchParams(r *http.Request) (p *searchParams, err erro
}
paramNames := map[string]criterionType{
"search": ctDomainOrClient,
"search": ctTerm,
"response_status": ctFilteringStatus,
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/golibs/log"
"github.com/miekg/dns"
"golang.org/x/net/idna"
)
// TODO(a.garipov): Use a proper structured approach here.
@@ -66,6 +67,20 @@ func (l *queryLog) logEntryToJSONEntry(entry *logEntry) (jsonEntry jobject) {
}
}
hostname := entry.QHost
question := jobject{
"type": entry.QType,
"class": entry.QClass,
"name": hostname,
}
if qhost, err := idna.ToUnicode(hostname); err == nil {
if qhost != hostname && qhost != "" {
question["unicode_name"] = qhost
}
} else {
log.Debug("translating %q into unicode: %s", hostname, err)
}
jsonEntry = jobject{
"reason": entry.Result.Reason.String(),
"elapsedMs": strconv.FormatFloat(entry.Elapsed.Seconds()*1000, 'f', -1, 64),
@@ -74,11 +89,7 @@ func (l *queryLog) logEntryToJSONEntry(entry *logEntry) (jsonEntry jobject) {
"client_info": entry.client,
"client_proto": entry.ClientProto,
"upstream": entry.Upstream,
"question": jobject{
"host": entry.QHost,
"type": entry.QType,
"class": entry.QClass,
},
"question": question,
}
if entry.ClientID != "" {

View File

@@ -67,7 +67,7 @@ func TestQueryLog(t *testing.T) {
}, {
name: "by_domain_strict",
sCr: []searchCriterion{{
criterionType: ctDomainOrClient,
criterionType: ctTerm,
strict: true,
value: "TEST.example.org",
}},
@@ -77,7 +77,7 @@ func TestQueryLog(t *testing.T) {
}, {
name: "by_domain_non-strict",
sCr: []searchCriterion{{
criterionType: ctDomainOrClient,
criterionType: ctTerm,
strict: false,
value: "example.ORG",
}},
@@ -89,7 +89,7 @@ func TestQueryLog(t *testing.T) {
}, {
name: "by_client_ip_strict",
sCr: []searchCriterion{{
criterionType: ctDomainOrClient,
criterionType: ctTerm,
strict: true,
value: "2.2.2.2",
}},
@@ -99,7 +99,7 @@ func TestQueryLog(t *testing.T) {
}, {
name: "by_client_ip_non-strict",
sCr: []searchCriterion{{
criterionType: ctDomainOrClient,
criterionType: ctTerm,
strict: false,
value: "2.2.2",
}},

View File

@@ -11,9 +11,11 @@ import (
type criterionType int
const (
// ctDomainOrClient is for searching by the domain name, the client's IP
// address, or the clinet's ID.
ctDomainOrClient criterionType = iota
// ctTerm is for searching by the domain name, the client's IP
// address, the client's ID or the client's name.
//
// TODO(e.burkov): Make it support IDNA while #3012.
ctTerm criterionType = iota
// ctFilteringStatus is for searching by the filtering status.
//
// See (*searchCriterion).ctFilteringStatusCase for details.
@@ -114,7 +116,7 @@ func (c *searchCriterion) ctDomainOrClientCaseNonStrict(
// optimisation purposes.
func (c *searchCriterion) quickMatch(line string, findClient quickMatchClientFunc) (ok bool) {
switch c.criterionType {
case ctDomainOrClient:
case ctTerm:
host := readJSONValue(line, `"QH":"`)
ip := readJSONValue(line, `"IP":"`)
clientID := readJSONValue(line, `"CID":"`)
@@ -141,7 +143,7 @@ func (c *searchCriterion) quickMatch(line string, findClient quickMatchClientFun
// match checks if the log entry matches this search criterion.
func (c *searchCriterion) match(entry *logEntry) bool {
switch c.criterionType {
case ctDomainOrClient:
case ctTerm:
return c.ctDomainOrClientCase(entry)
case ctFilteringStatus:
return c.ctFilteringStatusCase(entry.Result)