all: resync with master
This commit is contained in:
parent
158d4f0249
commit
5c6bb33e3a
|
@ -265,8 +265,8 @@
|
|||
# need to build a few of these.
|
||||
'variables':
|
||||
'channel': 'beta'
|
||||
'dockerFrontend': '${bamboo.adguardRegistryBasePath}/home-js-builder:2.0'
|
||||
'dockerGo': '${bamboo.adguardRegistryBasePath}/go-builder:1.22.5--1'
|
||||
'dockerFrontend': 'adguard/home-js-builder:2.0'
|
||||
'dockerGo': 'adguard/go-builder:1.22.5--1'
|
||||
# release-vX.Y.Z branches are the branches from which the actual final
|
||||
# release is built.
|
||||
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
|
||||
|
@ -281,5 +281,5 @@
|
|||
# are the ones that actually get released.
|
||||
'variables':
|
||||
'channel': 'release'
|
||||
'dockerFrontend': '${bamboo.adguardRegistryBasePath}/home-js-builder:2.0'
|
||||
'dockerGo': '${bamboo.adguardRegistryBasePath}/go-builder:1.22.5--1'
|
||||
'dockerFrontend': 'adguard/home-js-builder:2.0'
|
||||
'dockerGo': 'adguard/go-builder:1.22.5--1'
|
||||
|
|
|
@ -194,6 +194,6 @@
|
|||
# Set the default release channel on the release branch to beta, as we
|
||||
# may need to build a few of these.
|
||||
'variables':
|
||||
'dockerFrontend': '${bamboo.adguardRegistryBasePath}/home-js-builder:2.0'
|
||||
'dockerGo': '${bamboo.adguardRegistryBasePath}/go-builder:1.22.5--1'
|
||||
'dockerFrontend': 'adguard/home-js-builder:2.0'
|
||||
'dockerGo': 'adguard/go-builder:1.22.5--1'
|
||||
'channel': 'candidate'
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
package dnsforward
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/cache"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// uint* sizes in bytes to improve readability.
|
||||
//
|
||||
// TODO(e.burkov): Remove when there will be a more regardful way to define
|
||||
// those. See https://github.com/golang/go/issues/29982.
|
||||
const (
|
||||
uint16sz = 2
|
||||
uint64sz = 8
|
||||
)
|
||||
|
||||
// recursionDetector detects recursion in DNS forwarding.
|
||||
type recursionDetector struct {
|
||||
recentRequests cache.Cache
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
// check checks if the passed req was already sent by the server.
|
||||
func (rd *recursionDetector) check(msg dns.Msg) (ok bool) {
|
||||
if len(msg.Question) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
key := msgToSignature(msg)
|
||||
expireData := rd.recentRequests.Get(key)
|
||||
if expireData == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
expire := time.Unix(0, int64(binary.BigEndian.Uint64(expireData)))
|
||||
|
||||
return time.Now().Before(expire)
|
||||
}
|
||||
|
||||
// add caches the msg if it has anything in the questions section.
|
||||
func (rd *recursionDetector) add(msg dns.Msg) {
|
||||
now := time.Now()
|
||||
|
||||
if len(msg.Question) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
key := msgToSignature(msg)
|
||||
expire64 := uint64(now.Add(rd.ttl).UnixNano())
|
||||
expire := make([]byte, uint64sz)
|
||||
binary.BigEndian.PutUint64(expire, expire64)
|
||||
|
||||
rd.recentRequests.Set(key, expire)
|
||||
}
|
||||
|
||||
// clear clears the recent requests cache.
|
||||
func (rd *recursionDetector) clear() {
|
||||
rd.recentRequests.Clear()
|
||||
}
|
||||
|
||||
// newRecursionDetector returns the initialized *recursionDetector.
|
||||
func newRecursionDetector(ttl time.Duration, suspectsNum uint) (rd *recursionDetector) {
|
||||
return &recursionDetector{
|
||||
recentRequests: cache.New(cache.Config{
|
||||
EnableLRU: true,
|
||||
MaxCount: suspectsNum,
|
||||
}),
|
||||
ttl: ttl,
|
||||
}
|
||||
}
|
||||
|
||||
// msgToSignature converts msg into it's signature represented in bytes.
|
||||
func msgToSignature(msg dns.Msg) (sig []byte) {
|
||||
sig = make([]byte, uint16sz*2+netutil.MaxDomainNameLen)
|
||||
// The binary.BigEndian byte order is used everywhere except when the real
|
||||
// machine's endianness is needed.
|
||||
byteOrder := binary.BigEndian
|
||||
byteOrder.PutUint16(sig[0:], msg.Id)
|
||||
q := msg.Question[0]
|
||||
byteOrder.PutUint16(sig[uint16sz:], q.Qtype)
|
||||
copy(sig[2*uint16sz:], []byte(q.Name))
|
||||
|
||||
return sig
|
||||
}
|
||||
|
||||
// msgToSignatureSlow converts msg into it's signature represented in bytes in
|
||||
// the less efficient way.
|
||||
//
|
||||
// See BenchmarkMsgToSignature.
|
||||
func msgToSignatureSlow(msg dns.Msg) (sig []byte) {
|
||||
type msgSignature struct {
|
||||
name [netutil.MaxDomainNameLen]byte
|
||||
id uint16
|
||||
qtype uint16
|
||||
}
|
||||
|
||||
b := bytes.NewBuffer(sig)
|
||||
q := msg.Question[0]
|
||||
signature := msgSignature{
|
||||
id: msg.Id,
|
||||
qtype: q.Qtype,
|
||||
}
|
||||
copy(signature.name[:], q.Name)
|
||||
if err := binary.Write(b, binary.BigEndian, signature); err != nil {
|
||||
log.Debug("writing message signature: %s", err)
|
||||
}
|
||||
|
||||
return b.Bytes()
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
package dnsforward
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRecursionDetector_Check(t *testing.T) {
|
||||
rd := newRecursionDetector(0, 2)
|
||||
|
||||
const (
|
||||
recID = 1234
|
||||
recTTL = time.Hour * 100
|
||||
)
|
||||
|
||||
const nonRecID = recID * 2
|
||||
|
||||
sampleQuestion := dns.Question{
|
||||
Name: "some.domain",
|
||||
Qtype: dns.TypeAAAA,
|
||||
}
|
||||
sampleMsg := dns.Msg{
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Id: recID,
|
||||
},
|
||||
Question: []dns.Question{sampleQuestion},
|
||||
}
|
||||
|
||||
// Manually add the message with big ttl.
|
||||
key := msgToSignature(sampleMsg)
|
||||
expire := make([]byte, uint64sz)
|
||||
binary.BigEndian.PutUint64(expire, uint64(time.Now().Add(recTTL).UnixNano()))
|
||||
rd.recentRequests.Set(key, expire)
|
||||
|
||||
// Add an expired message.
|
||||
sampleMsg.Id = nonRecID
|
||||
rd.add(sampleMsg)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
questions []dns.Question
|
||||
id uint16
|
||||
want bool
|
||||
}{{
|
||||
name: "recurrent",
|
||||
questions: []dns.Question{sampleQuestion},
|
||||
id: recID,
|
||||
want: true,
|
||||
}, {
|
||||
name: "not_suspected",
|
||||
questions: []dns.Question{sampleQuestion},
|
||||
id: recID + 1,
|
||||
want: false,
|
||||
}, {
|
||||
name: "expired",
|
||||
questions: []dns.Question{sampleQuestion},
|
||||
id: nonRecID,
|
||||
want: false,
|
||||
}, {
|
||||
name: "empty",
|
||||
questions: []dns.Question{},
|
||||
id: nonRecID,
|
||||
want: false,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
sampleMsg.Id = tc.id
|
||||
sampleMsg.Question = tc.questions
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
detected := rd.check(sampleMsg)
|
||||
assert.Equal(t, tc.want, detected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecursionDetector_Suspect(t *testing.T) {
|
||||
rd := newRecursionDetector(0, 1)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
msg dns.Msg
|
||||
want int
|
||||
}{{
|
||||
name: "simple",
|
||||
msg: dns.Msg{
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Id: 1234,
|
||||
},
|
||||
Question: []dns.Question{{
|
||||
Name: "some.domain",
|
||||
Qtype: dns.TypeA,
|
||||
}},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
name: "unencumbered",
|
||||
msg: dns.Msg{},
|
||||
want: 0,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Cleanup(rd.clear)
|
||||
rd.add(tc.msg)
|
||||
assert.Equal(t, tc.want, rd.recentRequests.Stats().Count)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var sink []byte
|
||||
|
||||
func BenchmarkMsgToSignature(b *testing.B) {
|
||||
const name = "some.not.very.long.host.name"
|
||||
|
||||
msg := dns.Msg{
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Id: 1234,
|
||||
},
|
||||
Question: []dns.Question{{
|
||||
Name: name,
|
||||
Qtype: dns.TypeAAAA,
|
||||
}},
|
||||
}
|
||||
|
||||
b.Run("efficient", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
sink = msgToSignature(msg)
|
||||
}
|
||||
|
||||
assert.NotEmpty(b, sink)
|
||||
})
|
||||
|
||||
b.Run("inefficient", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
sink = msgToSignatureSlow(msg)
|
||||
}
|
||||
|
||||
assert.NotEmpty(b, sink)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue