mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 16:41:30 +00:00
109 lines
2.7 KiB
Go
109 lines
2.7 KiB
Go
|
package fakeip
|
||
|
|
||
|
import (
|
||
|
"net/netip"
|
||
|
|
||
|
"github.com/sagernet/sing-box/adapter"
|
||
|
"github.com/sagernet/sing-dns"
|
||
|
E "github.com/sagernet/sing/common/exceptions"
|
||
|
)
|
||
|
|
||
|
var _ adapter.FakeIPStore = (*Store)(nil)
|
||
|
|
||
|
type Store struct {
|
||
|
router adapter.Router
|
||
|
inet4Range netip.Prefix
|
||
|
inet6Range netip.Prefix
|
||
|
storage adapter.FakeIPStorage
|
||
|
inet4Current netip.Addr
|
||
|
inet6Current netip.Addr
|
||
|
}
|
||
|
|
||
|
func NewStore(router adapter.Router, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
|
||
|
return &Store{
|
||
|
router: router,
|
||
|
inet4Range: inet4Range,
|
||
|
inet6Range: inet6Range,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Store) Start() error {
|
||
|
var storage adapter.FakeIPStorage
|
||
|
if clashServer := s.router.ClashServer(); clashServer != nil && clashServer.StoreFakeIP() {
|
||
|
if cacheFile := clashServer.CacheFile(); cacheFile != nil {
|
||
|
storage = cacheFile
|
||
|
}
|
||
|
}
|
||
|
if storage == nil {
|
||
|
storage = NewMemoryStorage()
|
||
|
}
|
||
|
metadata := storage.FakeIPMetadata()
|
||
|
if metadata != nil && metadata.Inet4Range == s.inet4Range && metadata.Inet6Range == s.inet6Range {
|
||
|
s.inet4Current = metadata.Inet4Current
|
||
|
s.inet6Current = metadata.Inet6Current
|
||
|
} else {
|
||
|
if s.inet4Range.IsValid() {
|
||
|
s.inet4Current = s.inet4Range.Addr().Next().Next()
|
||
|
}
|
||
|
if s.inet6Range.IsValid() {
|
||
|
s.inet6Current = s.inet6Range.Addr().Next().Next()
|
||
|
}
|
||
|
}
|
||
|
s.storage = storage
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (s *Store) Contains(address netip.Addr) bool {
|
||
|
return s.inet4Range.Contains(address) || s.inet6Range.Contains(address)
|
||
|
}
|
||
|
|
||
|
func (s *Store) Close() error {
|
||
|
if s.storage == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return s.storage.FakeIPSaveMetadata(&adapter.FakeIPMetadata{
|
||
|
Inet4Range: s.inet4Range,
|
||
|
Inet6Range: s.inet6Range,
|
||
|
Inet4Current: s.inet4Current,
|
||
|
Inet6Current: s.inet6Current,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error) {
|
||
|
var address netip.Addr
|
||
|
if strategy == dns.DomainStrategyUseIPv4 {
|
||
|
if !s.inet4Current.IsValid() {
|
||
|
return netip.Addr{}, E.New("missing IPv4 fakeip address range")
|
||
|
}
|
||
|
nextAddress := s.inet4Current.Next()
|
||
|
if !s.inet4Range.Contains(nextAddress) {
|
||
|
nextAddress = s.inet4Range.Addr().Next().Next()
|
||
|
}
|
||
|
s.inet4Current = nextAddress
|
||
|
address = nextAddress
|
||
|
} else {
|
||
|
if !s.inet6Current.IsValid() {
|
||
|
return netip.Addr{}, E.New("missing IPv6 fakeip address range")
|
||
|
}
|
||
|
nextAddress := s.inet6Current.Next()
|
||
|
if !s.inet6Range.Contains(nextAddress) {
|
||
|
nextAddress = s.inet6Range.Addr().Next().Next()
|
||
|
}
|
||
|
s.inet6Current = nextAddress
|
||
|
address = nextAddress
|
||
|
}
|
||
|
err := s.storage.FakeIPStore(address, domain)
|
||
|
if err != nil {
|
||
|
return netip.Addr{}, err
|
||
|
}
|
||
|
return address, nil
|
||
|
}
|
||
|
|
||
|
func (s *Store) Lookup(address netip.Addr) (string, bool) {
|
||
|
return s.storage.FakeIPLoad(address)
|
||
|
}
|
||
|
|
||
|
func (s *Store) Reset() error {
|
||
|
return s.storage.FakeIPReset()
|
||
|
}
|