mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-25 17:21:34 +00:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7320ec4285 | ||
|
|
be5359cd58 | ||
|
|
c84d058bba | ||
|
|
a2590e861c | ||
|
|
8ca484948c | ||
|
|
e1d23600e7 | ||
|
|
f56945fdb7 | ||
|
|
c84dfeabaa | ||
|
|
09e458e9e8 | ||
|
|
82d006b7e8 | ||
|
|
eac04117dc | ||
|
|
b72da8ca94 | ||
|
|
fcd28dd387 |
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PROJECTS=$(dirname "$0")/../..
|
||||
|
||||
function updateClient() {
|
||||
pushd clients/$1
|
||||
git fetch
|
||||
git reset FETCH_HEAD --hard
|
||||
popd
|
||||
git add clients/$1
|
||||
}
|
||||
|
||||
updateClient "apple"
|
||||
updateClient "android"
|
||||
@@ -1,6 +0,0 @@
|
||||
[submodule "clients/apple"]
|
||||
path = clients/apple
|
||||
url = https://github.com/SagerNet/sing-box-for-apple.git
|
||||
[submodule "clients/android"]
|
||||
path = clients/android
|
||||
url = https://github.com/SagerNet/sing-box-for-android.git
|
||||
@@ -78,12 +78,11 @@ update_android_version:
|
||||
go run ./cmd/internal/update_android_version
|
||||
|
||||
build_android:
|
||||
cd ../sing-box-for-android && ./gradlew :app:assemblePlayRelease && ./gradlew :app:assembleOtherRelease && ./gradlew --stop
|
||||
cd ../sing-box-for-android && ./gradlew :app:assemblePlayRelease && ./gradlew --stop
|
||||
|
||||
upload_android:
|
||||
mkdir -p dist/release_android
|
||||
cp ../sing-box-for-android/app/build/outputs/apk/play/release/*.apk dist/release_android
|
||||
cp ../sing-box-for-android/app/build/outputs/apk/other/release/*-universal.apk dist/release_android
|
||||
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release_android
|
||||
rm -rf dist/release_android
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
"github.com/sagernet/sing-dns"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
)
|
||||
@@ -31,9 +30,6 @@ type CacheFile interface {
|
||||
StoreFakeIP() bool
|
||||
FakeIPStorage
|
||||
|
||||
StoreRDRC() bool
|
||||
dns.RDRCStore
|
||||
|
||||
LoadMode() string
|
||||
StoreMode(mode string) error
|
||||
LoadSelected(group string) string
|
||||
|
||||
@@ -33,8 +33,6 @@ type Router interface {
|
||||
|
||||
RuleSet(tag string) (RuleSet, bool)
|
||||
|
||||
NeedWIFIState() bool
|
||||
|
||||
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
|
||||
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
|
||||
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
|
||||
|
||||
Submodule clients/android deleted from 67fba0f0d3
Submodule clients/apple deleted from be86607f31
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -19,46 +18,34 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
common.Must(os.Chdir(androidPath))
|
||||
localProps := common.Must1(os.ReadFile("version.properties"))
|
||||
localProps := common.Must1(os.ReadFile("local.properties"))
|
||||
var propsList [][]string
|
||||
for _, propLine := range strings.Split(string(localProps), "\n") {
|
||||
propsList = append(propsList, strings.Split(propLine, "="))
|
||||
}
|
||||
var (
|
||||
versionUpdated bool
|
||||
goVersionUpdated bool
|
||||
)
|
||||
for _, propPair := range propsList {
|
||||
switch propPair[0] {
|
||||
case "VERSION_NAME":
|
||||
if propPair[1] != newVersion.String() {
|
||||
versionUpdated = true
|
||||
propPair[1] = newVersion.String()
|
||||
log.Info("updated version to ", newVersion.String())
|
||||
}
|
||||
case "GO_VERSION":
|
||||
if propPair[1] != runtime.Version() {
|
||||
goVersionUpdated = true
|
||||
propPair[1] = runtime.Version()
|
||||
log.Info("updated Go version to ", runtime.Version())
|
||||
if propPair[0] == "VERSION_NAME" {
|
||||
if propPair[1] == newVersion.String() {
|
||||
log.Info("version not changed")
|
||||
return
|
||||
}
|
||||
propPair[1] = newVersion.String()
|
||||
log.Info("updated version to ", newVersion.String())
|
||||
}
|
||||
}
|
||||
if !(versionUpdated || goVersionUpdated) {
|
||||
log.Info("version not changed")
|
||||
return
|
||||
}
|
||||
for _, propPair := range propsList {
|
||||
switch propPair[0] {
|
||||
case "VERSION_CODE":
|
||||
versionCode := common.Must1(strconv.ParseInt(propPair[1], 10, 64))
|
||||
propPair[1] = strconv.Itoa(int(versionCode + 1))
|
||||
log.Info("updated version code to ", propPair[1])
|
||||
case "RELEASE_NOTES":
|
||||
propPair[1] = "sing-box " + newVersion.String()
|
||||
}
|
||||
}
|
||||
var newProps []string
|
||||
for _, propPair := range propsList {
|
||||
newProps = append(newProps, strings.Join(propPair, "="))
|
||||
}
|
||||
common.Must(os.WriteFile("version.properties", []byte(strings.Join(newProps, "\n")), 0o644))
|
||||
common.Must(os.WriteFile("local.properties", []byte(strings.Join(newProps, "\n")), 0o644))
|
||||
}
|
||||
|
||||
@@ -2,20 +2,6 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
#### 1.9.0-alpha.9
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.9.0-alpha.8
|
||||
|
||||
* Add rejected DNS response cache support **1**
|
||||
* Fixes and improvements
|
||||
|
||||
**1**:
|
||||
|
||||
The new feature allows you to cache the check results of
|
||||
[Address filter DNS rule items](/configuration/dns/rule/#address-filter-fields) until expiration.
|
||||
|
||||
#### 1.9.0-alpha.7
|
||||
|
||||
* Update gVisor to 20240206.0
|
||||
|
||||
@@ -339,13 +339,9 @@ Will overrides `dns.client_subnet` and `servers.[].client_subnet`.
|
||||
|
||||
Only takes effect for IP address requests. When the query results do not match the address filtering rule items, the current rule will be skipped.
|
||||
|
||||
!!! info ""
|
||||
|
||||
`ip_cidr` items in included rule sets also takes effect as an address filtering field.
|
||||
|
||||
!!! note ""
|
||||
|
||||
Enable `experimental.cache_file.store_rdrc` to cache results.
|
||||
`ip_cidr` items in included rule sets also takes effect as an address filtering field.
|
||||
|
||||
#### geoip
|
||||
|
||||
|
||||
@@ -337,13 +337,9 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
|
||||
|
||||
仅对IP地址请求生效。 当查询结果与地址筛选规则项不匹配时,将跳过当前规则。
|
||||
|
||||
!!! info ""
|
||||
|
||||
引用的规则集中的 `ip_cidr` 项也作为地址筛选字段生效。
|
||||
|
||||
!!! note ""
|
||||
|
||||
启用 `experimental.cache_file.store_rdrc` 以缓存结果。
|
||||
引用的规则集中的 `ip_cidr` 项也作为地址筛选字段生效。
|
||||
|
||||
#### geoip
|
||||
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
---
|
||||
|
||||
!!! question "Since sing-box 1.8.0"
|
||||
|
||||
!!! quote "Changes in sing-box 1.9.0"
|
||||
|
||||
:material-plus: [store_rdrc](#store_rdrc)
|
||||
:material-plus: [rdrc_timeout](#rdrc_timeout)
|
||||
|
||||
### Structure
|
||||
|
||||
```json
|
||||
@@ -16,9 +7,7 @@ icon: material/new-box
|
||||
"enabled": true,
|
||||
"path": "",
|
||||
"cache_id": "",
|
||||
"store_fakeip": false,
|
||||
"store_rdrc": false,
|
||||
"rdrc_timeout": ""
|
||||
"store_fakeip": false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -36,23 +25,6 @@ Path to the cache file.
|
||||
|
||||
#### cache_id
|
||||
|
||||
Identifier in the cache file
|
||||
Identifier in cache file.
|
||||
|
||||
If not empty, configuration specified data will use a separate store keyed by it.
|
||||
|
||||
#### store_fakeip
|
||||
|
||||
Store fakeip in the cache file
|
||||
|
||||
#### store_rdrc
|
||||
|
||||
Store rejected DNS response cache in the cache file
|
||||
|
||||
The check results of [Address filter DNS rule items](/configuration/dns/rule/#address-filter-fields)
|
||||
will be cached until expiration.
|
||||
|
||||
#### rdrc_timeout
|
||||
|
||||
Timeout of rejected DNS response cache.
|
||||
|
||||
`7d` is used by default.
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
---
|
||||
|
||||
!!! question "自 sing-box 1.8.0 起"
|
||||
|
||||
!!! quote "sing-box 1.9.0 中的更改"
|
||||
|
||||
:material-plus: [store_rdrc](#store_rdrc)
|
||||
:material-plus: [rdrc_timeout](#rdrc_timeout)
|
||||
|
||||
### 结构
|
||||
|
||||
```json
|
||||
@@ -16,9 +7,7 @@ icon: material/new-box
|
||||
"enabled": true,
|
||||
"path": "",
|
||||
"cache_id": "",
|
||||
"store_fakeip": false,
|
||||
"store_rdrc": false,
|
||||
"rdrc_timeout": ""
|
||||
"store_fakeip": false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -37,19 +26,3 @@ icon: material/new-box
|
||||
缓存文件中的标识符。
|
||||
|
||||
如果不为空,配置特定的数据将使用由其键控的单独存储。
|
||||
|
||||
#### store_fakeip
|
||||
|
||||
将 fakeip 存储在缓存文件中。
|
||||
|
||||
#### store_rdrc
|
||||
|
||||
将拒绝的 DNS 响应缓存存储在缓存文件中。
|
||||
|
||||
[地址筛选 DNS 规则项](/zh/configuration/dns/rule/#_3) 的检查结果将被缓存至过期。
|
||||
|
||||
#### rdrc_timeout
|
||||
|
||||
拒绝的 DNS 响应缓存超时。
|
||||
|
||||
默认使用 `7d`。
|
||||
|
||||
@@ -29,7 +29,6 @@ var (
|
||||
string(bucketExpand),
|
||||
string(bucketMode),
|
||||
string(bucketRuleSet),
|
||||
string(bucketRDRC),
|
||||
}
|
||||
|
||||
cacheIDDefault = []byte("default")
|
||||
@@ -38,25 +37,17 @@ var (
|
||||
var _ adapter.CacheFile = (*CacheFile)(nil)
|
||||
|
||||
type CacheFile struct {
|
||||
ctx context.Context
|
||||
path string
|
||||
cacheID []byte
|
||||
storeFakeIP bool
|
||||
storeRDRC bool
|
||||
rdrcTimeout time.Duration
|
||||
ctx context.Context
|
||||
path string
|
||||
cacheID []byte
|
||||
storeFakeIP bool
|
||||
|
||||
DB *bbolt.DB
|
||||
saveMetadataTimer *time.Timer
|
||||
saveFakeIPAccess sync.RWMutex
|
||||
saveAccess sync.RWMutex
|
||||
saveDomain map[netip.Addr]string
|
||||
saveAddress4 map[string]netip.Addr
|
||||
saveAddress6 map[string]netip.Addr
|
||||
saveRDRCAccess sync.RWMutex
|
||||
saveRDRC map[saveRDRCCacheKey]bool
|
||||
}
|
||||
|
||||
type saveRDRCCacheKey struct {
|
||||
TransportName string
|
||||
QuestionName string
|
||||
saveMetadataTimer *time.Timer
|
||||
}
|
||||
|
||||
func New(ctx context.Context, options option.CacheFileOptions) *CacheFile {
|
||||
@@ -70,25 +61,14 @@ func New(ctx context.Context, options option.CacheFileOptions) *CacheFile {
|
||||
if options.CacheID != "" {
|
||||
cacheIDBytes = append([]byte{0}, []byte(options.CacheID)...)
|
||||
}
|
||||
var rdrcTimeout time.Duration
|
||||
if options.StoreRDRC {
|
||||
if options.RDRCTimeout > 0 {
|
||||
rdrcTimeout = time.Duration(options.RDRCTimeout)
|
||||
} else {
|
||||
rdrcTimeout = 7 * 24 * time.Hour
|
||||
}
|
||||
}
|
||||
return &CacheFile{
|
||||
ctx: ctx,
|
||||
path: filemanager.BasePath(ctx, path),
|
||||
cacheID: cacheIDBytes,
|
||||
storeFakeIP: options.StoreFakeIP,
|
||||
storeRDRC: options.StoreRDRC,
|
||||
rdrcTimeout: rdrcTimeout,
|
||||
saveDomain: make(map[netip.Addr]string),
|
||||
saveAddress4: make(map[string]netip.Addr),
|
||||
saveAddress6: make(map[string]netip.Addr),
|
||||
saveRDRC: make(map[saveRDRCCacheKey]bool),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,34 +89,34 @@ func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
|
||||
}
|
||||
|
||||
func (c *CacheFile) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
|
||||
c.saveFakeIPAccess.Lock()
|
||||
c.saveAccess.Lock()
|
||||
c.saveDomain[address] = domain
|
||||
if address.Is4() {
|
||||
c.saveAddress4[domain] = address
|
||||
} else {
|
||||
c.saveAddress6[domain] = address
|
||||
}
|
||||
c.saveFakeIPAccess.Unlock()
|
||||
c.saveAccess.Unlock()
|
||||
go func() {
|
||||
err := c.FakeIPStore(address, domain)
|
||||
if err != nil {
|
||||
logger.Warn("save FakeIP cache: ", err)
|
||||
logger.Warn("save FakeIP address pair: ", err)
|
||||
}
|
||||
c.saveFakeIPAccess.Lock()
|
||||
c.saveAccess.Lock()
|
||||
delete(c.saveDomain, address)
|
||||
if address.Is4() {
|
||||
delete(c.saveAddress4, domain)
|
||||
} else {
|
||||
delete(c.saveAddress6, domain)
|
||||
}
|
||||
c.saveFakeIPAccess.Unlock()
|
||||
c.saveAccess.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
|
||||
c.saveFakeIPAccess.RLock()
|
||||
c.saveAccess.RLock()
|
||||
cachedDomain, cached := c.saveDomain[address]
|
||||
c.saveFakeIPAccess.RUnlock()
|
||||
c.saveAccess.RUnlock()
|
||||
if cached {
|
||||
return cachedDomain, true
|
||||
}
|
||||
@@ -137,13 +137,13 @@ func (c *CacheFile) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bo
|
||||
cachedAddress netip.Addr
|
||||
cached bool
|
||||
)
|
||||
c.saveFakeIPAccess.RLock()
|
||||
c.saveAccess.RLock()
|
||||
if !isIPv6 {
|
||||
cachedAddress, cached = c.saveAddress4[domain]
|
||||
} else {
|
||||
cachedAddress, cached = c.saveAddress6[domain]
|
||||
}
|
||||
c.saveFakeIPAccess.RUnlock()
|
||||
c.saveAccess.RUnlock()
|
||||
if cached {
|
||||
return cachedAddress, true
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
package cachefile
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/bbolt"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
)
|
||||
|
||||
var bucketRDRC = []byte("rdrc")
|
||||
|
||||
func (c *CacheFile) StoreRDRC() bool {
|
||||
return c.storeRDRC
|
||||
}
|
||||
|
||||
func (c *CacheFile) RDRCTimeout() time.Duration {
|
||||
return c.rdrcTimeout
|
||||
}
|
||||
|
||||
func (c *CacheFile) LoadRDRC(transportName string, qName string) (rejected bool) {
|
||||
c.saveRDRCAccess.RLock()
|
||||
rejected, cached := c.saveRDRC[saveRDRCCacheKey{transportName, qName}]
|
||||
c.saveRDRCAccess.RUnlock()
|
||||
if cached {
|
||||
return
|
||||
}
|
||||
var deleteCache bool
|
||||
err := c.DB.View(func(tx *bbolt.Tx) error {
|
||||
bucket := c.bucket(tx, bucketRDRC)
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
bucket = bucket.Bucket([]byte(transportName))
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
content := bucket.Get([]byte(qName))
|
||||
if content == nil {
|
||||
return nil
|
||||
}
|
||||
expiresAt := time.Unix(int64(binary.BigEndian.Uint64(content)), 0)
|
||||
if time.Now().After(expiresAt) {
|
||||
deleteCache = true
|
||||
return nil
|
||||
}
|
||||
rejected = true
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if deleteCache {
|
||||
c.DB.Update(func(tx *bbolt.Tx) error {
|
||||
bucket := c.bucket(tx, bucketRDRC)
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
bucket = bucket.Bucket([]byte(transportName))
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
return bucket.Delete([]byte(qName))
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *CacheFile) SaveRDRC(transportName string, qName string) error {
|
||||
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
||||
bucket, err := c.createBucket(tx, bucketRDRC)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bucket, err = bucket.CreateBucketIfNotExists([]byte(transportName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
expiresAt := buf.Get(8)
|
||||
defer buf.Put(expiresAt)
|
||||
binary.BigEndian.PutUint64(expiresAt, uint64(time.Now().Add(c.rdrcTimeout).Unix()))
|
||||
return bucket.Put([]byte(qName), expiresAt)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *CacheFile) SaveRDRCAsync(transportName string, qName string, logger logger.Logger) {
|
||||
saveKey := saveRDRCCacheKey{transportName, qName}
|
||||
c.saveRDRCAccess.Lock()
|
||||
c.saveRDRC[saveKey] = true
|
||||
c.saveRDRCAccess.Unlock()
|
||||
go func() {
|
||||
err := c.SaveRDRC(transportName, qName)
|
||||
if err != nil {
|
||||
logger.Warn("save RDRC: ", err)
|
||||
}
|
||||
c.saveRDRCAccess.Lock()
|
||||
delete(c.saveRDRC, saveKey)
|
||||
c.saveRDRCAccess.Unlock()
|
||||
}()
|
||||
}
|
||||
@@ -77,10 +77,6 @@ func (s *BoxService) Close() error {
|
||||
return s.instance.Close()
|
||||
}
|
||||
|
||||
func (s *BoxService) NeedWIFIState() bool {
|
||||
return s.instance.Router().NeedWIFIState()
|
||||
}
|
||||
|
||||
var (
|
||||
_ platform.Interface = (*platformInterfaceWrapper)(nil)
|
||||
_ log.PlatformWriter = (*platformInterfaceWrapper)(nil)
|
||||
|
||||
@@ -12,7 +12,7 @@ require (
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/gofrs/uuid/v5 v5.0.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240204152450-ca2dc33955c1
|
||||
github.com/libdns/alidns v1.0.3
|
||||
github.com/libdns/cloudflare v0.1.0
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
@@ -26,8 +26,8 @@ require (
|
||||
github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f
|
||||
github.com/sagernet/quic-go v0.41.0-beta.2
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.3.1-beta.1
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.5
|
||||
github.com/sagernet/sing v0.3.1-beta.2
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.4
|
||||
github.com/sagernet/sing-mux v0.2.0
|
||||
github.com/sagernet/sing-quic v0.1.9-beta.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||
@@ -48,7 +48,7 @@ require (
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||
google.golang.org/grpc v1.60.1
|
||||
google.golang.org/grpc v1.61.1
|
||||
google.golang.org/protobuf v1.32.0
|
||||
howett.net/plist v1.0.1
|
||||
)
|
||||
@@ -91,7 +91,7 @@ require (
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.2.1 // indirect
|
||||
|
||||
@@ -42,15 +42,15 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240204152450-ca2dc33955c1 h1:L3pm9Kf2G6gJVYawz2SrI5QnV1wzHYbqmKnSHHXJAb8=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240204152450-ca2dc33955c1/go.mod h1:izxuNQZeFrbx2nK2fAyN5iNUB34Fe9j0nK4PwLzAkKw=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
@@ -109,10 +109,10 @@ github.com/sagernet/quic-go v0.41.0-beta.2/go.mod h1:X10Mf9DVHuSEReOLov/XuflD13M
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||
github.com/sagernet/sing v0.3.1-beta.1 h1:5s4hUokrd58xgmiT2baXQJmZDUvjf7qzXXIqVbPTa3o=
|
||||
github.com/sagernet/sing v0.3.1-beta.1/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.5 h1:i2uS6fpIEjFyMFQ82PkCNdndtIfMOyC+n5vUKavMzFg=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.5/go.mod h1:IxOqfSb6Zt6UVCy8fJpDxb2XxqzHUytNqeOuJfaiLu8=
|
||||
github.com/sagernet/sing v0.3.1-beta.2 h1:QEbBAXStZ/l4fPKbTkJZZrR/hPDOstEsZ5B9JbvkZO4=
|
||||
github.com/sagernet/sing v0.3.1-beta.2/go.mod h1:qHySJ7u8po9DABtMYEkNBcOumx7ZZJf/fbv2sfTkNHE=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.4 h1:lzfESvGHP0xVNneuVnOdhueZhi9ekg1TruBF2UN2epU=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.4/go.mod h1:IxOqfSb6Zt6UVCy8fJpDxb2XxqzHUytNqeOuJfaiLu8=
|
||||
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
||||
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-quic v0.1.9-beta.1 h1:rCmgLUq2d4EA643EAvjbfUYYVMPCss0GpmS4pJCT2Lw=
|
||||
@@ -206,10 +206,10 @@ golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
|
||||
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
|
||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
|
||||
google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY=
|
||||
google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
|
||||
@@ -8,12 +8,10 @@ type ExperimentalOptions struct {
|
||||
}
|
||||
|
||||
type CacheFileOptions struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
CacheID string `json:"cache_id,omitempty"`
|
||||
StoreFakeIP bool `json:"store_fakeip,omitempty"`
|
||||
StoreRDRC bool `json:"store_rdrc,omitempty"`
|
||||
RDRCTimeout Duration `json:"rdrc_timeout,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
CacheID string `json:"cache_id,omitempty"`
|
||||
StoreFakeIP bool `json:"store_fakeip,omitempty"`
|
||||
}
|
||||
|
||||
type ClashAPIOptions struct {
|
||||
|
||||
+7
-26
@@ -136,17 +136,7 @@ func NewRouter(
|
||||
DisableCache: dnsOptions.DNSClientOptions.DisableCache,
|
||||
DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
|
||||
IndependentCache: dnsOptions.DNSClientOptions.IndependentCache,
|
||||
RDRC: func() dns.RDRCStore {
|
||||
cacheFile := service.FromContext[adapter.CacheFile](ctx)
|
||||
if cacheFile == nil {
|
||||
return nil
|
||||
}
|
||||
if !cacheFile.StoreRDRC() {
|
||||
return nil
|
||||
}
|
||||
return cacheFile
|
||||
},
|
||||
Logger: router.dnsLogger,
|
||||
Logger: router.dnsLogger,
|
||||
})
|
||||
for i, ruleOptions := range options.Rules {
|
||||
routeRule, err := NewRule(router, router.logger, ruleOptions, true)
|
||||
@@ -588,12 +578,13 @@ func (r *Router) Start() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needWIFIStateFromRuleSet || r.needWIFIState) && r.platformInterface != nil {
|
||||
if needWIFIStateFromRuleSet || r.needWIFIState {
|
||||
monitor.Start("initialize WIFI state")
|
||||
r.needWIFIState = true
|
||||
r.interfaceMonitor.RegisterCallback(func(_ int) {
|
||||
r.updateWIFIState()
|
||||
})
|
||||
if r.platformInterface != nil && r.interfaceMonitor != nil {
|
||||
r.interfaceMonitor.RegisterCallback(func(_ int) {
|
||||
r.updateWIFIState()
|
||||
})
|
||||
}
|
||||
r.updateWIFIState()
|
||||
monitor.Finish()
|
||||
}
|
||||
@@ -606,11 +597,6 @@ func (r *Router) Start() error {
|
||||
return E.Cause(err, "initialize rule[", i, "]")
|
||||
}
|
||||
}
|
||||
|
||||
monitor.Start("initialize DNS client")
|
||||
r.dnsClient.Start()
|
||||
monitor.Finish()
|
||||
|
||||
for i, rule := range r.dnsRules {
|
||||
monitor.Start("initialize DNS rule[", i, "]")
|
||||
err := rule.Start()
|
||||
@@ -748,11 +734,6 @@ func (r *Router) RuleSet(tag string) (adapter.RuleSet, bool) {
|
||||
return ruleSet, loaded
|
||||
}
|
||||
|
||||
func (r *Router) NeedWIFIState() bool {
|
||||
return r.needWIFIState
|
||||
|
||||
}
|
||||
|
||||
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||
if r.pauseManager.IsDevicePaused() {
|
||||
return E.New("reject connection to ", metadata.Destination, " while device paused")
|
||||
|
||||
+10
-21
@@ -139,9 +139,7 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||
}
|
||||
cancel()
|
||||
if err != nil {
|
||||
if errors.Is(err, dns.ErrResponseRejectedCached) {
|
||||
r.dnsLogger.DebugContext(ctx, E.Cause(err, "response rejected for ", formatQuestion(message.Question[0].String())), " (cached)")
|
||||
} else if errors.Is(err, dns.ErrResponseRejected) {
|
||||
if errors.Is(err, dns.ErrResponseRejected) {
|
||||
r.dnsLogger.DebugContext(ctx, E.Cause(err, "response rejected for ", formatQuestion(message.Question[0].String())))
|
||||
} else if len(message.Question) > 0 {
|
||||
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", formatQuestion(message.Question[0].String())))
|
||||
@@ -168,15 +166,6 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||
}
|
||||
|
||||
func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
||||
var (
|
||||
responseAddrs []netip.Addr
|
||||
cached bool
|
||||
err error
|
||||
)
|
||||
responseAddrs, cached = r.dnsClient.LookupCache(ctx, domain, strategy)
|
||||
if cached {
|
||||
return responseAddrs, nil
|
||||
}
|
||||
r.dnsLogger.DebugContext(ctx, "lookup domain ", domain)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Domain = domain
|
||||
@@ -185,6 +174,8 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
|
||||
transportStrategy dns.DomainStrategy
|
||||
rule adapter.DNSRule
|
||||
ruleIndex int
|
||||
resultAddrs []netip.Addr
|
||||
err error
|
||||
)
|
||||
ruleIndex = -1
|
||||
for {
|
||||
@@ -202,24 +193,22 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
|
||||
dnsCtx, cancel = context.WithTimeout(dnsCtx, C.DNSTimeout)
|
||||
if rule != nil && rule.WithAddressLimit() {
|
||||
addressLimit = true
|
||||
responseAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, strategy, func(responseAddrs []netip.Addr) bool {
|
||||
resultAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, strategy, func(responseAddrs []netip.Addr) bool {
|
||||
metadata.DestinationAddresses = responseAddrs
|
||||
return rule.MatchAddressLimit(metadata)
|
||||
})
|
||||
} else {
|
||||
addressLimit = false
|
||||
responseAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, strategy)
|
||||
resultAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, strategy)
|
||||
}
|
||||
cancel()
|
||||
if err != nil {
|
||||
if errors.Is(err, dns.ErrResponseRejectedCached) {
|
||||
r.dnsLogger.DebugContext(ctx, "response rejected for ", domain, " (cached)")
|
||||
} else if errors.Is(err, dns.ErrResponseRejected) {
|
||||
if errors.Is(err, dns.ErrResponseRejected) {
|
||||
r.dnsLogger.DebugContext(ctx, "response rejected for ", domain)
|
||||
} else {
|
||||
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "lookup failed for ", domain))
|
||||
}
|
||||
} else if len(responseAddrs) == 0 {
|
||||
} else if len(resultAddrs) == 0 {
|
||||
r.dnsLogger.ErrorContext(ctx, "lookup failed for ", domain, ": empty result")
|
||||
err = dns.RCodeNameError
|
||||
}
|
||||
@@ -227,10 +216,10 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(responseAddrs) > 0 {
|
||||
r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(responseAddrs), " "))
|
||||
if len(resultAddrs) > 0 {
|
||||
r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(resultAddrs), " "))
|
||||
}
|
||||
return responseAddrs, err
|
||||
return resultAddrs, err
|
||||
}
|
||||
|
||||
func (r *Router) LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error) {
|
||||
|
||||
@@ -58,7 +58,6 @@ func NewTransport(options dns.TransportOptions) (*Transport, error) {
|
||||
return nil, E.New("missing router in context")
|
||||
}
|
||||
transport := &Transport{
|
||||
options: options,
|
||||
router: router,
|
||||
interfaceName: linkURL.Host,
|
||||
autoInterface: linkURL.Host == "auto",
|
||||
|
||||
Reference in New Issue
Block a user