1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-20 22:45:24 +00:00

fix: a concurrency issue in fakedns (#1666)

In rare cases different domains asking for dns will return the same IP, Add a mutex.
This commit is contained in:
yuhan6665 2022-03-08 21:58:49 -05:00 committed by GitHub
parent 1039ed98b1
commit 6f8af37568
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 1 deletions

View File

@ -8,6 +8,7 @@ import (
"math"
"math/big"
gonet "net"
"sync"
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/cache"
@ -18,6 +19,7 @@ import (
type Holder struct {
domainToIP cache.Lru
nextIP *big.Int
mu *sync.Mutex
ipRange *gonet.IPNet
@ -54,6 +56,7 @@ func (fkdns *Holder) Close() error {
fkdns.domainToIP = nil
fkdns.nextIP = nil
fkdns.ipRange = nil
fkdns.mu = nil
return nil
}
@ -72,7 +75,7 @@ func NewFakeDNSHolder() (*Holder, error) {
}
func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
return &Holder{nil, nil, nil, conf}, nil
return &Holder{nil, nil, nil, nil, conf}, nil
}
func (fkdns *Holder) initializeFromConfig() error {
@ -102,11 +105,14 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
fkdns.domainToIP = cache.NewLru(lruSize)
fkdns.ipRange = ipRange
fkdns.nextIP = currentIP
fkdns.mu = new(sync.Mutex)
return nil
}
// GetFakeIPForDomain checks and generate a fake IP for a domain name
func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
fkdns.mu.Lock()
defer fkdns.mu.Unlock()
if v, ok := fkdns.domainToIP.Get(domain); ok {
return []net.Address{v.(net.Address)}
}

View File

@ -2,10 +2,13 @@ package fakedns
import (
gonet "net"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/sync/errgroup"
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/net"
"github.com/v2fly/v2ray-core/v5/common/uuid"
@ -71,6 +74,31 @@ func TestFakeDnsHolderCreateMappingManySingleDomain(t *testing.T) {
assert.Equal(t, "198.18.0.0", addr2[0].IP().String())
}
func TestGetFakeIPForDomainConcurrently(t *testing.T) {
fkdns, err := NewFakeDNSHolder()
common.Must(err)
total := 200
addr := make([][]net.Address, total+1)
var errg errgroup.Group
for i := 0; i < total; i++ {
errg.Go(testGetFakeIP(i, addr, fkdns))
}
errg.Wait()
for i := 0; i < total; i++ {
for j := i + 1; j < total; j++ {
assert.NotEqual(t, addr[i][0].IP().String(), addr[j][0].IP().String())
}
}
}
func testGetFakeIP(index int, addr [][]net.Address, fkdns *Holder) func() error {
return func() error {
addr[index] = fkdns.GetFakeIPForDomain("fakednstest" + strconv.Itoa(index) + ".example.com")
return nil
}
}
func TestFakeDnsHolderCreateMappingAndRollOver(t *testing.T) {
fkdns, err := NewFakeDNSHolderConfigOnly(&FakeDnsPool{
IpPool: "240.0.0.0/12",