mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 10:01:30 +00:00
Fix fakeip lookup
This commit is contained in:
parent
bb651db2d2
commit
120dae4eed
|
@ -10,7 +10,7 @@ import (
|
||||||
type FakeIPStore interface {
|
type FakeIPStore interface {
|
||||||
Service
|
Service
|
||||||
Contains(address netip.Addr) bool
|
Contains(address netip.Addr) bool
|
||||||
Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error)
|
Create(domain string, isIPv6 bool) (netip.Addr, error)
|
||||||
Lookup(address netip.Addr) (string, bool)
|
Lookup(address netip.Addr) (string, bool)
|
||||||
Reset() error
|
Reset() error
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ type FakeIPStorage interface {
|
||||||
FakeIPStore(address netip.Addr, domain string) error
|
FakeIPStore(address netip.Addr, domain string) error
|
||||||
FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger)
|
FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger)
|
||||||
FakeIPLoad(address netip.Addr) (string, bool)
|
FakeIPLoad(address netip.Addr) (string, bool)
|
||||||
|
FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool)
|
||||||
FakeIPReset() error
|
FakeIPReset() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,16 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bucketFakeIP = []byte("fakeip")
|
bucketFakeIP = []byte("fakeip")
|
||||||
keyMetadata = []byte("metadata")
|
bucketFakeIPDomain4 = []byte("fakeip_domain4")
|
||||||
|
bucketFakeIPDomain6 = []byte("fakeip_domain6")
|
||||||
|
keyMetadata = []byte("metadata")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *CacheFile) FakeIPMetadata() *adapter.FakeIPMetadata {
|
func (c *CacheFile) FakeIPMetadata() *adapter.FakeIPMetadata {
|
||||||
|
@ -54,7 +57,19 @@ func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return bucket.Put(address.AsSlice(), []byte(domain))
|
err = bucket.Put(address.AsSlice(), []byte(domain))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if address.Is4() {
|
||||||
|
bucket, err = tx.CreateBucketIfNotExists(bucketFakeIPDomain4)
|
||||||
|
} else {
|
||||||
|
bucket, err = tx.CreateBucketIfNotExists(bucketFakeIPDomain6)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bucket.Put([]byte(domain), address.AsSlice())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +107,34 @@ func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
|
||||||
return domain, domain != ""
|
return domain, domain != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CacheFile) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool) {
|
||||||
|
var address netip.Addr
|
||||||
|
_ = c.DB.View(func(tx *bbolt.Tx) error {
|
||||||
|
var bucket *bbolt.Bucket
|
||||||
|
if isIPv6 {
|
||||||
|
bucket = tx.Bucket(bucketFakeIPDomain6)
|
||||||
|
} else {
|
||||||
|
bucket = tx.Bucket(bucketFakeIPDomain4)
|
||||||
|
}
|
||||||
|
if bucket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
address = M.AddrFromIP(bucket.Get([]byte(domain)))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return address, address.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *CacheFile) FakeIPReset() error {
|
func (c *CacheFile) FakeIPReset() error {
|
||||||
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
||||||
return tx.DeleteBucket(bucketFakeIP)
|
err := tx.DeleteBucket(bucketFakeIP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = tx.DeleteBucket(bucketFakeIPDomain4)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.DeleteBucket(bucketFakeIPDomain6)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,48 +2,78 @@ package fakeip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing/common/cache"
|
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.FakeIPStorage = (*MemoryStorage)(nil)
|
var _ adapter.FakeIPStorage = (*MemoryStorage)(nil)
|
||||||
|
|
||||||
type MemoryStorage struct {
|
type MemoryStorage struct {
|
||||||
metadata *adapter.FakeIPMetadata
|
addressAccess sync.RWMutex
|
||||||
domainCache *cache.LruCache[netip.Addr, string]
|
domainAccess sync.RWMutex
|
||||||
|
addressCache map[netip.Addr]string
|
||||||
|
domainCache4 map[string]netip.Addr
|
||||||
|
domainCache6 map[string]netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemoryStorage() *MemoryStorage {
|
func NewMemoryStorage() *MemoryStorage {
|
||||||
return &MemoryStorage{
|
return &MemoryStorage{
|
||||||
domainCache: cache.New[netip.Addr, string](),
|
addressCache: make(map[netip.Addr]string),
|
||||||
|
domainCache4: make(map[string]netip.Addr),
|
||||||
|
domainCache6: make(map[string]netip.Addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPMetadata() *adapter.FakeIPMetadata {
|
func (s *MemoryStorage) FakeIPMetadata() *adapter.FakeIPMetadata {
|
||||||
return s.metadata
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
|
func (s *MemoryStorage) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
|
||||||
s.metadata = metadata
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error {
|
func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error {
|
||||||
s.domainCache.Store(address, domain)
|
s.addressAccess.Lock()
|
||||||
|
s.domainAccess.Lock()
|
||||||
|
s.addressCache[address] = domain
|
||||||
|
if address.Is4() {
|
||||||
|
s.domainCache4[domain] = address
|
||||||
|
} else {
|
||||||
|
s.domainCache6[domain] = address
|
||||||
|
}
|
||||||
|
s.domainAccess.Unlock()
|
||||||
|
s.addressAccess.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
|
func (s *MemoryStorage) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
|
||||||
s.domainCache.Store(address, domain)
|
_ = s.FakeIPStore(address, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) {
|
func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) {
|
||||||
return s.domainCache.Load(address)
|
s.addressAccess.RLock()
|
||||||
|
defer s.addressAccess.RUnlock()
|
||||||
|
domain, loaded := s.addressCache[address]
|
||||||
|
return domain, loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MemoryStorage) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool) {
|
||||||
|
s.domainAccess.RLock()
|
||||||
|
defer s.domainAccess.RUnlock()
|
||||||
|
if !isIPv6 {
|
||||||
|
address, loaded := s.domainCache4[domain]
|
||||||
|
return address, loaded
|
||||||
|
} else {
|
||||||
|
address, loaded := s.domainCache6[domain]
|
||||||
|
return address, loaded
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPReset() error {
|
func (s *MemoryStorage) FakeIPReset() error {
|
||||||
s.domainCache = cache.New[netip.Addr, string]()
|
s.addressCache = make(map[netip.Addr]string)
|
||||||
|
s.domainCache4 = make(map[string]netip.Addr)
|
||||||
|
s.domainCache6 = make(map[string]netip.Addr)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,14 +69,14 @@ func (s *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
||||||
func (s *Transport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
func (s *Transport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
||||||
var addresses []netip.Addr
|
var addresses []netip.Addr
|
||||||
if strategy != dns.DomainStrategyUseIPv6 {
|
if strategy != dns.DomainStrategyUseIPv6 {
|
||||||
inet4Address, err := s.store.Create(domain, dns.DomainStrategyUseIPv4)
|
inet4Address, err := s.store.Create(domain, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
addresses = append(addresses, inet4Address)
|
addresses = append(addresses, inet4Address)
|
||||||
}
|
}
|
||||||
if strategy != dns.DomainStrategyUseIPv4 {
|
if strategy != dns.DomainStrategyUseIPv4 {
|
||||||
inet6Address, err := s.store.Create(domain, dns.DomainStrategyUseIPv6)
|
inet6Address, err := s.store.Create(domain, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-dns"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
@ -72,9 +71,12 @@ func (s *Store) Close() error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error) {
|
func (s *Store) Create(domain string, isIPv6 bool) (netip.Addr, error) {
|
||||||
|
if address, loaded := s.storage.FakeIPLoadDomain(domain, isIPv6); loaded {
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
var address netip.Addr
|
var address netip.Addr
|
||||||
if strategy == dns.DomainStrategyUseIPv4 {
|
if !isIPv6 {
|
||||||
if !s.inet4Current.IsValid() {
|
if !s.inet4Current.IsValid() {
|
||||||
return netip.Addr{}, E.New("missing IPv4 fakeip address range")
|
return netip.Addr{}, E.New("missing IPv4 fakeip address range")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue