mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-14 04:38:28 +10:00
Compare commits
1 Commits
v1.11.0-al
...
v1.10.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e2231ff17 |
11
Makefile
11
Makefile
@@ -155,16 +155,7 @@ upload_macos_dmg:
|
||||
cp SFM.dmg "SFM-${VERSION}-universal.dmg" && \
|
||||
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dmg"
|
||||
|
||||
upload_macos_dsyms:
|
||||
pushd ../sing-box-for-apple/build/SFM.System.xcarchive && \
|
||||
zip -r SFM.dSYMs.zip dSYMs && \
|
||||
mv SFM.dSYMs.zip ../../../sing-box/dist/SFM && \
|
||||
popd && \
|
||||
cd dist/SFM && \
|
||||
cp SFM.dSYMs.zip "SFM-${VERSION}-universal.dSYMs.zip" && \
|
||||
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dSYMs.zip"
|
||||
|
||||
release_macos_standalone: build_macos_standalone build_macos_dmg upload_macos_dmg upload_macos_dsyms
|
||||
release_macos_standalone: build_macos_standalone build_macos_dmg upload_macos_dmg
|
||||
|
||||
build_tvos:
|
||||
cd ../sing-box-for-apple && \
|
||||
|
||||
@@ -91,6 +91,15 @@ func ContextFrom(ctx context.Context) *InboundContext {
|
||||
return metadata.(*InboundContext)
|
||||
}
|
||||
|
||||
func AppendContext(ctx context.Context) (context.Context, *InboundContext) {
|
||||
metadata := ContextFrom(ctx)
|
||||
if metadata != nil {
|
||||
return ctx, metadata
|
||||
}
|
||||
metadata = new(InboundContext)
|
||||
return WithContext(ctx, metadata), metadata
|
||||
}
|
||||
|
||||
func ExtendContext(ctx context.Context) (context.Context, *InboundContext) {
|
||||
var newMetadata InboundContext
|
||||
if metadata := ContextFrom(ctx); metadata != nil {
|
||||
|
||||
@@ -2,17 +2,13 @@ package adapter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/common/geoip"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-dns"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/x/list"
|
||||
"github.com/sagernet/sing/service"
|
||||
@@ -102,7 +98,7 @@ type DNSRule interface {
|
||||
|
||||
type RuleSet interface {
|
||||
Name() string
|
||||
StartContext(ctx context.Context, startContext *HTTPStartContext) error
|
||||
StartContext(ctx context.Context, startContext RuleSetStartContext) error
|
||||
PostStart() error
|
||||
Metadata() RuleSetMetadata
|
||||
ExtractIPSet() []*netipx.IPSet
|
||||
@@ -122,42 +118,10 @@ type RuleSetMetadata struct {
|
||||
ContainsWIFIRule bool
|
||||
ContainsIPCIDRRule bool
|
||||
}
|
||||
type HTTPStartContext struct {
|
||||
access sync.Mutex
|
||||
httpClientCache map[string]*http.Client
|
||||
}
|
||||
|
||||
func NewHTTPStartContext() *HTTPStartContext {
|
||||
return &HTTPStartContext{
|
||||
httpClientCache: make(map[string]*http.Client),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *HTTPStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Client {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
if httpClient, loaded := c.httpClientCache[detour]; loaded {
|
||||
return httpClient
|
||||
}
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: C.TCPTimeout,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
},
|
||||
}
|
||||
c.httpClientCache[detour] = httpClient
|
||||
return httpClient
|
||||
}
|
||||
|
||||
func (c *HTTPStartContext) Close() {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
for _, client := range c.httpClientCache {
|
||||
client.CloseIdleConnections()
|
||||
}
|
||||
type RuleSetStartContext interface {
|
||||
HTTPClient(detour string, dialer N.Dialer) *http.Client
|
||||
Close()
|
||||
}
|
||||
|
||||
type InterfaceUpdateListener interface {
|
||||
|
||||
Submodule clients/android updated: 45a1f5f0aa...2aa661d507
Submodule clients/apple updated: c7d9b49de7...c223f50ffb
@@ -58,7 +58,7 @@ func FindSDK() {
|
||||
}
|
||||
|
||||
func findNDK() bool {
|
||||
const fixedVersion = "27.2.12479018"
|
||||
const fixedVersion = "26.2.11394342"
|
||||
const versionFile = "source.properties"
|
||||
if fixedPath := filepath.Join(androidSDKPath, "ndk", fixedVersion); rw.IsFile(filepath.Join(fixedPath, versionFile)) {
|
||||
androidNDKPath = fixedPath
|
||||
|
||||
@@ -7,10 +7,8 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
_ "github.com/sagernet/sing-box/include"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing/service"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -67,5 +65,4 @@ func preRun(cmd *cobra.Command, args []string) {
|
||||
if len(configPaths) == 0 && len(configDirectories) == 0 {
|
||||
configPaths = append(configPaths, "config.json")
|
||||
}
|
||||
globalCtx = service.ContextWith(globalCtx, deprecated.NewEnvManager(log.StdLogger()))
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi
|
||||
if options.ConnectTimeout != 0 {
|
||||
dialer.Timeout = time.Duration(options.ConnectTimeout)
|
||||
} else {
|
||||
dialer.Timeout = C.TCPConnectTimeout
|
||||
dialer.Timeout = C.TCPTimeout
|
||||
}
|
||||
// TODO: Add an option to customize the keep alive period
|
||||
dialer.KeepAlive = C.TCPKeepAliveInitial
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
@@ -114,7 +113,6 @@ func URLTest(ctx context.Context, link string, detour N.Dialer) (t uint16, err e
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
Timeout: C.TCPTimeout,
|
||||
}
|
||||
defer client.CloseIdleConnections()
|
||||
resp, err := client.Do(req.WithContext(ctx))
|
||||
|
||||
@@ -5,8 +5,7 @@ import "time"
|
||||
const (
|
||||
TCPKeepAliveInitial = 10 * time.Minute
|
||||
TCPKeepAliveInterval = 75 * time.Second
|
||||
TCPConnectTimeout = 5 * time.Second
|
||||
TCPTimeout = 15 * time.Second
|
||||
TCPTimeout = 5 * time.Second
|
||||
ReadPayloadTimeout = 300 * time.Millisecond
|
||||
DNSTimeout = 10 * time.Second
|
||||
QUICTimeout = 30 * time.Second
|
||||
|
||||
@@ -2,124 +2,10 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
#### 1.11.0-alpha.6
|
||||
|
||||
* Update quic-go to v0.48.1
|
||||
* Set gateway for tun correctly
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.11.0-alpha.2
|
||||
|
||||
* Add warnings for usage of deprecated features
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.11.0-alpha.1
|
||||
|
||||
* Update quic-go to v0.48.0
|
||||
* Fixes and improvements
|
||||
|
||||
### 1.10.1
|
||||
#### 1.10.0-rc.1
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
### 1.10.0
|
||||
|
||||
Important changes since 1.9:
|
||||
|
||||
* Introducing auto-redirect **1**
|
||||
* Add AdGuard DNS Filter support **2**
|
||||
* TUN address fields are merged **3**
|
||||
* Add custom options for `auto-route` and `auto-redirect` **4**
|
||||
* Drop support for go1.18 and go1.19 **5**
|
||||
* Add tailing comma support in JSON configuration
|
||||
* Improve sniffers **6**
|
||||
* Add new `inline` rule-set type **7**
|
||||
* Add access control options for Clash API **8**
|
||||
* Add `rule_set_ip_cidr_accept_empty` DNS address filter rule item **9**
|
||||
* Add auto reload support for local rule-set
|
||||
* Update fsnotify usages **10**
|
||||
* Add IP address support for `rule-set match` command
|
||||
* Add `rule-set decompile` command
|
||||
* Add `process_path_regex` rule item
|
||||
* Update uTLS to v1.6.7 **11**
|
||||
* Optimize memory usages of rule-sets **12**
|
||||
|
||||
**1**:
|
||||
|
||||
The new auto-redirect feature allows TUN to automatically
|
||||
configure connection redirection to improve proxy performance.
|
||||
|
||||
When auto-redirect is enabled, new route address set options will allow you to
|
||||
automatically configure destination IP CIDR rules from a specified rule set to the firewall.
|
||||
|
||||
Specified or unspecified destinations will bypass the sing-box routes to get better performance
|
||||
(for example, keep hardware offloading of direct traffics on the router).
|
||||
|
||||
See [TUN](/configuration/inbound/tun).
|
||||
|
||||
**2**:
|
||||
|
||||
The new feature allows you to use AdGuard DNS Filter lists in a sing-box without AdGuard Home.
|
||||
|
||||
See [AdGuard DNS Filter](/configuration/rule-set/adguard/).
|
||||
|
||||
**3**:
|
||||
|
||||
See [Migration](/migration/#tun-address-fields-are-merged).
|
||||
|
||||
**4**:
|
||||
|
||||
See [iproute2_table_index](/configuration/inbound/tun/#iproute2_table_index),
|
||||
[iproute2_rule_index](/configuration/inbound/tun/#iproute2_rule_index),
|
||||
[auto_redirect_input_mark](/configuration/inbound/tun/#auto_redirect_input_mark) and
|
||||
[auto_redirect_output_mark](/configuration/inbound/tun/#auto_redirect_output_mark).
|
||||
|
||||
**5**:
|
||||
|
||||
Due to maintenance difficulties, sing-box 1.10.0 requires at least Go 1.20 to compile.
|
||||
|
||||
**6**:
|
||||
|
||||
BitTorrent, DTLS, RDP, SSH sniffers are added.
|
||||
|
||||
Now the QUIC sniffer can correctly extract the server name from Chromium requests and
|
||||
can identify common QUIC clients, including
|
||||
Chromium, Safari, Firefox, quic-go (including uquic disguised as Chrome).
|
||||
|
||||
**7**:
|
||||
|
||||
The new [rule-set](/configuration/rule-set/) type inline (which also becomes the default type)
|
||||
allows you to write headless rules directly without creating a rule-set file.
|
||||
|
||||
**8**:
|
||||
|
||||
With the new access control options, not only can you allow Clash dashboards
|
||||
to access the Clash API on your local network,
|
||||
you can also manually limit the websites that can access the API instead of allowing everyone.
|
||||
|
||||
See [Clash API](/configuration/experimental/clash-api/).
|
||||
|
||||
**9**:
|
||||
|
||||
See [DNS Rule](/configuration/dns/rule/#rule_set_ip_cidr_accept_empty).
|
||||
|
||||
**10**:
|
||||
|
||||
sing-box now uses fsnotify correctly and will not cancel watching
|
||||
if the target file is deleted or recreated via rename (e.g. `mv`).
|
||||
|
||||
This affects all path options that support reload, including
|
||||
`tls.certificate_path`, `tls.key_path`, `tls.ech.key_path` and `rule_set.path`.
|
||||
|
||||
**11**:
|
||||
|
||||
Some legacy chrome fingerprints have been removed and will fallback to chrome,
|
||||
see [utls](/configuration/shared/tls#utls).
|
||||
|
||||
**12**:
|
||||
|
||||
See [Source Format](/configuration/rule-set/source-format/#version).
|
||||
|
||||
### 1.9.7
|
||||
|
||||
* Fixes and improvements
|
||||
@@ -127,20 +13,18 @@ See [Source Format](/configuration/rule-set/source-format/#version).
|
||||
#### 1.10.0-beta.11
|
||||
|
||||
* Update uTLS to v1.6.7 **1**
|
||||
* Add ipk in release artifacts
|
||||
|
||||
**1**:
|
||||
|
||||
Some legacy chrome fingerprints have been removed and will fallback to chrome,
|
||||
see [utls](/configuration/shared/tls#utls).
|
||||
Some legacy chrome fingerprints have been removed and will fallback to chrome, see [utls](/configuration/shared/tls#utls).
|
||||
|
||||
#### 1.10.0-beta.10
|
||||
|
||||
* Add `process_path_regex` rule item
|
||||
* Fixes and improvements
|
||||
|
||||
_The macOS standalone versions of sing-box (>=1.9.5/<1.10.0-beta.11) now silently fail and require manual granting of
|
||||
the **Full Disk Access** permission to system extension to start, probably due to Apple's changed security policy. We
|
||||
will prompt users about this in feature versions._
|
||||
_The macOS standalone versions of sing-box (>=1.9.5/<1.10.0-beta.11) now silently fail and require manual granting of the **Full Disk Access** permission to system extension to start, probably due to Apple's changed security policy. We will prompt users about this in feature versions._
|
||||
|
||||
### 1.9.6
|
||||
|
||||
@@ -170,8 +54,7 @@ We are still working on getting all sing-box apps back on the App Store, which s
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
_With the help of a netizen, we are in the process of getting sing-box apps back on the App Store, which should be
|
||||
completed within a month (TestFlight is already available)._
|
||||
_With the help of a netizen, we are in the process of getting sing-box apps back on the App Store, which should be completed within a month (TestFlight is already available)._
|
||||
|
||||
#### 1.10.0-beta.7
|
||||
|
||||
@@ -276,9 +159,11 @@ See [Source Format](/configuration/rule-set/source-format/#version).
|
||||
|
||||
**1**:
|
||||
|
||||
The new [rule-set](/configuration/rule-set/) type inline (which also becomes the default type)
|
||||
The new [rule-set] type inline (which also becomes the default type)
|
||||
allows you to write headless rules directly without creating a rule-set file.
|
||||
|
||||
[rule-set]: /configuration/rule-set/
|
||||
|
||||
**2**:
|
||||
|
||||
sing-box now uses fsnotify correctly and will not cancel watching
|
||||
|
||||
@@ -232,12 +232,12 @@ Automatically configure iptables/nftables to redirect connections.
|
||||
|
||||
*In Android*:
|
||||
|
||||
Only local IPv4 connections are forwarded. To share your VPN connection over hotspot or repeater,
|
||||
Only local connections are forwarded. To share your VPN connection over hotspot or repeater,
|
||||
use [VPNHotspot](https://github.com/Mygod/VPNHotspot).
|
||||
|
||||
*In Linux*:
|
||||
|
||||
`auto_route` with `auto_redirect` works as expected on routers **without intervention**.
|
||||
`auto_route` with `auto_redirect` now works as expected on routers **without intervention**.
|
||||
|
||||
#### auto_redirect_input_mark
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ tun 接口的 IPv6 前缀。
|
||||
|
||||
仅支持 Linux,且需要 `auto_route` 已启用。
|
||||
|
||||
自动配置 iptables/nftables 以重定向连接。
|
||||
自动配置 iptables 以重定向 TCP 连接。
|
||||
|
||||
*在 Android 中*:
|
||||
|
||||
@@ -240,7 +240,7 @@ tun 接口的 IPv6 前缀。
|
||||
|
||||
*在 Linux 中*:
|
||||
|
||||
带有 `auto_redirect `的 `auto_route` 可以在路由器上按预期工作,**无需干预**。
|
||||
带有 `auto_redirect `的 `auto_route` 现在可以在路由器上按预期工作,**无需干预**。
|
||||
|
||||
#### auto_redirect_input_mark
|
||||
|
||||
|
||||
@@ -14,11 +14,6 @@ icon: material/delete-alert
|
||||
|
||||
Old fields are deprecated and will be removed in sing-box 1.11.0.
|
||||
|
||||
#### Match source rule items are renamed
|
||||
|
||||
`rule_set_ipcidr_match_source` route and DNS rule items are renamed to
|
||||
`rule_set_ip_cidr_match_source` and will be remove in sing-box 1.11.0.
|
||||
|
||||
#### Drop support for go1.18 and go1.19
|
||||
|
||||
Due to maintenance difficulties, sing-box 1.10.0 requires at least Go 1.20 to compile.
|
||||
|
||||
@@ -6,18 +6,13 @@ icon: material/delete-alert
|
||||
|
||||
## 1.10.0
|
||||
|
||||
#### Match source 规则项已重命名
|
||||
|
||||
`rule_set_ipcidr_match_source` 路由和 DNS 规则项已被重命名为
|
||||
`rule_set_ip_cidr_match_source` 且将在 sing-box 1.11.0 中被移除。
|
||||
|
||||
#### TUN 地址字段已合并
|
||||
|
||||
`inet4_address` 和 `inet6_address` 已合并为 `address`,
|
||||
`inet4_route_address` 和 `inet6_route_address` 已合并为 `route_address`,
|
||||
`inet4_route_exclude_address` 和 `inet6_route_exclude_address` 已合并为 `route_exclude_address`。
|
||||
|
||||
旧字段已废弃,且将在 sing-box 1.11.0 中被移除。
|
||||
旧字段已废弃,且将在 sing-box 1.11.0 中移除。
|
||||
|
||||
#### 移除对 go1.18 和 go1.19 的支持
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
@@ -60,7 +60,7 @@ func (s *Server) downloadExternalUI() error {
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: C.TCPTimeout,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package deprecated
|
||||
|
||||
import (
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
type Note struct {
|
||||
Name string
|
||||
Description string
|
||||
DeprecatedVersion string
|
||||
ScheduledVersion string
|
||||
EnvName string
|
||||
MigrationLink string
|
||||
}
|
||||
|
||||
func (n Note) Impending() bool {
|
||||
if n.ScheduledVersion == "" {
|
||||
return false
|
||||
}
|
||||
if !semver.IsValid("v" + C.Version) {
|
||||
return false
|
||||
}
|
||||
versionMinor := semver.Compare(semver.MajorMinor("v"+C.Version), "v"+n.ScheduledVersion)
|
||||
if versionMinor < 0 {
|
||||
panic("invalid deprecated note: " + n.Name)
|
||||
}
|
||||
return versionMinor <= 1
|
||||
}
|
||||
|
||||
func (n Note) Message() string {
|
||||
return F.ToString(
|
||||
n.Description, " is deprecated in sing-box ", n.DeprecatedVersion,
|
||||
" and will be removed in sing-box ", n.ScheduledVersion, ", please checkout documentation for migration.",
|
||||
)
|
||||
}
|
||||
|
||||
func (n Note) MessageWithLink() string {
|
||||
return F.ToString(
|
||||
n.Description, " is deprecated in sing-box ", n.DeprecatedVersion,
|
||||
" and will be removed in sing-box ", n.ScheduledVersion, ", checkout documentation for migration: ", n.MigrationLink,
|
||||
)
|
||||
}
|
||||
|
||||
var OptionBadMatchSource = Note{
|
||||
Name: "bad-match-source",
|
||||
Description: "legacy match source rule item",
|
||||
DeprecatedVersion: "1.10.0",
|
||||
ScheduledVersion: "1.11.0",
|
||||
MigrationLink: "https://sing-box.sagernet.org/deprecated/#match-source-rule-items-are-renamed",
|
||||
}
|
||||
|
||||
var OptionGEOIP = Note{
|
||||
Name: "geoip",
|
||||
Description: "geoip database",
|
||||
DeprecatedVersion: "1.8.0",
|
||||
ScheduledVersion: "1.12.0",
|
||||
EnvName: "GEOIP",
|
||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-geoip-to-rule-sets",
|
||||
}
|
||||
|
||||
var OptionGEOSITE = Note{
|
||||
Name: "geosite",
|
||||
Description: "geosite database",
|
||||
DeprecatedVersion: "1.8.0",
|
||||
ScheduledVersion: "1.12.0",
|
||||
EnvName: "GEOSITE",
|
||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-geosite-to-rule-sets",
|
||||
}
|
||||
|
||||
var OptionTUNAddressX = Note{
|
||||
Name: "tun-address-x",
|
||||
Description: "legacy tun address fields",
|
||||
DeprecatedVersion: "1.10.0",
|
||||
ScheduledVersion: "1.12.0",
|
||||
MigrationLink: "https://sing-box.sagernet.org/migration/#tun-address-fields-are-merged",
|
||||
}
|
||||
|
||||
var Options = []Note{
|
||||
OptionBadMatchSource,
|
||||
OptionGEOIP,
|
||||
OptionGEOSITE,
|
||||
OptionTUNAddressX,
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package deprecated
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
)
|
||||
|
||||
type envManager struct {
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
func NewEnvManager(logger logger.Logger) Manager {
|
||||
return &envManager{logger: logger}
|
||||
}
|
||||
|
||||
func (f *envManager) ReportDeprecated(feature Note) {
|
||||
if !feature.Impending() {
|
||||
f.logger.Warn(feature.MessageWithLink())
|
||||
return
|
||||
}
|
||||
enable, enableErr := strconv.ParseBool(os.Getenv("ENABLE_DEPRECATED_" + feature.EnvName))
|
||||
if enableErr == nil && enable {
|
||||
f.logger.Warn(feature.MessageWithLink())
|
||||
return
|
||||
}
|
||||
f.logger.Error(feature.MessageWithLink())
|
||||
f.logger.Fatal("to continuing using this feature, set ENABLE_DEPRECATED_" + feature.EnvName + "=true")
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package deprecated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing/service"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
ReportDeprecated(feature Note)
|
||||
}
|
||||
|
||||
func Report(ctx context.Context, feature Note) {
|
||||
manager := service.FromContext[Manager](ctx)
|
||||
if manager == nil {
|
||||
return
|
||||
}
|
||||
manager.ReportDeprecated(feature)
|
||||
}
|
||||
@@ -16,5 +16,4 @@ const (
|
||||
CommandSetSystemProxyEnabled
|
||||
CommandConnections
|
||||
CommandCloseConnection
|
||||
CommandGetDeprecatedNotes
|
||||
)
|
||||
|
||||
@@ -20,7 +20,6 @@ type CommandClient struct {
|
||||
type CommandClientOptions struct {
|
||||
Command int32
|
||||
StatusInterval int64
|
||||
IsMainClient bool
|
||||
}
|
||||
|
||||
type CommandClientHandler interface {
|
||||
@@ -29,7 +28,6 @@ type CommandClientHandler interface {
|
||||
ClearLogs()
|
||||
WriteLogs(messageList StringIterator)
|
||||
WriteStatus(message *StatusMessage)
|
||||
OpenURL(url string)
|
||||
WriteGroups(message OutboundGroupIterator)
|
||||
InitializeClashMode(modeList StringIterator, currentMode string)
|
||||
UpdateClashMode(newMode string)
|
||||
@@ -93,13 +91,9 @@ func (c *CommandClient) Connect() error {
|
||||
c.handler.Connected()
|
||||
go c.handleLogConn(conn)
|
||||
case CommandStatus:
|
||||
err = binary.Write(conn, binary.BigEndian, c.options.IsMainClient)
|
||||
if err != nil {
|
||||
return E.Cause(err, "write is main client")
|
||||
}
|
||||
err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval)
|
||||
if err != nil {
|
||||
return E.Cause(err, "write header")
|
||||
return E.Cause(err, "write interval")
|
||||
}
|
||||
c.handler.Connected()
|
||||
go c.handleStatusConn(conn)
|
||||
|
||||
@@ -18,10 +18,6 @@ func (c *CommandClient) CloseConnection(connId string) error {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
err = binary.Write(conn, binary.BigEndian, uint8(CommandCloseConnection))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writer := bufio.NewWriter(conn)
|
||||
err = varbin.Write(writer, binary.BigEndian, connId)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/varbin"
|
||||
"github.com/sagernet/sing/service"
|
||||
)
|
||||
|
||||
func (c *CommandClient) GetDeprecatedNotes() (DeprecatedNoteIterator, error) {
|
||||
conn, err := c.directConnect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
err = binary.Write(conn, binary.BigEndian, uint8(CommandGetDeprecatedNotes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = readError(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var features []deprecated.Note
|
||||
err = varbin.Read(conn, binary.BigEndian, &features)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newIterator(common.Map(features, func(it deprecated.Note) *DeprecatedNote { return (*DeprecatedNote)(&it) })), nil
|
||||
}
|
||||
|
||||
func (s *CommandServer) handleGetDeprecatedNotes(conn net.Conn) error {
|
||||
boxService := s.service
|
||||
if boxService == nil {
|
||||
return writeError(conn, E.New("service not ready"))
|
||||
}
|
||||
err := writeError(conn, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return varbin.Write(conn, binary.BigEndian, service.FromContext[deprecated.Manager](boxService.ctx).(*deprecatedManager).Get())
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/varbin"
|
||||
)
|
||||
|
||||
type myEvent interface {
|
||||
writeTo(writer varbin.Writer)
|
||||
}
|
||||
|
||||
func readEvent(reader varbin.Reader) (myEvent, error) {
|
||||
eventType, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch eventType {
|
||||
case eventTypeEmpty:
|
||||
return nil, nil
|
||||
case eventTypeOpenURL:
|
||||
url, err := varbin.ReadValue[string](reader, binary.BigEndian)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &eventOpenURL{URL: url}, nil
|
||||
default:
|
||||
return nil, E.New("unknown event type: ", eventType)
|
||||
}
|
||||
}
|
||||
|
||||
type eventOpenURL struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func (e *eventOpenURL) writeTo(writer varbin.Writer) {
|
||||
writer.WriteByte(eventTypeOpenURL)
|
||||
varbin.Write(writer, binary.BigEndian, e.URL)
|
||||
}
|
||||
@@ -33,7 +33,6 @@ type CommandServer struct {
|
||||
urlTestUpdate chan struct{}
|
||||
modeUpdate chan struct{}
|
||||
logReset chan struct{}
|
||||
events chan myEvent
|
||||
|
||||
closedConnections []Connection
|
||||
}
|
||||
@@ -53,7 +52,6 @@ func NewCommandServer(handler CommandServerHandler, maxLines int32) *CommandServ
|
||||
urlTestUpdate: make(chan struct{}, 1),
|
||||
modeUpdate: make(chan struct{}, 1),
|
||||
logReset: make(chan struct{}, 1),
|
||||
events: make(chan myEvent, 8),
|
||||
}
|
||||
server.observer = observable.NewObserver[string](server.subscriber, 64)
|
||||
return server
|
||||
@@ -63,12 +61,6 @@ func (s *CommandServer) SetService(newService *BoxService) {
|
||||
if newService != nil {
|
||||
service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate)
|
||||
newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate)
|
||||
newService.platformInterface.openURLFunc = func(url string) {
|
||||
select {
|
||||
case s.events <- &eventOpenURL{URL: url}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
s.service = newService
|
||||
s.notifyURLTestUpdate()
|
||||
@@ -182,8 +174,6 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
|
||||
return s.handleConnectionsConn(conn)
|
||||
case CommandCloseConnection:
|
||||
return s.handleCloseConnection(conn)
|
||||
case CommandGetDeprecatedNotes:
|
||||
return s.handleGetDeprecatedNotes(conn)
|
||||
default:
|
||||
return E.New("unknown command: ", command)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
std_bufio "bufio"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"runtime"
|
||||
@@ -10,15 +9,9 @@ import (
|
||||
"github.com/sagernet/sing-box/common/conntrack"
|
||||
"github.com/sagernet/sing-box/experimental/clashapi"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/memory"
|
||||
)
|
||||
|
||||
const (
|
||||
eventTypeEmpty byte = iota
|
||||
eventTypeOpenURL
|
||||
)
|
||||
|
||||
type StatusMessage struct {
|
||||
Memory int64
|
||||
Goroutines int32
|
||||
@@ -51,73 +44,31 @@ func (s *CommandServer) readStatus() StatusMessage {
|
||||
}
|
||||
|
||||
func (s *CommandServer) handleStatusConn(conn net.Conn) error {
|
||||
var isMainClient bool
|
||||
err := binary.Read(conn, binary.BigEndian, &isMainClient)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read is main client")
|
||||
}
|
||||
var interval int64
|
||||
err = binary.Read(conn, binary.BigEndian, &interval)
|
||||
err := binary.Read(conn, binary.BigEndian, &interval)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read interval")
|
||||
}
|
||||
ticker := time.NewTicker(time.Duration(interval))
|
||||
defer ticker.Stop()
|
||||
ctx := connKeepAlive(conn)
|
||||
writer := std_bufio.NewWriter(conn)
|
||||
if isMainClient {
|
||||
for {
|
||||
writer.WriteByte(eventTypeEmpty)
|
||||
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writer.Flush()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
case event := <-s.events:
|
||||
event.writeTo(writer)
|
||||
writer.Flush()
|
||||
}
|
||||
for {
|
||||
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
for {
|
||||
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writer.Flush()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommandClient) handleStatusConn(conn net.Conn) {
|
||||
reader := std_bufio.NewReader(conn)
|
||||
for {
|
||||
if c.options.IsMainClient {
|
||||
rawEvent, err := readEvent(reader)
|
||||
if err != nil {
|
||||
c.handler.Disconnected(err.Error())
|
||||
return
|
||||
}
|
||||
switch event := rawEvent.(type) {
|
||||
case *eventOpenURL:
|
||||
c.handler.OpenURL(event.URL)
|
||||
continue
|
||||
case nil:
|
||||
default:
|
||||
panic(F.ToString("unexpected event type: ", event))
|
||||
}
|
||||
}
|
||||
var message StatusMessage
|
||||
err := binary.Read(reader, binary.BigEndian, &message)
|
||||
err := binary.Read(conn, binary.BigEndian, &message)
|
||||
if err != nil {
|
||||
c.handler.Disconnected(err.Error())
|
||||
return
|
||||
|
||||
@@ -134,9 +134,6 @@ func (s *interfaceMonitorStub) RegisterCallback(callback tun.DefaultInterfaceUpd
|
||||
func (s *interfaceMonitorStub) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) OpenURL(url string) {
|
||||
}
|
||||
|
||||
func FormatConfig(configContent string) (string, error) {
|
||||
options, err := parseConfig(configContent)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
)
|
||||
|
||||
var _ deprecated.Manager = (*deprecatedManager)(nil)
|
||||
|
||||
type deprecatedManager struct {
|
||||
access sync.Mutex
|
||||
features []deprecated.Note
|
||||
}
|
||||
|
||||
func (m *deprecatedManager) ReportDeprecated(feature deprecated.Note) {
|
||||
m.access.Lock()
|
||||
defer m.access.Unlock()
|
||||
m.features = append(m.features, feature)
|
||||
}
|
||||
|
||||
func (m *deprecatedManager) Get() []deprecated.Note {
|
||||
m.access.Lock()
|
||||
defer m.access.Unlock()
|
||||
features := m.features
|
||||
m.features = nil
|
||||
return features
|
||||
}
|
||||
|
||||
var _ = deprecated.Note(DeprecatedNote{})
|
||||
|
||||
type DeprecatedNote struct {
|
||||
Name string
|
||||
Description string
|
||||
DeprecatedVersion string
|
||||
ScheduledVersion string
|
||||
EnvName string
|
||||
MigrationLink string
|
||||
}
|
||||
|
||||
func (n DeprecatedNote) Impending() bool {
|
||||
return deprecated.Note(n).Impending()
|
||||
}
|
||||
|
||||
func (n DeprecatedNote) Message() string {
|
||||
return deprecated.Note(n).Message()
|
||||
}
|
||||
|
||||
func (n DeprecatedNote) MessageWithLink() string {
|
||||
return deprecated.Note(n).MessageWithLink()
|
||||
}
|
||||
|
||||
type DeprecatedNoteIterator interface {
|
||||
HasNext() bool
|
||||
Next() *DeprecatedNote
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
@@ -69,9 +69,8 @@ type httpClient struct {
|
||||
|
||||
func NewHTTPClient() HTTPClient {
|
||||
client := new(httpClient)
|
||||
client.client.Timeout = 15 * time.Second
|
||||
client.client.Transport = &client.transport
|
||||
client.transport.ForceAttemptHTTP2 = true
|
||||
client.transport.TLSHandshakeTimeout = C.TCPTimeout
|
||||
client.transport.TLSClientConfig = &client.tls
|
||||
client.transport.DisableKeepAlives = true
|
||||
return client
|
||||
@@ -128,6 +127,7 @@ func (c *httpClient) TrySocks5(port int32) {
|
||||
}
|
||||
|
||||
func (c *httpClient) KeepAlive() {
|
||||
c.transport.ForceAttemptHTTP2 = true
|
||||
c.transport.DisableKeepAlives = false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// copied from net.linkFlags
|
||||
func linkFlags(rawFlags uint32) net.Flags {
|
||||
var f net.Flags
|
||||
if rawFlags&syscall.IFF_UP != 0 {
|
||||
f |= net.FlagUp
|
||||
}
|
||||
if rawFlags&syscall.IFF_RUNNING != 0 {
|
||||
f |= net.FlagRunning
|
||||
}
|
||||
if rawFlags&syscall.IFF_BROADCAST != 0 {
|
||||
f |= net.FlagBroadcast
|
||||
}
|
||||
if rawFlags&syscall.IFF_LOOPBACK != 0 {
|
||||
f |= net.FlagLoopback
|
||||
}
|
||||
if rawFlags&syscall.IFF_POINTOPOINT != 0 {
|
||||
f |= net.FlagPointToPoint
|
||||
}
|
||||
if rawFlags&syscall.IFF_MULTICAST != 0 {
|
||||
f |= net.FlagMulticast
|
||||
}
|
||||
return f
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
//go:build !linux
|
||||
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func linkFlags(rawFlags uint32) net.Flags {
|
||||
panic("stub!")
|
||||
}
|
||||
@@ -38,7 +38,6 @@ type NetworkInterface struct {
|
||||
MTU int32
|
||||
Name string
|
||||
Addresses StringIterator
|
||||
Flags int32
|
||||
}
|
||||
|
||||
type WIFIState struct {
|
||||
|
||||
@@ -25,5 +25,4 @@ type Interface interface {
|
||||
ClearDNSCache()
|
||||
ReadWIFIState() adapter.WIFIState
|
||||
process.Searcher
|
||||
OpenURL(url string)
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ func DecodeProfileContent(data []byte) (*ProfileContent, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = binary.Read(bReader, binary.BigEndian, &content.Type)
|
||||
err = binary.Read(reader, binary.BigEndian, &content.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -233,17 +233,17 @@ func DecodeProfileContent(data []byte) (*ProfileContent, error) {
|
||||
}
|
||||
}
|
||||
if content.Type == ProfileTypeRemote || (version == 0 && content.Type != ProfileTypeLocal) {
|
||||
err = binary.Read(bReader, binary.BigEndian, &content.AutoUpdate)
|
||||
err = binary.Read(reader, binary.BigEndian, &content.AutoUpdate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version >= 1 {
|
||||
err = binary.Read(bReader, binary.BigEndian, &content.AutoUpdateInterval)
|
||||
err = binary.Read(reader, binary.BigEndian, &content.AutoUpdateInterval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = binary.Read(bReader, binary.BigEndian, &content.LastUpdated)
|
||||
err = binary.Read(reader, binary.BigEndian, &content.LastUpdated)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/sagernet/sing-box/common/process"
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
|
||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
@@ -34,9 +33,9 @@ type BoxService struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
instance *box.Box
|
||||
platformInterface *platformInterfaceWrapper
|
||||
pauseManager pause.Manager
|
||||
urlTestHistoryStorage *urltest.HistoryStorage
|
||||
|
||||
servicePauseFields
|
||||
}
|
||||
|
||||
@@ -50,7 +49,6 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
||||
ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID)
|
||||
urlTestHistoryStorage := urltest.NewHistoryStorage()
|
||||
ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage)
|
||||
ctx = service.ContextWith[deprecated.Manager](ctx, new(deprecatedManager))
|
||||
platformWrapper := &platformInterfaceWrapper{iif: platformInterface, useProcFS: platformInterface.UseProcFS()}
|
||||
instance, err := box.New(box.Options{
|
||||
Context: ctx,
|
||||
@@ -67,7 +65,6 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
instance: instance,
|
||||
platformInterface: platformWrapper,
|
||||
urlTestHistoryStorage: urlTestHistoryStorage,
|
||||
pauseManager: service.FromContext[pause.Manager](ctx),
|
||||
}, nil
|
||||
@@ -103,10 +100,9 @@ var (
|
||||
)
|
||||
|
||||
type platformInterfaceWrapper struct {
|
||||
iif PlatformInterface
|
||||
useProcFS bool
|
||||
router adapter.Router
|
||||
openURLFunc func(url string)
|
||||
iif PlatformInterface
|
||||
useProcFS bool
|
||||
router adapter.Router
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapter.Router) error {
|
||||
@@ -181,7 +177,6 @@ func (w *platformInterfaceWrapper) Interfaces() ([]control.Interface, error) {
|
||||
MTU: int(netInterface.MTU),
|
||||
Name: netInterface.Name,
|
||||
Addresses: common.Map(iteratorToArray[string](netInterface.Addresses), netip.MustParsePrefix),
|
||||
Flags: linkFlags(uint32(netInterface.Flags)),
|
||||
})
|
||||
}
|
||||
return interfaces, nil
|
||||
@@ -241,9 +236,3 @@ func (w *platformInterfaceWrapper) DisableColors() bool {
|
||||
func (w *platformInterfaceWrapper) WriteMessage(level log.Level, message string) {
|
||||
w.iif.WriteLog(message)
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) OpenURL(url string) {
|
||||
if w.openURLFunc != nil {
|
||||
w.openURLFunc(url)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ var (
|
||||
|
||||
func init() {
|
||||
debug.SetPanicOnFault(true)
|
||||
debug.SetTraceback("all")
|
||||
}
|
||||
|
||||
func Setup(basePath string, workingPath string, tempPath string, isTVOS bool) {
|
||||
|
||||
28
go.mod
28
go.mod
@@ -7,14 +7,14 @@ require (
|
||||
github.com/caddyserver/certmagic v0.20.0
|
||||
github.com/cloudflare/circl v1.3.7
|
||||
github.com/cretz/bine v0.2.0
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
||||
github.com/libdns/alidns v1.0.3
|
||||
github.com/libdns/cloudflare v0.1.1
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa
|
||||
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d
|
||||
github.com/mholt/acmez v1.2.0
|
||||
github.com/miekg/dns v1.1.62
|
||||
github.com/ooni/go-libtor v1.1.8
|
||||
@@ -25,30 +25,29 @@ require (
|
||||
github.com/sagernet/fswatch v0.1.1
|
||||
github.com/sagernet/gomobile v0.1.4
|
||||
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f
|
||||
github.com/sagernet/quic-go v0.48.1-beta.1
|
||||
github.com/sagernet/quic-go v0.47.0-beta.2
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.5.0
|
||||
github.com/sagernet/sing-dns v0.3.0
|
||||
github.com/sagernet/sing v0.5.0-rc.2
|
||||
github.com/sagernet/sing-dns v0.3.0-rc.2
|
||||
github.com/sagernet/sing-mux v0.2.0
|
||||
github.com/sagernet/sing-quic v0.3.0-rc.2
|
||||
github.com/sagernet/sing-quic v0.3.0-rc.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||
github.com/sagernet/sing-shadowtls v0.1.4
|
||||
github.com/sagernet/sing-tun v0.4.0-rc.5
|
||||
github.com/sagernet/sing-tun v0.4.0-rc.3
|
||||
github.com/sagernet/sing-vmess v0.1.12
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||
github.com/sagernet/utls v1.6.7
|
||||
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.uber.org/zap v1.27.0
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
golang.org/x/mod v0.20.0
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/sys v0.26.0
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/sys v0.25.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||
google.golang.org/grpc v1.63.2
|
||||
google.golang.org/protobuf v1.33.0
|
||||
@@ -90,10 +89,11 @@ require (
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
60
go.sum
60
go.sum
@@ -8,7 +8,7 @@ github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4
|
||||
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
||||
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
|
||||
@@ -17,8 +17,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
@@ -70,8 +70,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4=
|
||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d h1:j9LtzkYstLFoNvXW824QQeN7Y26uPL5249kzWKbzO9U=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
|
||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
@@ -110,27 +110,27 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/quic-go v0.48.1-beta.1 h1:ElPaV5yzlXIKZpqFMAcUGax6vddi3zt4AEpT94Z0vwo=
|
||||
github.com/sagernet/quic-go v0.48.1-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/+or9YMLaG5VeTk4k=
|
||||
github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
|
||||
github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
|
||||
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.5.0 h1:soo2wVwLcieKWWKIksFNK6CCAojUgAppqQVwyRYGkEM=
|
||||
github.com/sagernet/sing v0.5.0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.3.0 h1:uHCIlbCwBxALJwXcEK1d75d7t3vzCSVEQsPfZR1cxQE=
|
||||
github.com/sagernet/sing-dns v0.3.0/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M=
|
||||
github.com/sagernet/sing v0.5.0-rc.2 h1:tIrs6pRbjJWvI0ITRSg47P1wosY+iSuHpw9t5/hBx+Q=
|
||||
github.com/sagernet/sing v0.5.0-rc.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-dns v0.3.0-rc.2 h1:z1yROBxd/6wik5h53Sz5df1DSmbPTaOu/Z0wAmyXGoQ=
|
||||
github.com/sagernet/sing-dns v0.3.0-rc.2/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M=
|
||||
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.3.0-rc.2 h1:7vcC4bdS1GBJzHZhfmJiH0CfzQ4mYLUW51Z2RNHcGwc=
|
||||
github.com/sagernet/sing-quic v0.3.0-rc.2/go.mod h1:3UOq51WVqzra7eCgod7t4hqnTaOiZzFUci9avMrtOqs=
|
||||
github.com/sagernet/sing-quic v0.3.0-rc.1 h1:SlzL1yfEAKJyRduub8vzOVtbyTLAX7RZEEBZxO5utts=
|
||||
github.com/sagernet/sing-quic v0.3.0-rc.1/go.mod h1:uX+aUHA0fgIN6U3WViseDpSdTQriViZ7qz0Wbsf1mNQ=
|
||||
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.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||
github.com/sagernet/sing-tun v0.4.0-rc.5 h1:d4o36GbVZtsucpt5On7CjTFSx4zx82DL8OlGR7rX7vY=
|
||||
github.com/sagernet/sing-tun v0.4.0-rc.5/go.mod h1:rWu1ZC2lj4+UOOSNiUWjsY0y2fJcOHnLTMGna2n5P2o=
|
||||
github.com/sagernet/sing-tun v0.4.0-rc.3 h1:W/Odc87dGXkRhwRo2jhsKYHypNbajIcsGlIzDatmMKA=
|
||||
github.com/sagernet/sing-tun v0.4.0-rc.3/go.mod h1:+lQdWhqD4atzrCgRhoyrxBCg1OBru/hAv2BT3kdgmGM=
|
||||
github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg=
|
||||
github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
@@ -141,8 +141,8 @@ github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYASco
|
||||
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc=
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -170,16 +170,16 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -190,19 +190,19 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
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-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/taskmonitor"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
@@ -55,18 +54,15 @@ type Tun struct {
|
||||
|
||||
func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*Tun, error) {
|
||||
address := options.Address
|
||||
var deprecatedAddressUsed bool
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
if len(options.Inet4Address) > 0 {
|
||||
address = append(address, options.Inet4Address...)
|
||||
deprecatedAddressUsed = true
|
||||
}
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
if len(options.Inet6Address) > 0 {
|
||||
address = append(address, options.Inet6Address...)
|
||||
deprecatedAddressUsed = true
|
||||
}
|
||||
inet4Address := common.Filter(address, func(it netip.Prefix) bool {
|
||||
return it.Addr().Is4()
|
||||
@@ -80,13 +76,11 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||
//goland:noinspection GoDeprecation
|
||||
if len(options.Inet4RouteAddress) > 0 {
|
||||
routeAddress = append(routeAddress, options.Inet4RouteAddress...)
|
||||
deprecatedAddressUsed = true
|
||||
}
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
if len(options.Inet6RouteAddress) > 0 {
|
||||
routeAddress = append(routeAddress, options.Inet6RouteAddress...)
|
||||
deprecatedAddressUsed = true
|
||||
}
|
||||
inet4RouteAddress := common.Filter(routeAddress, func(it netip.Prefix) bool {
|
||||
return it.Addr().Is4()
|
||||
@@ -100,13 +94,11 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||
//goland:noinspection GoDeprecation
|
||||
if len(options.Inet4RouteExcludeAddress) > 0 {
|
||||
routeExcludeAddress = append(routeExcludeAddress, options.Inet4RouteExcludeAddress...)
|
||||
deprecatedAddressUsed = true
|
||||
}
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
if len(options.Inet6RouteExcludeAddress) > 0 {
|
||||
routeExcludeAddress = append(routeExcludeAddress, options.Inet6RouteExcludeAddress...)
|
||||
deprecatedAddressUsed = true
|
||||
}
|
||||
inet4RouteExcludeAddress := common.Filter(routeExcludeAddress, func(it netip.Prefix) bool {
|
||||
return it.Addr().Is4()
|
||||
@@ -115,10 +107,6 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||
return it.Addr().Is6()
|
||||
})
|
||||
|
||||
if deprecatedAddressUsed {
|
||||
deprecated.Report(ctx, deprecated.OptionTUNAddressX)
|
||||
}
|
||||
|
||||
tunMTU := options.MTU
|
||||
if tunMTU == 0 {
|
||||
tunMTU = 9000
|
||||
|
||||
@@ -64,7 +64,7 @@ func (r Rule) IsValid() bool {
|
||||
}
|
||||
}
|
||||
|
||||
type DefaultRule struct {
|
||||
type _DefaultRule struct {
|
||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||
IPVersion int `json:"ip_version,omitempty"`
|
||||
Network Listable[string] `json:"network,omitempty"`
|
||||
@@ -104,6 +104,22 @@ type DefaultRule struct {
|
||||
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
||||
}
|
||||
|
||||
type DefaultRule _DefaultRule
|
||||
|
||||
func (r *DefaultRule) UnmarshalJSON(bytes []byte) error {
|
||||
err := json.Unmarshal(bytes, (*_DefaultRule)(r))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
if r.Deprecated_RulesetIPCIDRMatchSource {
|
||||
r.Deprecated_RulesetIPCIDRMatchSource = false
|
||||
r.RuleSetIPCIDRMatchSource = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DefaultRule) IsValid() bool {
|
||||
var defaultValue DefaultRule
|
||||
defaultValue.Invert = r.Invert
|
||||
|
||||
@@ -64,7 +64,7 @@ func (r DNSRule) IsValid() bool {
|
||||
}
|
||||
}
|
||||
|
||||
type DefaultDNSRule struct {
|
||||
type _DefaultDNSRule struct {
|
||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||
IPVersion int `json:"ip_version,omitempty"`
|
||||
QueryType Listable[DNSQueryType] `json:"query_type,omitempty"`
|
||||
@@ -109,6 +109,22 @@ type DefaultDNSRule struct {
|
||||
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
||||
}
|
||||
|
||||
type DefaultDNSRule _DefaultDNSRule
|
||||
|
||||
func (r *DefaultDNSRule) UnmarshalJSON(bytes []byte) error {
|
||||
err := json.UnmarshalDisallowUnknownFields(bytes, (*_DefaultDNSRule)(r))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
if r.Deprecated_RulesetIPCIDRMatchSource {
|
||||
r.Deprecated_RulesetIPCIDRMatchSource = false
|
||||
r.RuleSetIPCIDRMatchSource = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DefaultDNSRule) IsValid() bool {
|
||||
var defaultValue DefaultDNSRule
|
||||
defaultValue.Invert = r.Invert
|
||||
|
||||
@@ -48,6 +48,17 @@ func (r *RuleSet) UnmarshalJSON(bytes []byte) error {
|
||||
if r.Tag == "" {
|
||||
return E.New("missing tag")
|
||||
}
|
||||
if r.Type != C.RuleSetTypeInline {
|
||||
switch r.Format {
|
||||
case "":
|
||||
return E.New("missing format")
|
||||
case C.RuleSetFormatSource, C.RuleSetFormatBinary:
|
||||
default:
|
||||
return E.New("unknown rule-set format: " + r.Format)
|
||||
}
|
||||
} else {
|
||||
r.Format = ""
|
||||
}
|
||||
var v any
|
||||
switch r.Type {
|
||||
case "", C.RuleSetTypeInline:
|
||||
@@ -60,17 +71,6 @@ func (r *RuleSet) UnmarshalJSON(bytes []byte) error {
|
||||
default:
|
||||
return E.New("unknown rule-set type: " + r.Type)
|
||||
}
|
||||
if r.Type != C.RuleSetTypeInline {
|
||||
switch r.Format {
|
||||
case "":
|
||||
return E.New("missing format")
|
||||
case C.RuleSetFormatSource, C.RuleSetFormatBinary:
|
||||
default:
|
||||
return E.New("unknown rule-set format: " + r.Format)
|
||||
}
|
||||
} else {
|
||||
r.Format = ""
|
||||
}
|
||||
err = UnmarshallExcluded(bytes, (*_RuleSet)(r), v)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
)
|
||||
|
||||
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Outbound) (adapter.Outbound, error) {
|
||||
var metadata *adapter.InboundContext
|
||||
if tag != "" {
|
||||
ctx = adapter.WithContext(ctx, &adapter.InboundContext{
|
||||
Outbound: tag,
|
||||
})
|
||||
ctx, metadata = adapter.AppendContext(ctx)
|
||||
metadata.Outbound = tag
|
||||
}
|
||||
if options.Type == "" {
|
||||
return nil, E.New("missing outbound type")
|
||||
|
||||
@@ -70,7 +70,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
||||
}
|
||||
|
||||
func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
switch h.overrideOption {
|
||||
@@ -98,7 +98,7 @@ func (h *Direct) DialContext(ctx context.Context, network string, destination M.
|
||||
}
|
||||
|
||||
func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
switch h.overrideOption {
|
||||
|
||||
@@ -54,7 +54,7 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||
}
|
||||
|
||||
func (h *HTTP) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
h.logger.InfoContext(ctx, "outbound connection to ", destination)
|
||||
|
||||
@@ -79,7 +79,7 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
||||
}
|
||||
|
||||
func (h *Shadowsocks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
if h.multiplexDialer == nil {
|
||||
@@ -107,7 +107,7 @@ func (h *Shadowsocks) DialContext(ctx context.Context, network string, destinati
|
||||
}
|
||||
|
||||
func (h *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
if h.multiplexDialer == nil {
|
||||
@@ -149,7 +149,7 @@ var _ N.Dialer = (*shadowsocksDialer)(nil)
|
||||
type shadowsocksDialer Shadowsocks
|
||||
|
||||
func (h *shadowsocksDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
switch N.NetworkName(network) {
|
||||
@@ -177,7 +177,7 @@ func (h *shadowsocksDialer) DialContext(ctx context.Context, network string, des
|
||||
}
|
||||
|
||||
func (h *shadowsocksDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
|
||||
|
||||
@@ -92,7 +92,7 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
|
||||
}
|
||||
|
||||
func (h *ShadowTLS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
switch N.NetworkName(network) {
|
||||
|
||||
@@ -65,7 +65,7 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
|
||||
}
|
||||
|
||||
func (h *Socks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
switch N.NetworkName(network) {
|
||||
@@ -91,7 +91,7 @@ func (h *Socks) DialContext(ctx context.Context, network string, destination M.S
|
||||
}
|
||||
|
||||
func (h *Socks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
if h.uotClient != nil {
|
||||
|
||||
@@ -124,7 +124,7 @@ func (h *Trojan) Close() error {
|
||||
type trojanDialer Trojan
|
||||
|
||||
func (h *trojanDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
var conn net.Conn
|
||||
|
||||
@@ -143,7 +143,7 @@ func (h *VLESS) Close() error {
|
||||
type vlessDialer VLESS
|
||||
|
||||
func (h *vlessDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
var conn net.Conn
|
||||
@@ -186,7 +186,7 @@ func (h *vlessDialer) DialContext(ctx context.Context, network string, destinati
|
||||
|
||||
func (h *vlessDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
var conn net.Conn
|
||||
|
||||
@@ -157,7 +157,7 @@ func (h *VMess) NewPacketConnection(ctx context.Context, conn N.PacketConn, meta
|
||||
type vmessDialer VMess
|
||||
|
||||
func (h *vmessDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
var conn net.Conn
|
||||
@@ -185,7 +185,7 @@ func (h *vmessDialer) DialContext(ctx context.Context, network string, destinati
|
||||
}
|
||||
|
||||
func (h *vmessDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
var conn net.Conn
|
||||
|
||||
@@ -153,14 +153,14 @@ func NewRouter(
|
||||
Logger: router.dnsLogger,
|
||||
})
|
||||
for i, ruleOptions := range options.Rules {
|
||||
routeRule, err := NewRule(ctx, router, router.logger, ruleOptions, true)
|
||||
routeRule, err := NewRule(router, router.logger, ruleOptions, true)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse rule[", i, "]")
|
||||
}
|
||||
router.rules = append(router.rules, routeRule)
|
||||
}
|
||||
for i, dnsRuleOptions := range dnsOptions.Rules {
|
||||
dnsRule, err := NewDNSRule(ctx, router, router.logger, dnsRuleOptions, true)
|
||||
dnsRule, err := NewDNSRule(router, router.logger, dnsRuleOptions, true)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse dns rule[", i, "]")
|
||||
}
|
||||
@@ -659,15 +659,14 @@ func (r *Router) Close() error {
|
||||
|
||||
func (r *Router) PostStart() error {
|
||||
monitor := taskmonitor.New(r.logger, C.StopTimeout)
|
||||
var cacheContext *adapter.HTTPStartContext
|
||||
if len(r.ruleSets) > 0 {
|
||||
monitor.Start("initialize rule-set")
|
||||
cacheContext = adapter.NewHTTPStartContext()
|
||||
ruleSetStartContext := NewRuleSetStartContext()
|
||||
var ruleSetStartGroup task.Group
|
||||
for i, ruleSet := range r.ruleSets {
|
||||
ruleSetInPlace := ruleSet
|
||||
ruleSetStartGroup.Append0(func(ctx context.Context) error {
|
||||
err := ruleSetInPlace.StartContext(ctx, cacheContext)
|
||||
err := ruleSetInPlace.StartContext(ctx, ruleSetStartContext)
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize rule-set[", i, "]")
|
||||
}
|
||||
@@ -681,9 +680,7 @@ func (r *Router) PostStart() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cacheContext != nil {
|
||||
cacheContext.Close()
|
||||
ruleSetStartContext.Close()
|
||||
}
|
||||
needFindProcess := r.needFindProcess
|
||||
needWIFIState := r.needWIFIState
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/geoip"
|
||||
"github.com/sagernet/sing-box/common/geosite"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
@@ -32,7 +32,7 @@ func (r *Router) LoadGeosite(code string) (adapter.Rule, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rule, err = NewDefaultRule(r.ctx, r, nil, geosite.Compile(items))
|
||||
rule, err = NewDefaultRule(r, nil, geosite.Compile(items))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -41,7 +41,6 @@ func (r *Router) LoadGeosite(code string) (adapter.Rule, error) {
|
||||
}
|
||||
|
||||
func (r *Router) prepareGeoIPDatabase() error {
|
||||
deprecated.Report(r.ctx, deprecated.OptionGEOIP)
|
||||
var geoPath string
|
||||
if r.geoIPOptions.Path != "" {
|
||||
geoPath = r.geoIPOptions.Path
|
||||
@@ -88,7 +87,6 @@ func (r *Router) prepareGeoIPDatabase() error {
|
||||
}
|
||||
|
||||
func (r *Router) prepareGeositeDatabase() error {
|
||||
deprecated.Report(r.ctx, deprecated.OptionGEOSITE)
|
||||
var geoPath string
|
||||
if r.geositeOptions.Path != "" {
|
||||
geoPath = r.geositeOptions.Path
|
||||
@@ -160,7 +158,7 @@ func (r *Router) downloadGeoIPDatabase(savePath string) error {
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: C.TCPTimeout,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
@@ -215,7 +213,7 @@ func (r *Router) downloadGeositeDatabase(savePath string) error {
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: C.TCPTimeout,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) {
|
||||
func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) {
|
||||
switch options.Type {
|
||||
case "", C.RuleTypeDefault:
|
||||
if !options.DefaultOptions.IsValid() {
|
||||
@@ -20,7 +17,7 @@ func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||
if options.DefaultOptions.Outbound == "" && checkOutbound {
|
||||
return nil, E.New("missing outbound field")
|
||||
}
|
||||
return NewDefaultRule(ctx, router, logger, options.DefaultOptions)
|
||||
return NewDefaultRule(router, logger, options.DefaultOptions)
|
||||
case C.RuleTypeLogical:
|
||||
if !options.LogicalOptions.IsValid() {
|
||||
return nil, E.New("missing conditions")
|
||||
@@ -28,7 +25,7 @@ func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||
if options.LogicalOptions.Outbound == "" && checkOutbound {
|
||||
return nil, E.New("missing outbound field")
|
||||
}
|
||||
return NewLogicalRule(ctx, router, logger, options.LogicalOptions)
|
||||
return NewLogicalRule(router, logger, options.LogicalOptions)
|
||||
default:
|
||||
return nil, E.New("unknown rule type: ", options.Type)
|
||||
}
|
||||
@@ -45,7 +42,7 @@ type RuleItem interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
func NewDefaultRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
|
||||
func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
|
||||
rule := &DefaultRule{
|
||||
abstractDefaultRule{
|
||||
invert: options.Invert,
|
||||
@@ -221,16 +218,7 @@ func NewDefaultRule(ctx context.Context, router adapter.Router, logger log.Conte
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.RuleSet) > 0 {
|
||||
var matchSource bool
|
||||
if options.RuleSetIPCIDRMatchSource {
|
||||
matchSource = true
|
||||
} else
|
||||
//nolint:staticcheck
|
||||
if options.Deprecated_RulesetIPCIDRMatchSource {
|
||||
matchSource = true
|
||||
deprecated.Report(ctx, deprecated.OptionBadMatchSource)
|
||||
}
|
||||
item := NewRuleSetItem(router, options.RuleSet, matchSource, false)
|
||||
item := NewRuleSetItem(router, options.RuleSet, options.RuleSetIPCIDRMatchSource, false)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
@@ -243,7 +231,7 @@ type LogicalRule struct {
|
||||
abstractLogicalRule
|
||||
}
|
||||
|
||||
func NewLogicalRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
|
||||
func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
|
||||
r := &LogicalRule{
|
||||
abstractLogicalRule{
|
||||
rules: make([]adapter.HeadlessRule, len(options.Rules)),
|
||||
@@ -260,7 +248,7 @@ func NewLogicalRule(ctx context.Context, router adapter.Router, logger log.Conte
|
||||
return nil, E.New("unknown logical mode: ", options.Mode)
|
||||
}
|
||||
for i, subRule := range options.Rules {
|
||||
rule, err := NewRule(ctx, router, logger, subRule, false)
|
||||
rule, err := NewRule(router, logger, subRule, false)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "sub rule[", i, "]")
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, error) {
|
||||
func NewDNSRule(router adapter.Router, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, error) {
|
||||
switch options.Type {
|
||||
case "", C.RuleTypeDefault:
|
||||
if !options.DefaultOptions.IsValid() {
|
||||
@@ -22,7 +20,7 @@ func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
if options.DefaultOptions.Server == "" && checkServer {
|
||||
return nil, E.New("missing server field")
|
||||
}
|
||||
return NewDefaultDNSRule(ctx, router, logger, options.DefaultOptions)
|
||||
return NewDefaultDNSRule(router, logger, options.DefaultOptions)
|
||||
case C.RuleTypeLogical:
|
||||
if !options.LogicalOptions.IsValid() {
|
||||
return nil, E.New("missing conditions")
|
||||
@@ -30,7 +28,7 @@ func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
if options.LogicalOptions.Server == "" && checkServer {
|
||||
return nil, E.New("missing server field")
|
||||
}
|
||||
return NewLogicalDNSRule(ctx, router, logger, options.LogicalOptions)
|
||||
return NewLogicalDNSRule(router, logger, options.LogicalOptions)
|
||||
default:
|
||||
return nil, E.New("unknown rule type: ", options.Type)
|
||||
}
|
||||
@@ -45,7 +43,7 @@ type DefaultDNSRule struct {
|
||||
clientSubnet *netip.Prefix
|
||||
}
|
||||
|
||||
func NewDefaultDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
|
||||
func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
|
||||
rule := &DefaultDNSRule{
|
||||
abstractDefaultRule: abstractDefaultRule{
|
||||
invert: options.Invert,
|
||||
@@ -229,16 +227,7 @@ func NewDefaultDNSRule(ctx context.Context, router adapter.Router, logger log.Co
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.RuleSet) > 0 {
|
||||
var matchSource bool
|
||||
if options.RuleSetIPCIDRMatchSource {
|
||||
matchSource = true
|
||||
} else
|
||||
//nolint:staticcheck
|
||||
if options.Deprecated_RulesetIPCIDRMatchSource {
|
||||
matchSource = true
|
||||
deprecated.Report(ctx, deprecated.OptionBadMatchSource)
|
||||
}
|
||||
item := NewRuleSetItem(router, options.RuleSet, matchSource, options.RuleSetIPCIDRAcceptEmpty)
|
||||
item := NewRuleSetItem(router, options.RuleSet, options.RuleSetIPCIDRMatchSource, options.RuleSetIPCIDRAcceptEmpty)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
@@ -294,7 +283,7 @@ type LogicalDNSRule struct {
|
||||
clientSubnet *netip.Prefix
|
||||
}
|
||||
|
||||
func NewLogicalDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
|
||||
func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
|
||||
r := &LogicalDNSRule{
|
||||
abstractLogicalRule: abstractLogicalRule{
|
||||
rules: make([]adapter.HeadlessRule, len(options.Rules)),
|
||||
@@ -314,7 +303,7 @@ func NewLogicalDNSRule(ctx context.Context, router adapter.Router, logger log.Co
|
||||
return nil, E.New("unknown logical mode: ", options.Mode)
|
||||
}
|
||||
for i, subRule := range options.Rules {
|
||||
rule, err := NewDNSRule(ctx, router, logger, subRule, false)
|
||||
rule, err := NewDNSRule(router, logger, subRule, false)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "sub rule[", i, "]")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package route
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
@@ -9,6 +12,8 @@ import (
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"go4.org/netipx"
|
||||
)
|
||||
@@ -41,3 +46,43 @@ func extractIPSetFromRule(rawRule adapter.HeadlessRule) []*netipx.IPSet {
|
||||
panic("unexpected rule type")
|
||||
}
|
||||
}
|
||||
|
||||
var _ adapter.RuleSetStartContext = (*RuleSetStartContext)(nil)
|
||||
|
||||
type RuleSetStartContext struct {
|
||||
access sync.Mutex
|
||||
httpClientCache map[string]*http.Client
|
||||
}
|
||||
|
||||
func NewRuleSetStartContext() *RuleSetStartContext {
|
||||
return &RuleSetStartContext{
|
||||
httpClientCache: make(map[string]*http.Client),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RuleSetStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Client {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
if httpClient, loaded := c.httpClientCache[detour]; loaded {
|
||||
return httpClient
|
||||
}
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: C.TCPTimeout,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
},
|
||||
}
|
||||
c.httpClientCache[detour] = httpClient
|
||||
return httpClient
|
||||
}
|
||||
|
||||
func (c *RuleSetStartContext) Close() {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
for _, client := range c.httpClientCache {
|
||||
client.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ func NewLocalRuleSet(ctx context.Context, router adapter.Router, logger logger.L
|
||||
}
|
||||
}
|
||||
if options.Type == C.RuleSetTypeLocal {
|
||||
var watcher *fswatch.Watcher
|
||||
filePath, _ := filepath.Abs(options.LocalOptions.Path)
|
||||
watcher, err := fswatch.NewWatcher(fswatch.Options{
|
||||
Path: []string{filePath},
|
||||
@@ -84,7 +85,7 @@ func (s *LocalRuleSet) String() string {
|
||||
return strings.Join(F.MapToString(s.rules), " ")
|
||||
}
|
||||
|
||||
func (s *LocalRuleSet) StartContext(ctx context.Context, startContext *adapter.HTTPStartContext) error {
|
||||
func (s *LocalRuleSet) StartContext(ctx context.Context, startContext adapter.RuleSetStartContext) error {
|
||||
if s.watcher != nil {
|
||||
err := s.watcher.Start()
|
||||
if err != nil {
|
||||
|
||||
@@ -45,7 +45,6 @@ type RemoteRuleSet struct {
|
||||
lastUpdated time.Time
|
||||
lastEtag string
|
||||
updateTicker *time.Ticker
|
||||
cacheFile adapter.CacheFile
|
||||
pauseManager pause.Manager
|
||||
callbackAccess sync.Mutex
|
||||
callbacks list.List[adapter.RuleSetUpdateCallback]
|
||||
@@ -79,8 +78,7 @@ func (s *RemoteRuleSet) String() string {
|
||||
return strings.Join(F.MapToString(s.rules), " ")
|
||||
}
|
||||
|
||||
func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.HTTPStartContext) error {
|
||||
s.cacheFile = service.FromContext[adapter.CacheFile](s.ctx)
|
||||
func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext adapter.RuleSetStartContext) error {
|
||||
var dialer N.Dialer
|
||||
if s.options.RemoteOptions.DownloadDetour != "" {
|
||||
outbound, loaded := s.router.Outbound(s.options.RemoteOptions.DownloadDetour)
|
||||
@@ -96,8 +94,9 @@ func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.
|
||||
dialer = outbound
|
||||
}
|
||||
s.dialer = dialer
|
||||
if s.cacheFile != nil {
|
||||
if savedSet := s.cacheFile.LoadRuleSet(s.options.Tag); savedSet != nil {
|
||||
cacheFile := service.FromContext[adapter.CacheFile](s.ctx)
|
||||
if cacheFile != nil {
|
||||
if savedSet := cacheFile.LoadRuleSet(s.options.Tag); savedSet != nil {
|
||||
err := s.loadBytes(savedSet.Content)
|
||||
if err != nil {
|
||||
return E.Cause(err, "restore cached rule-set")
|
||||
@@ -227,7 +226,7 @@ func (s *RemoteRuleSet) loopUpdate() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RemoteRuleSet) fetchOnce(ctx context.Context, startContext *adapter.HTTPStartContext) error {
|
||||
func (s *RemoteRuleSet) fetchOnce(ctx context.Context, startContext adapter.RuleSetStartContext) error {
|
||||
s.logger.Debug("updating rule-set ", s.options.Tag, " from URL: ", s.options.RemoteOptions.URL)
|
||||
var httpClient *http.Client
|
||||
if startContext != nil {
|
||||
@@ -258,11 +257,12 @@ func (s *RemoteRuleSet) fetchOnce(ctx context.Context, startContext *adapter.HTT
|
||||
case http.StatusOK:
|
||||
case http.StatusNotModified:
|
||||
s.lastUpdated = time.Now()
|
||||
if s.cacheFile != nil {
|
||||
savedRuleSet := s.cacheFile.LoadRuleSet(s.options.Tag)
|
||||
cacheFile := service.FromContext[adapter.CacheFile](s.ctx)
|
||||
if cacheFile != nil {
|
||||
savedRuleSet := cacheFile.LoadRuleSet(s.options.Tag)
|
||||
if savedRuleSet != nil {
|
||||
savedRuleSet.LastUpdated = s.lastUpdated
|
||||
err = s.cacheFile.SaveRuleSet(s.options.Tag, savedRuleSet)
|
||||
err = cacheFile.SaveRuleSet(s.options.Tag, savedRuleSet)
|
||||
if err != nil {
|
||||
s.logger.Error("save rule-set updated time: ", err)
|
||||
return nil
|
||||
@@ -290,8 +290,9 @@ func (s *RemoteRuleSet) fetchOnce(ctx context.Context, startContext *adapter.HTT
|
||||
s.lastEtag = eTagHeader
|
||||
}
|
||||
s.lastUpdated = time.Now()
|
||||
if s.cacheFile != nil {
|
||||
err = s.cacheFile.SaveRuleSet(s.options.Tag, &adapter.SavedRuleSet{
|
||||
cacheFile := service.FromContext[adapter.CacheFile](s.ctx)
|
||||
if cacheFile != nil {
|
||||
err = cacheFile.SaveRuleSet(s.options.Tag, &adapter.SavedRuleSet{
|
||||
LastUpdated: s.lastUpdated,
|
||||
Content: content,
|
||||
LastEtag: s.lastEtag,
|
||||
|
||||
Reference in New Issue
Block a user