Compare commits

..
Author SHA1 Message Date
世界 7320ec4285 documentation: Bump version 2024-02-14 13:10:09 +08:00
世界 be5359cd58 Update dependencies 2024-02-14 13:10:06 +08:00
世界 c84d058bba Update gVisor to 20240206.0 2024-02-14 13:10:02 +08:00
世界 a2590e861c Update quic-go to v0.41.0 2024-02-14 12:57:55 +08:00
世界 8ca484948c documentation: Add description for client_subnet options 2024-02-14 12:57:44 +08:00
世界 e1d23600e7 documentation: Add description for address filter DNS rules 2024-02-14 12:57:44 +08:00
世界 f56945fdb7 Fixed order for Clash modes 2024-02-14 12:55:59 +08:00
世界 c84dfeabaa Add support for client-subnet DNS options 2024-02-14 12:55:55 +08:00
世界 09e458e9e8 Add address filter support for DNS rules 2024-02-14 12:55:38 +08:00
世界 82d006b7e8 Fix timezone for Android and iOS 2024-02-14 12:55:35 +08:00
世界 eac04117dc Improve domain suffix match behavior
For historical reasons, sing-box's `domain_suffix` rule matches literal prefixes instead of the same as other projects.

This change modifies the behavior of `domain_suffix`: If the rule value is prefixed with `.`,
the behavior is unchanged, otherwise it matches `(domain|.+\.domain)` instead.
2024-02-14 12:55:02 +08:00
世界 b72da8ca94 Remove PROCESS_NAME_NATIVE dwFlag in process query output
The `process_path` rule of sing-box is inherited from Clash,
the original code uses the local system's path format (e.g. `\Device\HarddiskVolume1\folder\program.exe`),
but when the device has multiple disks, the HarddiskVolume serial number is not stable.

This change make QueryFullProcessImageNameW output a Win32 path (such as `C:\folder\program.exe`),
which will disrupt the existing `process_path` use cases in Windows.
2024-02-10 23:49:52 +08:00
世界 fcd28dd387 badtls: Support uTLS and TLS ECH for read waiter 2024-02-10 23:49:52 +08:00
23 changed files with 69 additions and 346 deletions
-14
View File
@@ -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"
-6
View File
@@ -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
+1 -2
View File
@@ -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
-4
View File
@@ -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
-2
View File
@@ -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
+10 -23
View File
@@ -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))
}
-14
View File
@@ -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
+1 -5
View File
@@ -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
+1 -5
View File
@@ -337,13 +337,9 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
仅对IP地址请求生效。 当查询结果与地址筛选规则项不匹配时,将跳过当前规则。
!!! info ""
引用的规则集中的 `ip_cidr` 项也作为地址筛选字段生效。
!!! note ""
启用 `experimental.cache_file.store_rdrc` 以缓存结果。
引用的规则集中的 `ip_cidr` 项也作为地址筛选字段生效。
#### geoip
+2 -30
View File
@@ -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`。
+7 -27
View File
@@ -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),
}
}
+9 -9
View File
@@ -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
}
-101
View File
@@ -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()
}()
}
-4
View File
@@ -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)
+5 -5
View File
@@ -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
+11 -11
View File
@@ -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=
+4 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
-1
View File
@@ -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",