mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-10-21 00:34:24 +00:00
Compare commits
48
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e483c909b4 | ||
|
|
d9579c26ee | ||
|
|
48d3021b2c | ||
|
|
ce0fcd5c8b | ||
|
|
d9d0a2373a | ||
|
|
0c754505f7 | ||
|
|
606ff668da | ||
|
|
f43703801b | ||
|
|
1ed8f3a8d3 | ||
|
|
60fc913dc3 | ||
|
|
be8ee370ac | ||
|
|
0a9bf97438 | ||
|
|
74de437bfb | ||
|
|
c385e7c137 | ||
|
|
01291d16e0 | ||
|
|
11a448b52d | ||
|
|
22bda86bbf | ||
|
|
04cc343b2e | ||
|
|
093e539d3d | ||
|
|
5821b974bd | ||
|
|
8ce40f77b4 | ||
|
|
b45cb0763e | ||
|
|
48d102a0ab | ||
|
|
6a5943f4ce | ||
|
|
c9f9d9ee1c | ||
|
|
f3bf440c91 | ||
|
|
292fcde876 | ||
|
|
53e227a318 | ||
|
|
65cb225a2c | ||
|
|
7819f13489 | ||
|
|
f2780d0713 | ||
|
|
72239dcbd3 | ||
|
|
daf38a84e1 | ||
|
|
f2ddc5883b | ||
|
|
0437ac512b | ||
|
|
d297ad4c56 | ||
|
|
6823670f3d | ||
|
|
4a611eddf4 | ||
|
|
f12a294fb7 | ||
|
|
040a188c66 | ||
|
|
7ed10b35d0 | ||
|
|
afd341adfd | ||
|
|
7d26bac5ac | ||
|
|
63d8f6dc1c | ||
|
|
15cc3b85eb | ||
|
|
5a1c59ca88 | ||
|
|
7686503df8 | ||
|
|
96a8de9548 |
@@ -144,7 +144,7 @@ jobs:
|
||||
~/go/go1.20.14
|
||||
key: go120
|
||||
- name: Setup legacy Go
|
||||
if: matrix.require_legacy_go && steps.cache-legacy-go.outputs.cache-hit != 'true'
|
||||
if: matrix.require_legacy_go == 'true' && steps.cache-legacy-go.outputs.cache-hit != 'true'
|
||||
run: |-
|
||||
wget https://dl.google.com/go/go1.20.14.linux-amd64.tar.gz
|
||||
tar -xzf go1.20.14.linux-amd64.tar.gz
|
||||
@@ -159,7 +159,7 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser-pro
|
||||
version: 2.5.1
|
||||
version: latest
|
||||
install-only: true
|
||||
- name: Extract signing key
|
||||
run: |-
|
||||
@@ -224,7 +224,7 @@ jobs:
|
||||
id: setup-ndk
|
||||
uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
ndk-version: r28-beta3
|
||||
ndk-version: r28-beta2
|
||||
- name: Setup OpenJDK
|
||||
run: |-
|
||||
sudo apt update && sudo apt install -y openjdk-17-jdk-headless
|
||||
@@ -256,7 +256,8 @@ jobs:
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: gradle-${{ hashFiles('**/*.gradle') }}
|
||||
- name: Build
|
||||
- name: Build release
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |-
|
||||
go run -v ./cmd/internal/update_android_version --ci
|
||||
mkdir clients/android/app/libs
|
||||
@@ -267,18 +268,47 @@ jobs:
|
||||
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
|
||||
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
|
||||
- name: Prepare upload
|
||||
- name: Build debug
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: |-
|
||||
go run -v ./cmd/internal/update_android_version --ci
|
||||
mkdir clients/android/app/libs
|
||||
cp libbox.aar clients/android/app/libs
|
||||
cd clients/android
|
||||
./gradlew :app:assemblePlayRelease
|
||||
env:
|
||||
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
|
||||
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
|
||||
- name: Prepare release upload
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |-
|
||||
mkdir -p dist/release
|
||||
cp clients/android/app/build/outputs/apk/play/release/*.apk dist/release
|
||||
cp clients/android/app/build/outputs/apk/other/release/*-universal.apk dist/release
|
||||
- name: Prepare debug upload
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: |-
|
||||
mkdir -p dist/release
|
||||
cp clients/android/app/build/outputs/apk/play/release/*.apk dist/release
|
||||
- name: Upload artifact
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: binary-android-apks
|
||||
path: 'dist'
|
||||
- name: Upload debug apk (arm64-v8a)
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "SFA-${{ needs.calculate_version.outputs.version }}-arm64-v8a.apk"
|
||||
path: 'dist/release/*-arm64-v8a.apk'
|
||||
- name: Upload debug apk (universal)
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "SFA-${{ needs.calculate_version.outputs.version }}-universal.apk"
|
||||
path: 'dist/release/*-universal.apk'
|
||||
publish_android:
|
||||
name: Publish Android
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.build == 'publish-android'
|
||||
@@ -299,7 +329,7 @@ jobs:
|
||||
id: setup-ndk
|
||||
uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
ndk-version: r28-beta3
|
||||
ndk-version: r28-beta2
|
||||
- name: Setup OpenJDK
|
||||
run: |-
|
||||
sudo apt update && sudo apt install -y openjdk-17-jdk-headless
|
||||
@@ -548,7 +578,7 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser-pro
|
||||
version: 2.5.1
|
||||
version: latest
|
||||
install-only: true
|
||||
- name: Cache ghr
|
||||
uses: actions/cache@v4
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ builds:
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GOROOT={{ .Env.GOPATH }}/go1.20.14
|
||||
tool: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
|
||||
gobinary: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
|
||||
targets:
|
||||
- windows_amd64_v1
|
||||
- windows_386
|
||||
|
||||
@@ -399,7 +399,7 @@ func (s *Box) Close() error {
|
||||
close(s.done)
|
||||
}
|
||||
err := common.Close(
|
||||
s.inbound, s.outbound, s.endpoint, s.router, s.connection, s.network,
|
||||
s.inbound, s.outbound, s.router, s.connection, s.network,
|
||||
)
|
||||
for _, lifecycleService := range s.services {
|
||||
err = E.Append(err, lifecycleService.Close(), func(err error) error {
|
||||
|
||||
+1
-1
Submodule clients/android updated: 599d8cecac...e1049099a0
+1
-1
Submodule clients/apple updated: e43e3a3f64...3d889ae017
@@ -48,7 +48,7 @@ func FindSDK() {
|
||||
}
|
||||
|
||||
func findNDK() bool {
|
||||
const fixedVersion = "28.0.12916984"
|
||||
const fixedVersion = "28.0.12674087"
|
||||
const versionFile = "source.properties"
|
||||
if fixedPath := filepath.Join(androidSDKPath, "ndk", fixedVersion); rw.IsFile(filepath.Join(fixedPath, versionFile)) {
|
||||
androidNDKPath = fixedPath
|
||||
|
||||
@@ -61,15 +61,14 @@ func upgradeRuleSet(sourcePath string) error {
|
||||
log.Info("already up-to-date")
|
||||
return nil
|
||||
}
|
||||
plainRuleSetCompat.Options, err = plainRuleSetCompat.Upgrade()
|
||||
plainRuleSet, err := plainRuleSetCompat.Upgrade()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
plainRuleSetCompat.Version = C.RuleSetVersionCurrent
|
||||
buffer := new(bytes.Buffer)
|
||||
encoder := json.NewEncoder(buffer)
|
||||
encoder.SetIndent("", " ")
|
||||
err = encoder.Encode(plainRuleSetCompat)
|
||||
err = encoder.Encode(plainRuleSet)
|
||||
if err != nil {
|
||||
return E.Cause(err, "encode config")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/common/settings"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
@@ -57,7 +58,7 @@ func syncTime() error {
|
||||
return err
|
||||
}
|
||||
if commandSyncTimeWrite {
|
||||
err = ntp.SetSystemTime(response.Time)
|
||||
err = settings.SetSystemTime(response.Time)
|
||||
if err != nil {
|
||||
return E.Cause(err, "write time to system")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//go:build !(windows || linux || darwin)
|
||||
|
||||
package settings
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SetSystemTime(nowTime time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//go:build linux || darwin
|
||||
|
||||
package settings
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func SetSystemTime(nowTime time.Time) error {
|
||||
timeVal := unix.NsecToTimeval(nowTime.UnixNano())
|
||||
return unix.Settimeofday(&timeVal)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func SetSystemTime(nowTime time.Time) error {
|
||||
var systemTime windows.Systemtime
|
||||
systemTime.Year = uint16(nowTime.Year())
|
||||
systemTime.Month = uint16(nowTime.Month())
|
||||
systemTime.Day = uint16(nowTime.Day())
|
||||
systemTime.Hour = uint16(nowTime.Hour())
|
||||
systemTime.Minute = uint16(nowTime.Minute())
|
||||
systemTime.Second = uint16(nowTime.Second())
|
||||
systemTime.Milliseconds = uint16(nowTime.UnixMilli() - nowTime.Unix()*1000)
|
||||
|
||||
dllKernel32 := windows.NewLazySystemDLL("kernel32.dll")
|
||||
proc := dllKernel32.NewProc("SetSystemTime")
|
||||
|
||||
_, _, err := proc.Call(
|
||||
uintptr(unsafe.Pointer(&systemTime)),
|
||||
)
|
||||
|
||||
if err != nil && err.Error() != "The operation completed successfully." {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func (e *RealityClientConfig) ClientHandshake(ctx context.Context, conn net.Conn
|
||||
return nil, E.New("reality verification failed")
|
||||
}
|
||||
|
||||
return &realityClientConnWrapper{uConn}, nil
|
||||
return &utlsConnWrapper{uConn}, nil
|
||||
}
|
||||
|
||||
func realityClientFallback(uConn net.Conn, serverName string, fingerprint utls.ClientHelloID) {
|
||||
@@ -249,36 +249,3 @@ func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type realityClientConnWrapper struct {
|
||||
*utls.UConn
|
||||
}
|
||||
|
||||
func (c *realityClientConnWrapper) ConnectionState() tls.ConnectionState {
|
||||
state := c.Conn.ConnectionState()
|
||||
//nolint:staticcheck
|
||||
return tls.ConnectionState{
|
||||
Version: state.Version,
|
||||
HandshakeComplete: state.HandshakeComplete,
|
||||
DidResume: state.DidResume,
|
||||
CipherSuite: state.CipherSuite,
|
||||
NegotiatedProtocol: state.NegotiatedProtocol,
|
||||
NegotiatedProtocolIsMutual: state.NegotiatedProtocolIsMutual,
|
||||
ServerName: state.ServerName,
|
||||
PeerCertificates: state.PeerCertificates,
|
||||
VerifiedChains: state.VerifiedChains,
|
||||
SignedCertificateTimestamps: state.SignedCertificateTimestamps,
|
||||
OCSPResponse: state.OCSPResponse,
|
||||
TLSUnique: state.TLSUnique,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *realityClientConnWrapper) Upstream() any {
|
||||
return c.UConn
|
||||
}
|
||||
|
||||
// Due to low implementation quality, the reality server intercepted half close and caused memory leaks.
|
||||
// We fixed it by calling Close() directly.
|
||||
func (c *realityClientConnWrapper) CloseWrite() error {
|
||||
return c.Close()
|
||||
}
|
||||
|
||||
@@ -194,9 +194,3 @@ func (c *realityConnWrapper) ConnectionState() ConnectionState {
|
||||
func (c *realityConnWrapper) Upstream() any {
|
||||
return c.Conn
|
||||
}
|
||||
|
||||
// Due to low implementation quality, the reality server intercepted half close and caused memory leaks.
|
||||
// We fixed it by calling Close() directly.
|
||||
func (c *realityConnWrapper) CloseWrite() error {
|
||||
return c.Close()
|
||||
}
|
||||
|
||||
@@ -2,130 +2,6 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
### 1.11.0
|
||||
|
||||
Important changes since 1.10:
|
||||
|
||||
* Introducing rule actions **1**
|
||||
* Improve tun compatibility **3**
|
||||
* Merge route options to route actions **4**
|
||||
* Add `network_type`, `network_is_expensive` and `network_is_constrainted` rule items **5**
|
||||
* Add multi network dialing **6**
|
||||
* Add `cache_capacity` DNS option **7**
|
||||
* Add `override_address` and `override_port` route options **8**
|
||||
* Upgrade WireGuard outbound to endpoint **9**
|
||||
* Add UDP GSO support for WireGuard
|
||||
* Make GSO adaptive **10**
|
||||
* Add UDP timeout route option **11**
|
||||
* Add more masquerade options for hysteria2 **12**
|
||||
* Add `rule-set merge` command
|
||||
* Add port hopping support for Hysteria2 **13**
|
||||
* Hysteria2 `ignore_client_bandwidth` behavior update **14**
|
||||
|
||||
**1**:
|
||||
|
||||
New rule actions replace legacy inbound fields and special outbound fields,
|
||||
and can be used for pre-matching **2**.
|
||||
|
||||
See [Rule](/configuration/route/rule/),
|
||||
[Rule Action](/configuration/route/rule_action/),
|
||||
[DNS Rule](/configuration/dns/rule/) and
|
||||
[DNS Rule Action](/configuration/dns/rule_action/).
|
||||
|
||||
For migration, see
|
||||
[Migrate legacy special outbounds to rule actions](/migration/#migrate-legacy-special-outbounds-to-rule-actions),
|
||||
[Migrate legacy inbound fields to rule actions](/migration/#migrate-legacy-inbound-fields-to-rule-actions)
|
||||
and [Migrate legacy DNS route options to rule actions](/migration/#migrate-legacy-dns-route-options-to-rule-actions).
|
||||
|
||||
**2**:
|
||||
|
||||
Similar to Surge's pre-matching.
|
||||
|
||||
Specifically, new rule actions allow you to reject connections with
|
||||
TCP RST (for TCP connections) and ICMP port unreachable (for UDP packets)
|
||||
before connection established to improve tun's compatibility.
|
||||
|
||||
See [Rule Action](/configuration/route/rule_action/).
|
||||
|
||||
**3**:
|
||||
|
||||
When `gvisor` tun stack is enabled, even if the request passes routing,
|
||||
if the outbound connection establishment fails,
|
||||
the connection still does not need to be established and a TCP RST is replied.
|
||||
|
||||
**4**:
|
||||
|
||||
Route options in DNS route actions will no longer be considered deprecated,
|
||||
see [DNS Route Action](/configuration/dns/rule_action/).
|
||||
|
||||
Also, now `udp_disable_domain_unmapping` and `udp_connect` can also be configured in route action,
|
||||
see [Route Action](/configuration/route/rule_action/).
|
||||
|
||||
**5**:
|
||||
|
||||
When using in graphical clients, new routing rule items allow you to match on
|
||||
network type (WIFI, cellular, etc.), whether the network is expensive, and whether Low Data Mode is enabled.
|
||||
|
||||
See [Route Rule](/configuration/route/rule/), [DNS Route Rule](/configuration/dns/rule/)
|
||||
and [Headless Rule](/configuration/rule-set/headless-rule/).
|
||||
|
||||
**6**:
|
||||
|
||||
Similar to Surge's strategy.
|
||||
|
||||
New options allow you to connect using multiple network interfaces,
|
||||
prefer or only use one type of interface,
|
||||
and configure a timeout to fallback to other interfaces.
|
||||
|
||||
See [Dial Fields](/configuration/shared/dial/#network_strategy),
|
||||
[Rule Action](/configuration/route/rule_action/#network_strategy)
|
||||
and [Route](/configuration/route/#default_network_strategy).
|
||||
|
||||
**7**:
|
||||
|
||||
See [DNS](/configuration/dns/#cache_capacity).
|
||||
|
||||
**8**:
|
||||
|
||||
See [Rule Action](/configuration/route/#override_address) and
|
||||
[Migrate destination override fields to route options](/migration/#migrate-destination-override-fields-to-route-options).
|
||||
|
||||
**9**:
|
||||
|
||||
The new WireGuard endpoint combines inbound and outbound capabilities,
|
||||
and the old outbound will be removed in sing-box 1.13.0.
|
||||
|
||||
See [Endpoint](/configuration/endpoint/), [WireGuard Endpoint](/configuration/endpoint/wireguard/)
|
||||
and [Migrate WireGuard outbound fields to route options](/migration/#migrate-wireguard-outbound-to-endpoint).
|
||||
|
||||
**10**:
|
||||
|
||||
For WireGuard outbound and endpoint, GSO will be automatically enabled when available,
|
||||
see [WireGuard Outbound](/configuration/outbound/wireguard/#gso).
|
||||
|
||||
For TUN, GSO has been removed,
|
||||
see [Deprecated](/deprecated/#gso-option-in-tun).
|
||||
|
||||
**11**:
|
||||
|
||||
See [Rule Action](/configuration/route/rule_action/#udp_timeout).
|
||||
|
||||
**12**:
|
||||
|
||||
See [Hysteria2](/configuration/inbound/hysteria2/#masquerade).
|
||||
|
||||
**13**:
|
||||
|
||||
See [Hysteria2](/configuration/outbound/hysteria2/).
|
||||
|
||||
**14**:
|
||||
|
||||
When `up_mbps` and `down_mbps` are set, `ignore_client_bandwidth` instead denies clients from using BBR CC.
|
||||
|
||||
### 1.10.7
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.11.0-beta.20
|
||||
|
||||
* Hysteria2 `ignore_client_bandwidth` behavior update **1**
|
||||
|
||||
@@ -4,7 +4,7 @@ icon: material/delete-clock
|
||||
|
||||
!!! failure "已在 sing-box 1.11.0 废弃"
|
||||
|
||||
WireGuard 出站已被弃用,且将在 sing-box 1.13.0 中被移除,参阅 [迁移指南](/migration/#migrate-wireguard-outbound-to-endpoint)。
|
||||
WireGuard 出站已被启用,且将在 sing-box 1.13.0 中被移除,参阅 [迁移指南](/migration/#migrate-wireguard-outbound-to-endpoint)。
|
||||
|
||||
!!! quote "sing-box 1.11.0 中的更改"
|
||||
|
||||
|
||||
@@ -31,45 +31,6 @@ Tag of target outbound.
|
||||
|
||||
See `route-options` fields below.
|
||||
|
||||
### reject
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "reject",
|
||||
"method": "default", // default
|
||||
"no_drop": false
|
||||
}
|
||||
```
|
||||
|
||||
`reject` reject connections
|
||||
|
||||
The specified method is used for reject tun connections if `sniff` action has not been performed yet.
|
||||
|
||||
For non-tun connections and already established connections, will just be closed.
|
||||
|
||||
#### method
|
||||
|
||||
- `default`: Reply with TCP RST for TCP connections, and ICMP port unreachable for UDP packets.
|
||||
- `drop`: Drop packets.
|
||||
|
||||
#### no_drop
|
||||
|
||||
If not enabled, `method` will be temporarily overwritten to `drop` after 50 triggers in 30s.
|
||||
|
||||
Not available when `method` is set to drop.
|
||||
|
||||
### hijack-dns
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "hijack-dns"
|
||||
}
|
||||
```
|
||||
|
||||
`hijack-dns` hijack DNS requests to the sing-box DNS module.
|
||||
|
||||
## Non-final actions
|
||||
|
||||
### route-options
|
||||
|
||||
```json
|
||||
@@ -148,6 +109,45 @@ If no protocol is sniffed, the following ports will be recognized as protocols b
|
||||
| 443 | `quic` |
|
||||
| 3478 | `stun` |
|
||||
|
||||
### reject
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "reject",
|
||||
"method": "default", // default
|
||||
"no_drop": false
|
||||
}
|
||||
```
|
||||
|
||||
`reject` reject connections
|
||||
|
||||
The specified method is used for reject tun connections if `sniff` action has not been performed yet.
|
||||
|
||||
For non-tun connections and already established connections, will just be closed.
|
||||
|
||||
#### method
|
||||
|
||||
- `default`: Reply with TCP RST for TCP connections, and ICMP port unreachable for UDP packets.
|
||||
- `drop`: Drop packets.
|
||||
|
||||
#### no_drop
|
||||
|
||||
If not enabled, `method` will be temporarily overwritten to `drop` after 50 triggers in 30s.
|
||||
|
||||
Not available when `method` is set to drop.
|
||||
|
||||
### hijack-dns
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "hijack-dns"
|
||||
}
|
||||
```
|
||||
|
||||
`hijack-dns` hijack DNS requests to the sing-box DNS module.
|
||||
|
||||
## Non-final actions
|
||||
|
||||
### sniff
|
||||
|
||||
```json
|
||||
|
||||
@@ -27,45 +27,6 @@ icon: material/new-box
|
||||
|
||||
参阅下方的 `route-options` 字段。
|
||||
|
||||
### reject
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "reject",
|
||||
"method": "default", // 默认
|
||||
"no_drop": false
|
||||
}
|
||||
```
|
||||
|
||||
`reject` 拒绝连接。
|
||||
|
||||
如果尚未执行 `sniff` 操作,则将使用指定方法拒绝 tun 连接。
|
||||
|
||||
对于非 tun 连接和已建立的连接,将直接关闭。
|
||||
|
||||
#### method
|
||||
|
||||
- `default`: 对于 TCP 连接回复 RST,对于 UDP 包回复 ICMP 端口不可达。
|
||||
- `drop`: 丢弃数据包。
|
||||
|
||||
#### no_drop
|
||||
|
||||
如果未启用,则 30 秒内触发 50 次后,`method` 将被暂时覆盖为 `drop`。
|
||||
|
||||
当 `method` 设为 `drop` 时不可用。
|
||||
|
||||
### hijack-dns
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "hijack-dns"
|
||||
}
|
||||
```
|
||||
|
||||
`hijack-dns` 劫持 DNS 请求至 sing-box DNS 模块。
|
||||
|
||||
## 非最终动作
|
||||
|
||||
### route-options
|
||||
|
||||
```json
|
||||
@@ -146,6 +107,45 @@ UDP 连接超时时间。
|
||||
| 443 | `quic` |
|
||||
| 3478 | `stun` |
|
||||
|
||||
### reject
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "reject",
|
||||
"method": "default", // 默认
|
||||
"no_drop": false
|
||||
}
|
||||
```
|
||||
|
||||
`reject` 拒绝连接。
|
||||
|
||||
如果尚未执行 `sniff` 操作,则将使用指定方法拒绝 tun 连接。
|
||||
|
||||
对于非 tun 连接和已建立的连接,将直接关闭。
|
||||
|
||||
#### method
|
||||
|
||||
- `default`: 对于 TCP 连接回复 RST,对于 UDP 包回复 ICMP 端口不可达。
|
||||
- `drop`: 丢弃数据包。
|
||||
|
||||
#### no_drop
|
||||
|
||||
如果未启用,则 30 秒内触发 50 次后,`method` 将被暂时覆盖为 `drop`。
|
||||
|
||||
当 `method` 设为 `drop` 时不可用。
|
||||
|
||||
### hijack-dns
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "hijack-dns"
|
||||
}
|
||||
```
|
||||
|
||||
`hijack-dns` 劫持 DNS 请求至 sing-box DNS 模块。
|
||||
|
||||
## 非最终动作
|
||||
|
||||
### sniff
|
||||
|
||||
```json
|
||||
|
||||
@@ -66,6 +66,10 @@ func (s *platformInterfaceStub) OpenTun(options *tun.Options, platformOptions op
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) UpdateRouteOptions(options *tun.Options, platformInterface option.TunPlatformOptions) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) UsePlatformDefaultInterfaceMonitor() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ type PlatformInterface interface {
|
||||
UsePlatformAutoDetectInterfaceControl() bool
|
||||
AutoDetectInterfaceControl(fd int32) error
|
||||
OpenTun(options TunOptions) (int32, error)
|
||||
UpdateRouteOptions(options TunOptions) error
|
||||
WriteLog(message string)
|
||||
UseProcFS() bool
|
||||
FindConnectionOwner(ipProtocol int32, sourceAddress string, sourcePort int32, destinationAddress string, destinationPort int32) (int32, error)
|
||||
|
||||
@@ -13,6 +13,7 @@ type Interface interface {
|
||||
UsePlatformAutoDetectInterfaceControl() bool
|
||||
AutoDetectInterfaceControl(fd int) error
|
||||
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
||||
UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error
|
||||
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
|
||||
Interfaces() ([]adapter.NetworkInterface, error)
|
||||
UnderNetworkExtension() bool
|
||||
|
||||
@@ -174,6 +174,20 @@ func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions
|
||||
return tun.New(*options)
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error {
|
||||
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
|
||||
return E.New("android: unsupported uid options")
|
||||
}
|
||||
if len(options.IncludeAndroidUser) > 0 {
|
||||
return E.New("android: unsupported android_user option")
|
||||
}
|
||||
routeRanges, err := options.BuildAutoRouteRanges(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return w.iif.UpdateRouteOptions(&tunOptions{options, routeRanges, platformOptions})
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor {
|
||||
return &platformDefaultInterfaceMonitor{
|
||||
platformInterfaceWrapper: w,
|
||||
|
||||
@@ -26,14 +26,14 @@ require (
|
||||
github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff
|
||||
github.com/sagernet/quic-go v0.48.2-beta.1
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.6.0-beta.12
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.2
|
||||
github.com/sagernet/sing v0.6.0-beta.9
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.1
|
||||
github.com/sagernet/sing-mux v0.3.0-alpha.1
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.4
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.3
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.8
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.7
|
||||
github.com/sagernet/sing-vmess v0.2.0-beta.2
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||
github.com/sagernet/utls v1.6.7
|
||||
|
||||
@@ -119,22 +119,22 @@ github.com/sagernet/quic-go v0.48.2-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/
|
||||
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.6.0-beta.12 h1:2DnTJcvypK3/PM/8JjmgG8wVK48gdcpRwU98c4J/a7s=
|
||||
github.com/sagernet/sing v0.6.0-beta.12/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.2 h1:HW94bUEp7K/vf5DlYz646LTZevQtJ0250jZa/UZRlbY=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.2/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
||||
github.com/sagernet/sing v0.6.0-beta.9 h1:P8lKa5hN53fRNAVCIKy5cWd6/kLO5c4slhdsfehSmHs=
|
||||
github.com/sagernet/sing v0.6.0-beta.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.1 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
||||
github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg=
|
||||
github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.4 h1:kKiMLGaxvVLDCSvCMYo4PtWd1xU6FTL7xvUAQfXO09g=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.4/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.3/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0=
|
||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.8 h1:GFNt/w8r1v30zC/hfCytk8C9+N/f1DfvosFXJkyJlrw=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.8/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.7 h1:FCSX8oGBqb0H57AAvfGeeH/jMGYWCOg6XWkN/oeES+0=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||
github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs=
|
||||
github.com/sagernet/sing-vmess v0.2.0-beta.2/go.mod h1:HGhf9XUdeE2iOWrX0hQNFgXPbKyGlzpeYFyX0c/pykk=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
|
||||
@@ -74,7 +74,6 @@ func (m *Hysteria2Masquerade) UnmarshalJSON(bytes []byte) error {
|
||||
default:
|
||||
return E.New("unknown masquerade URL scheme: ", masqueradeURL.Scheme)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = json.Unmarshal(bytes, (*_Hysteria2Masquerade)(m))
|
||||
if err != nil {
|
||||
|
||||
+18
-16
@@ -80,22 +80,34 @@ func (i *Inbound) Close() error {
|
||||
}
|
||||
|
||||
func (i *Inbound) NewPacketEx(buffer *buf.Buffer, source M.Socksaddr) {
|
||||
i.udpNat.NewPacket([][]byte{buffer.Bytes()}, source, M.Socksaddr{}, nil)
|
||||
var destination M.Socksaddr
|
||||
switch i.overrideOption {
|
||||
case 1:
|
||||
destination = i.overrideDestination
|
||||
case 2:
|
||||
destination = i.overrideDestination
|
||||
destination.Port = i.listener.UDPAddr().Port
|
||||
case 3:
|
||||
destination = source
|
||||
destination.Port = i.overrideDestination.Port
|
||||
}
|
||||
i.udpNat.NewPacket([][]byte{buffer.Bytes()}, source, destination, nil)
|
||||
}
|
||||
|
||||
func (i *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
metadata.Inbound = i.Tag()
|
||||
metadata.InboundType = i.Type()
|
||||
destination := metadata.OriginDestination
|
||||
metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr())
|
||||
switch i.overrideOption {
|
||||
case 1:
|
||||
destination = i.overrideDestination
|
||||
metadata.Destination = i.overrideDestination
|
||||
case 2:
|
||||
destination.Addr = i.overrideDestination.Addr
|
||||
case 3:
|
||||
destination := i.overrideDestination
|
||||
destination.Port = metadata.Destination.Port
|
||||
metadata.Destination = destination
|
||||
case 3:
|
||||
metadata.Destination.Port = i.overrideDestination.Port
|
||||
}
|
||||
metadata.Destination = destination
|
||||
if i.overrideOption != 0 {
|
||||
i.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
|
||||
}
|
||||
@@ -113,16 +125,6 @@ func (i *Inbound) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn,
|
||||
//nolint:staticcheck
|
||||
metadata.InboundOptions = i.listener.ListenOptions().InboundOptions
|
||||
metadata.Source = source
|
||||
destination = i.listener.UDPAddr()
|
||||
switch i.overrideOption {
|
||||
case 1:
|
||||
destination = i.overrideDestination
|
||||
case 2:
|
||||
destination.Addr = i.overrideDestination.Addr
|
||||
case 3:
|
||||
destination.Port = i.overrideDestination.Port
|
||||
default:
|
||||
}
|
||||
metadata.Destination = destination
|
||||
metadata.OriginDestination = i.listener.UDPAddr()
|
||||
i.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
|
||||
|
||||
+37
-3
@@ -245,7 +245,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "initialize auto-redirect")
|
||||
}
|
||||
if !C.IsAndroid && (len(inbound.routeRuleSet) > 0 || len(inbound.routeExcludeRuleSet) > 0) {
|
||||
if runtime.GOOS != "android" && len(inbound.routeAddressSet) > 0 || len(inbound.routeExcludeAddressSet) > 0 {
|
||||
inbound.tunOptions.AutoRedirectMarkMode = true
|
||||
err = networkManager.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
|
||||
if err != nil {
|
||||
@@ -305,7 +305,7 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
|
||||
if t.tunOptions.Name == "" {
|
||||
t.tunOptions.Name = tun.CalculateInterfaceName("")
|
||||
}
|
||||
if t.platformInterface == nil {
|
||||
if t.platformInterface == nil || runtime.GOOS != "android" {
|
||||
t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
|
||||
for _, routeRuleSet := range t.routeRuleSet {
|
||||
ipSets := routeRuleSet.ExtractIPSet()
|
||||
@@ -421,7 +421,41 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
|
||||
func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) {
|
||||
t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
|
||||
t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
|
||||
t.autoRedirect.UpdateRouteAddressSet()
|
||||
if t.autoRedirect != nil {
|
||||
t.autoRedirect.UpdateRouteAddressSet()
|
||||
} else {
|
||||
tunOptions := t.tunOptions
|
||||
for _, ipSet := range t.routeAddressSet {
|
||||
for _, prefix := range ipSet.Prefixes() {
|
||||
if prefix.Addr().Is4() {
|
||||
tunOptions.Inet4RouteAddress = append(tunOptions.Inet4RouteAddress, prefix)
|
||||
} else {
|
||||
tunOptions.Inet6RouteAddress = append(tunOptions.Inet6RouteAddress, prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, ipSet := range t.routeExcludeAddressSet {
|
||||
for _, prefix := range ipSet.Prefixes() {
|
||||
if prefix.Addr().Is4() {
|
||||
tunOptions.Inet4RouteExcludeAddress = append(tunOptions.Inet4RouteExcludeAddress, prefix)
|
||||
} else {
|
||||
tunOptions.Inet6RouteExcludeAddress = append(tunOptions.Inet6RouteExcludeAddress, prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
if t.platformInterface != nil {
|
||||
err := t.platformInterface.UpdateRouteOptions(&tunOptions, t.platformOptions)
|
||||
if err != nil {
|
||||
t.logger.Error("update route addresses: ", err)
|
||||
}
|
||||
} else {
|
||||
err := t.tunIf.UpdateRouteOptions(tunOptions)
|
||||
if err != nil {
|
||||
t.logger.Error("update route addresses: ", err)
|
||||
}
|
||||
}
|
||||
t.logger.Info("updated route addresses")
|
||||
}
|
||||
t.routeAddressSet = nil
|
||||
t.routeExcludeAddressSet = nil
|
||||
}
|
||||
|
||||
+4
-22
@@ -33,18 +33,7 @@ import (
|
||||
|
||||
// Deprecated: use RouteConnectionEx instead.
|
||||
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||
done := make(chan interface{})
|
||||
err := r.routeConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
|
||||
close(done)
|
||||
}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
case <-r.ctx.Done():
|
||||
}
|
||||
return nil
|
||||
return r.routeConnection(ctx, conn, metadata, nil)
|
||||
}
|
||||
|
||||
func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
@@ -152,10 +141,7 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
}
|
||||
|
||||
func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||
done := make(chan interface{})
|
||||
err := r.routePacketConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
|
||||
close(done)
|
||||
}))
|
||||
err := r.routePacketConnection(ctx, conn, metadata, nil)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
if E.IsClosedOrCanceled(err) {
|
||||
@@ -164,10 +150,6 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||
r.logger.ErrorContext(ctx, err)
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
case <-r.ctx.Done():
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -491,7 +473,7 @@ match:
|
||||
}
|
||||
if !preMatch && inputPacketConn != nil && !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() {
|
||||
var timeout time.Duration
|
||||
if metadata.InboundType == C.TypeSOCKS {
|
||||
if metadata.InboundType == C.TypeSOCKS || metadata.InboundType == C.TypeMixed {
|
||||
timeout = C.TCPTimeout
|
||||
}
|
||||
newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{Timeout: timeout}, inputConn, inputPacketConn)
|
||||
@@ -590,7 +572,7 @@ func (r *Router) actionSniff(
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if !metadata.Destination.Addr.IsGlobalUnicast() {
|
||||
if !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() {
|
||||
metadata.Destination = destination
|
||||
}
|
||||
if len(packetBuffers) > 0 {
|
||||
|
||||
+21
-11
@@ -45,22 +45,28 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int,
|
||||
panic("no context")
|
||||
}
|
||||
var options dns.QueryOptions
|
||||
var currentRuleIndex int
|
||||
var (
|
||||
currentRuleIndex int
|
||||
currentRule adapter.DNSRule
|
||||
)
|
||||
if ruleIndex != -1 {
|
||||
currentRuleIndex = ruleIndex + 1
|
||||
}
|
||||
for ; currentRuleIndex < len(r.dnsRules); currentRuleIndex++ {
|
||||
currentRule := r.dnsRules[currentRuleIndex]
|
||||
for currentRuleIndex, currentRule = range r.dnsRules[currentRuleIndex:] {
|
||||
if currentRule.WithAddressLimit() && !isAddressQuery {
|
||||
continue
|
||||
}
|
||||
metadata.ResetRuleCache()
|
||||
if currentRule.Match(metadata) {
|
||||
displayRuleIndex := currentRuleIndex
|
||||
if ruleIndex != -1 {
|
||||
displayRuleIndex += ruleIndex + 1
|
||||
}
|
||||
ruleDescription := currentRule.String()
|
||||
if ruleDescription != "" {
|
||||
r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
|
||||
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] ", currentRule, " => ", currentRule.Action())
|
||||
} else {
|
||||
r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
|
||||
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
|
||||
}
|
||||
switch action := currentRule.Action().(type) {
|
||||
case *R.RuleActionDNSRoute:
|
||||
@@ -87,7 +93,7 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int,
|
||||
} else {
|
||||
options.Strategy = r.defaultDomainStrategy
|
||||
}
|
||||
r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
|
||||
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
|
||||
return transport, options, currentRule, currentRuleIndex
|
||||
case *R.RuleActionDNSRouteOptions:
|
||||
if action.DisableCache {
|
||||
@@ -99,9 +105,9 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int,
|
||||
if action.ClientSubnet.IsValid() {
|
||||
options.ClientSubnet = action.ClientSubnet
|
||||
}
|
||||
r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
|
||||
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
|
||||
case *R.RuleActionReject:
|
||||
r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
|
||||
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
|
||||
return nil, options, currentRule, currentRuleIndex
|
||||
}
|
||||
}
|
||||
@@ -127,6 +133,7 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||
}
|
||||
return &responseMessage, nil
|
||||
}
|
||||
r.dnsLogger.DebugContext(ctx, "exchange ", formatQuestion(message.Question[0].String()))
|
||||
var (
|
||||
response *mDNS.Msg
|
||||
cached bool
|
||||
@@ -167,11 +174,14 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||
}
|
||||
}
|
||||
}
|
||||
r.dnsLogger.DebugContext(ctx, "exchange ", formatQuestion(message.Question[0].String()), " via ", transport.Name())
|
||||
if rule != nil && rule.WithAddressLimit() {
|
||||
addressLimit = true
|
||||
response, err = r.dnsClient.ExchangeWithResponseCheck(dnsCtx, transport, message, options, func(responseAddrs []netip.Addr) bool {
|
||||
metadata.DestinationAddresses = responseAddrs
|
||||
response, err = r.dnsClient.ExchangeWithResponseCheck(dnsCtx, transport, message, options, func(response *mDNS.Msg) bool {
|
||||
addresses, addrErr := dns.MessageToAddresses(response)
|
||||
if addrErr != nil {
|
||||
return false
|
||||
}
|
||||
metadata.DestinationAddresses = addresses
|
||||
return rule.MatchAddressLimit(metadata)
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -59,7 +59,7 @@ func hasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultH
|
||||
}
|
||||
|
||||
func isProcessHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0
|
||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.PackageName) > 0
|
||||
}
|
||||
|
||||
func isWIFIHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
||||
|
||||
@@ -62,6 +62,10 @@ func isProcessDNSRule(rule option.DefaultDNSRule) bool {
|
||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
|
||||
}
|
||||
|
||||
func isProcessHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0
|
||||
}
|
||||
|
||||
func notPrivateNode(code string) bool {
|
||||
return code != "private"
|
||||
}
|
||||
|
||||
+4
-4
@@ -13,9 +13,9 @@ require (
|
||||
github.com/docker/go-connections v0.5.0
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/sagernet/quic-go v0.48.2-beta.1
|
||||
github.com/sagernet/sing v0.6.0-beta.12
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.2
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.4
|
||||
github.com/sagernet/sing v0.6.0-beta.9
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.1
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.3
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||
github.com/spyzhov/ajson v0.9.4
|
||||
@@ -85,7 +85,7 @@ require (
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||
github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 // indirect
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.8 // indirect
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.7 // indirect
|
||||
github.com/sagernet/sing-vmess v0.2.0-beta.2 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||
github.com/sagernet/utls v1.6.7 // indirect
|
||||
|
||||
+8
-8
@@ -146,22 +146,22 @@ github.com/sagernet/quic-go v0.48.2-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/
|
||||
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.6.0-beta.12 h1:2DnTJcvypK3/PM/8JjmgG8wVK48gdcpRwU98c4J/a7s=
|
||||
github.com/sagernet/sing v0.6.0-beta.12/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.2 h1:HW94bUEp7K/vf5DlYz646LTZevQtJ0250jZa/UZRlbY=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.2/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
||||
github.com/sagernet/sing v0.6.0-beta.9 h1:P8lKa5hN53fRNAVCIKy5cWd6/kLO5c4slhdsfehSmHs=
|
||||
github.com/sagernet/sing v0.6.0-beta.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.1 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY=
|
||||
github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
||||
github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg=
|
||||
github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.4 h1:kKiMLGaxvVLDCSvCMYo4PtWd1xU6FTL7xvUAQfXO09g=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.4/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg=
|
||||
github.com/sagernet/sing-quic v0.4.0-beta.3/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0=
|
||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.8 h1:GFNt/w8r1v30zC/hfCytk8C9+N/f1DfvosFXJkyJlrw=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.8/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.7 h1:FCSX8oGBqb0H57AAvfGeeH/jMGYWCOg6XWkN/oeES+0=
|
||||
github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||
github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs=
|
||||
github.com/sagernet/sing-vmess v0.2.0-beta.2/go.mod h1:HGhf9XUdeE2iOWrX0hQNFgXPbKyGlzpeYFyX0c/pykk=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
|
||||
Reference in New Issue
Block a user