mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-13 20:28:32 +10:00
Compare commits
19 Commits
v1.9.0-rc.
...
v1.9.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1482baa771 | ||
|
|
ee280ba43c | ||
|
|
2c24391e7b | ||
|
|
532d408b70 | ||
|
|
2e34207d30 | ||
|
|
73c8b82fcf | ||
|
|
ec081b1428 | ||
|
|
afbf1d4285 | ||
|
|
b84ac3f771 | ||
|
|
183c8b241b | ||
|
|
6897a2e9ed | ||
|
|
31cff044dd | ||
|
|
7bd3df223f | ||
|
|
a7f080bede | ||
|
|
a6ddd48e37 | ||
|
|
bddea6dd29 | ||
|
|
7f4b256872 | ||
|
|
56e2ada4d6 | ||
|
|
c32ad152b6 |
11
.github/workflows/linux.yml
vendored
11
.github/workflows/linux.yml
vendored
@@ -17,21 +17,12 @@ jobs:
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.22
|
||||
- name: Extract signing key
|
||||
run: |-
|
||||
mkdir -p $HOME/.gnupg
|
||||
cat > $HOME/.gnupg/sagernet.key <<EOF
|
||||
${{ secrets.GPG_KEY }}
|
||||
EOF
|
||||
- name: Publish release
|
||||
uses: goreleaser/goreleaser-action@v5
|
||||
with:
|
||||
distribution: goreleaser-pro
|
||||
version: latest
|
||||
args: release -f .goreleaser.fury.yaml --clean
|
||||
args: goreleaser release -f .goreleaser.fury.yaml --clean
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
|
||||
NFPM_KEY_PATH: ${{ env.Home }}/.gnupg/sagernet.key
|
||||
NFPM_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
|
||||
@@ -50,25 +50,16 @@ nfpms:
|
||||
dst: /etc/sing-box/config.json
|
||||
type: config
|
||||
- src: release/config/sing-box.service
|
||||
dst: /usr/lib/systemd/system/sing-box.service
|
||||
dst: /etc/systemd/system/sing-box.service
|
||||
- src: release/config/sing-box@.service
|
||||
dst: /usr/lib/systemd/system/sing-box@.service
|
||||
dst: /etc/systemd/system/sing-box@.service
|
||||
- src: LICENSE
|
||||
dst: /usr/share/licenses/sing-box/LICENSE
|
||||
deb:
|
||||
signature:
|
||||
key_file: "{{ .Env.NFPM_KEY_PATH }}"
|
||||
fields:
|
||||
Bugs: https://github.com/SagerNet/sing-box/issues
|
||||
rpm:
|
||||
signature:
|
||||
key_file: "{{ .Env.NFPM_KEY_PATH }}"
|
||||
conflicts:
|
||||
- sing-box-beta
|
||||
- id: package_beta
|
||||
<<: *template
|
||||
package_name: sing-box-beta
|
||||
file_name_template: '{{ .ProjectName }}-beta_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
@@ -80,8 +71,10 @@ furies:
|
||||
- account: sagernet
|
||||
ids:
|
||||
- package
|
||||
disable: "{{ not (not .Prerelease) }}"
|
||||
skip: |-
|
||||
{{ eq .Prerelease "" }}
|
||||
- account: sagernet
|
||||
ids:
|
||||
- package_beta
|
||||
disable: "{{ not .Prerelease }}"
|
||||
skip: |-
|
||||
{{ ne .Prerelease "" }}
|
||||
|
||||
@@ -48,8 +48,8 @@ builds:
|
||||
- with_clash_api
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GOROOT={{ .Env.GOPATH }}/go1.20.14
|
||||
gobinary: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
|
||||
- GOROOT=/nix/store/cpfvjwc7d5hai3iar78h86iwnvgppjrg-go-1.20.14/share/go
|
||||
gobinary: /nix/store/cpfvjwc7d5hai3iar78h86iwnvgppjrg-go-1.20.14/bin/go
|
||||
targets:
|
||||
- windows_amd64_v1
|
||||
- windows_386
|
||||
@@ -128,16 +128,14 @@ nfpms:
|
||||
dst: /etc/sing-box/config.json
|
||||
type: config
|
||||
- src: release/config/sing-box.service
|
||||
dst: /usr/lib/systemd/system/sing-box.service
|
||||
dst: /etc/systemd/system/sing-box.service
|
||||
- src: release/config/sing-box@.service
|
||||
dst: /usr/lib/systemd/system/sing-box@.service
|
||||
dst: /etc/systemd/system/sing-box@.service
|
||||
- src: LICENSE
|
||||
dst: /usr/share/licenses/sing-box/LICENSE
|
||||
deb:
|
||||
signature:
|
||||
key_file: "{{ .Env.NFPM_KEY_PATH }}"
|
||||
fields:
|
||||
Bugs: https://github.com/SagerNet/sing-box/issues
|
||||
rpm:
|
||||
signature:
|
||||
key_file: "{{ .Env.NFPM_KEY_PATH }}"
|
||||
|
||||
5
Makefile
5
Makefile
@@ -64,7 +64,7 @@ proto_install:
|
||||
go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
|
||||
release:
|
||||
go run ./cmd/internal/build goreleaser release --clean --skip publish
|
||||
go run ./cmd/internal/build goreleaser release --clean --skip publish --skip fury
|
||||
mkdir dist/release
|
||||
mv dist/*.tar.gz \
|
||||
dist/*.zip \
|
||||
@@ -81,13 +81,14 @@ release_repo:
|
||||
go run ./cmd/internal/build goreleaser release -f .goreleaser.fury.yaml --clean
|
||||
|
||||
release_install:
|
||||
go install -v github.com/goreleaser/goreleaser@latest
|
||||
go install -v github.com/tcnksm/ghr@latest
|
||||
|
||||
update_android_version:
|
||||
go run ./cmd/internal/update_android_version
|
||||
|
||||
build_android:
|
||||
cd ../sing-box-for-android && ./gradlew :app:clean :app:assemblePlayRelease :app:assembleOtherRelease && ./gradlew --stop
|
||||
cd ../sing-box-for-android && ./gradlew :app:assemblePlayRelease && ./gradlew :app:assembleOtherRelease && ./gradlew --stop
|
||||
|
||||
upload_android:
|
||||
mkdir -p dist/release_android
|
||||
|
||||
@@ -66,7 +66,6 @@ func (c *InboundContext) ResetRuleCache() {
|
||||
c.SourcePortMatch = false
|
||||
c.DestinationAddressMatch = false
|
||||
c.DestinationPortMatch = false
|
||||
c.DidMatch = false
|
||||
}
|
||||
|
||||
type inboundContextKey struct{}
|
||||
|
||||
@@ -71,7 +71,6 @@ func RouterFromContext(ctx context.Context) Router {
|
||||
|
||||
type HeadlessRule interface {
|
||||
Match(metadata *InboundContext) bool
|
||||
String() string
|
||||
}
|
||||
|
||||
type Rule interface {
|
||||
@@ -80,6 +79,7 @@ type Rule interface {
|
||||
Type() string
|
||||
UpdateGeosite() error
|
||||
Outbound() string
|
||||
String() string
|
||||
}
|
||||
|
||||
type DNSRule interface {
|
||||
|
||||
4
box.go
4
box.go
@@ -235,7 +235,7 @@ func (s *Box) Start() error {
|
||||
}
|
||||
|
||||
func (s *Box) preStart() error {
|
||||
monitor := taskmonitor.New(s.logger, C.StartTimeout)
|
||||
monitor := taskmonitor.New(s.logger, C.DefaultStartTimeout)
|
||||
monitor.Start("start logger")
|
||||
err := s.logFactory.Start()
|
||||
monitor.Finish()
|
||||
@@ -331,7 +331,7 @@ func (s *Box) Close() error {
|
||||
default:
|
||||
close(s.done)
|
||||
}
|
||||
monitor := taskmonitor.New(s.logger, C.StopTimeout)
|
||||
monitor := taskmonitor.New(s.logger, C.DefaultStopTimeout)
|
||||
var errors error
|
||||
for serviceName, service := range s.postServices {
|
||||
monitor.Start("close ", serviceName)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *Box) startOutbounds() error {
|
||||
monitor := taskmonitor.New(s.logger, C.StartTimeout)
|
||||
monitor := taskmonitor.New(s.logger, C.DefaultStartTimeout)
|
||||
outboundTags := make(map[adapter.Outbound]string)
|
||||
outbounds := make(map[string]adapter.Outbound)
|
||||
for i, outboundToStart := range s.outbounds {
|
||||
|
||||
Submodule clients/android updated: 288a6f34db...5feba135c4
Submodule clients/apple updated: 1c5bc23a25...7098a84187
@@ -1,86 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/srs"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/route"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/json"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var flagRuleSetMatchFormat string
|
||||
|
||||
var commandRuleSetMatch = &cobra.Command{
|
||||
Use: "match <rule-set path> <domain>",
|
||||
Short: "Check if a domain matches the rule set",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := ruleSetMatch(args[0], args[1])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
commandRuleSetMatch.Flags().StringVarP(&flagRuleSetMatchFormat, "format", "f", "source", "rule-set format")
|
||||
commandRuleSet.AddCommand(commandRuleSetMatch)
|
||||
}
|
||||
|
||||
func ruleSetMatch(sourcePath string, domain string) error {
|
||||
var (
|
||||
reader io.Reader
|
||||
err error
|
||||
)
|
||||
if sourcePath == "stdin" {
|
||||
reader = os.Stdin
|
||||
} else {
|
||||
reader, err = os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read rule-set")
|
||||
}
|
||||
}
|
||||
content, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read rule-set")
|
||||
}
|
||||
var plainRuleSet option.PlainRuleSet
|
||||
switch flagRuleSetMatchFormat {
|
||||
case C.RuleSetFormatSource:
|
||||
var compat option.PlainRuleSetCompat
|
||||
compat, err = json.UnmarshalExtended[option.PlainRuleSetCompat](content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
plainRuleSet = compat.Upgrade()
|
||||
case C.RuleSetFormatBinary:
|
||||
plainRuleSet, err = srs.Read(bytes.NewReader(content), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return E.New("unknown rule set format: ", flagRuleSetMatchFormat)
|
||||
}
|
||||
for i, ruleOptions := range plainRuleSet.Rules {
|
||||
var currentRule adapter.HeadlessRule
|
||||
currentRule, err = route.NewHeadlessRule(nil, ruleOptions)
|
||||
if err != nil {
|
||||
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
||||
}
|
||||
if currentRule.Match(&adapter.InboundContext{
|
||||
Domain: domain,
|
||||
}) {
|
||||
println("match rules.[", i, "]: "+currentRule.String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -199,7 +199,7 @@ func run() error {
|
||||
}
|
||||
|
||||
func closeMonitor(ctx context.Context) {
|
||||
time.Sleep(C.FatalStopTimeout)
|
||||
time.Sleep(C.DefaultStopFatalTimeout)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
@@ -63,9 +63,6 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi
|
||||
} else {
|
||||
dialer.Timeout = C.TCPTimeout
|
||||
}
|
||||
// TODO: Add an option to customize the keep alive period
|
||||
dialer.KeepAlive = C.TCPKeepAliveInitial
|
||||
dialer.Control = control.Append(dialer.Control, control.SetKeepAlivePeriod(C.TCPKeepAliveInitial, C.TCPKeepAliveInterval))
|
||||
var udpFragment bool
|
||||
if options.UDPFragment != nil {
|
||||
udpFragment = *options.UDPFragment
|
||||
|
||||
@@ -3,18 +3,15 @@ package constant
|
||||
import "time"
|
||||
|
||||
const (
|
||||
TCPKeepAliveInitial = 10 * time.Minute
|
||||
TCPKeepAliveInterval = 75 * time.Second
|
||||
TCPTimeout = 5 * time.Second
|
||||
ReadPayloadTimeout = 300 * time.Millisecond
|
||||
DNSTimeout = 10 * time.Second
|
||||
QUICTimeout = 30 * time.Second
|
||||
STUNTimeout = 15 * time.Second
|
||||
UDPTimeout = 5 * time.Minute
|
||||
DefaultURLTestInterval = 3 * time.Minute
|
||||
DefaultURLTestIdleTimeout = 30 * time.Minute
|
||||
StartTimeout = 10 * time.Second
|
||||
StopTimeout = 5 * time.Second
|
||||
FatalStopTimeout = 10 * time.Second
|
||||
FakeIPMetadataSaveInterval = 10 * time.Second
|
||||
TCPTimeout = 5 * time.Second
|
||||
ReadPayloadTimeout = 300 * time.Millisecond
|
||||
DNSTimeout = 10 * time.Second
|
||||
QUICTimeout = 30 * time.Second
|
||||
STUNTimeout = 15 * time.Second
|
||||
UDPTimeout = 5 * time.Minute
|
||||
DefaultURLTestInterval = 3 * time.Minute
|
||||
DefaultURLTestIdleTimeout = 30 * time.Minute
|
||||
DefaultStartTimeout = 10 * time.Second
|
||||
DefaultStopTimeout = 5 * time.Second
|
||||
DefaultStopFatalTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
@@ -2,31 +2,6 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
#### 1.9.0-rc.11
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.8.11
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.8.10
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.9.0-beta.17
|
||||
|
||||
* Update `quic-go` to v0.42.0
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.9.0-beta.16
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
_Our Testflight distribution has been temporarily blocked by Apple (possibly due to too many beta versions)
|
||||
and you cannot join the test, install or update the sing-box beta app right now.
|
||||
Please wait patiently for processing._
|
||||
|
||||
#### 1.9.0-beta.14
|
||||
|
||||
* Update gVisor to 20240212.0-65-g71212d503
|
||||
|
||||
@@ -15,11 +15,7 @@ platform-specific function implementation, such as TUN transparent proxy impleme
|
||||
## :material-download: Download
|
||||
|
||||
* [App Store](https://apps.apple.com/us/app/sing-box/id6451272673)
|
||||
* ~~[TestFlight (Beta)](https://testflight.apple.com/join/AcqO44FH)~~
|
||||
|
||||
_Our Testflight distribution has been temporarily blocked by Apple (possibly due to too many beta versions)
|
||||
and you cannot join the test, install or update the sing-box beta app right now.
|
||||
Please wait patiently for processing._
|
||||
* [TestFlight (Beta)](https://testflight.apple.com/join/AcqO44FH)
|
||||
|
||||
## :material-file-download: Download (macOS standalone version)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ icon: material/package
|
||||
=== ":material-debian: Debian / APT"
|
||||
|
||||
```bash
|
||||
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc
|
||||
sudo curl -fsSL https://deb.sagernet.org/gpg.key -o /etc/apt/keyrings/sagernet.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/sagernet.asc
|
||||
echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/sagernet.asc] https://deb.sagernet.org/ * *" | \
|
||||
sudo tee /etc/apt/sources.list.d/sagernet.list > /dev/null
|
||||
@@ -21,7 +21,7 @@ icon: material/package
|
||||
|
||||
```bash
|
||||
sudo dnf -y install dnf-plugins-core
|
||||
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo dnf config-manager --add-repo https://sing-box.app/rpm.repo
|
||||
sudo dnf install sing-box # or sing-box-beta
|
||||
```
|
||||
|
||||
@@ -29,7 +29,7 @@ icon: material/package
|
||||
|
||||
```bash
|
||||
sudo yum install -y yum-utils
|
||||
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo yum-config-manager --add-repo https://sing-box.app/rpm.repo
|
||||
sudo yum install sing-box # or sing-box-beta
|
||||
```
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ icon: material/package
|
||||
=== ":material-debian: Debian / APT"
|
||||
|
||||
```bash
|
||||
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc
|
||||
sudo curl -fsSL https://deb.sagernet.org/gpg.key -o /etc/apt/keyrings/sagernet.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/sagernet.asc
|
||||
echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/sagernet.asc] https://deb.sagernet.org/ * *" | \
|
||||
sudo tee /etc/apt/sources.list.d/sagernet.list > /dev/null
|
||||
@@ -21,7 +21,7 @@ icon: material/package
|
||||
|
||||
```bash
|
||||
sudo dnf -y install dnf-plugins-core
|
||||
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo dnf config-manager --add-repo https://sing-box.app/rpm.repo
|
||||
sudo dnf install sing-box # or sing-box-beta
|
||||
```
|
||||
|
||||
@@ -29,7 +29,7 @@ icon: material/package
|
||||
|
||||
```bash
|
||||
sudo yum install -y yum-utils
|
||||
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo yum-config-manager --add-repo https://sing-box.app/rpm.repo
|
||||
sudo yum install sing-box # or sing-box-beta
|
||||
```
|
||||
|
||||
|
||||
6
docs/installation/tools/rpm.repo
Normal file
6
docs/installation/tools/rpm.repo
Normal file
@@ -0,0 +1,6 @@
|
||||
[sing-box]
|
||||
name=sing-box
|
||||
baseurl=https://rpm.sagernet.org/
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgkey=https://deb.sagernet.org/gpg.key
|
||||
@@ -1,8 +0,0 @@
|
||||
[sing-box]
|
||||
name=sing-box
|
||||
baseurl=https://rpm.sagernet.org/
|
||||
metalink=https://sing-box.app/sing-box.repo
|
||||
enabled=1
|
||||
repo_gpgcheck=1
|
||||
gpgcheck=1
|
||||
gpgkey=https://sing-box.app/gpg.key
|
||||
@@ -380,8 +380,7 @@ flowchart TB
|
||||
"mode": "and",
|
||||
"rules": [
|
||||
{
|
||||
"rule_set": "geosite-geolocation-!cn",
|
||||
"invert": true
|
||||
"rule_set": "geosite-geolocation-!cn"
|
||||
},
|
||||
{
|
||||
"rule_set": "geoip-cn"
|
||||
@@ -463,8 +462,7 @@ flowchart TB
|
||||
"mode": "and",
|
||||
"rules": [
|
||||
{
|
||||
"rule_set": "geosite-geolocation-!cn",
|
||||
"invert": true
|
||||
"rule_set": "geosite-geolocation-!cn"
|
||||
},
|
||||
{
|
||||
"rule_set": "geoip-cn"
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/sagernet/bbolt"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
)
|
||||
@@ -59,13 +58,12 @@ func (c *CacheFile) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
|
||||
}
|
||||
|
||||
func (c *CacheFile) FakeIPSaveMetadataAsync(metadata *adapter.FakeIPMetadata) {
|
||||
if c.saveMetadataTimer == nil {
|
||||
c.saveMetadataTimer = time.AfterFunc(C.FakeIPMetadataSaveInterval, func() {
|
||||
_ = c.FakeIPSaveMetadata(metadata)
|
||||
})
|
||||
} else {
|
||||
c.saveMetadataTimer.Reset(C.FakeIPMetadataSaveInterval)
|
||||
if timer := c.saveMetadataTimer; timer != nil {
|
||||
timer.Stop()
|
||||
}
|
||||
c.saveMetadataTimer = time.AfterFunc(10*time.Second, func() {
|
||||
_ = c.FakeIPSaveMetadata(metadata)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/sagernet/sing-box"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/process"
|
||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
@@ -74,7 +75,7 @@ func (s *platformInterfaceStub) UsePlatformInterfaceGetter() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) Interfaces() ([]control.Interface, error) {
|
||||
func (s *platformInterfaceStub) Interfaces() ([]platform.NetworkInterface, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package platform
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/process"
|
||||
@@ -19,9 +20,16 @@ type Interface interface {
|
||||
UsePlatformDefaultInterfaceMonitor() bool
|
||||
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
|
||||
UsePlatformInterfaceGetter() bool
|
||||
Interfaces() ([]control.Interface, error)
|
||||
Interfaces() ([]NetworkInterface, error)
|
||||
UnderNetworkExtension() bool
|
||||
ClearDNSCache()
|
||||
ReadWIFIState() adapter.WIFIState
|
||||
process.Searcher
|
||||
}
|
||||
|
||||
type NetworkInterface struct {
|
||||
Index int
|
||||
MTU int
|
||||
Name string
|
||||
Addresses []netip.Prefix
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func (s *BoxService) Close() error {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
case <-time.After(C.FatalStopTimeout):
|
||||
case <-time.After(C.DefaultStopFatalTimeout):
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
@@ -192,14 +192,14 @@ func (w *platformInterfaceWrapper) UsePlatformInterfaceGetter() bool {
|
||||
return w.iif.UsePlatformInterfaceGetter()
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) Interfaces() ([]control.Interface, error) {
|
||||
func (w *platformInterfaceWrapper) Interfaces() ([]platform.NetworkInterface, error) {
|
||||
interfaceIterator, err := w.iif.GetInterfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var interfaces []control.Interface
|
||||
var interfaces []platform.NetworkInterface
|
||||
for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) {
|
||||
interfaces = append(interfaces, control.Interface{
|
||||
interfaces = append(interfaces, platform.NetworkInterface{
|
||||
Index: int(netInterface.Index),
|
||||
MTU: int(netInterface.MTU),
|
||||
Name: netInterface.Name,
|
||||
|
||||
39
go.mod
39
go.mod
@@ -11,29 +11,29 @@ require (
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/gofrs/uuid/v5 v5.1.0
|
||||
github.com/gofrs/uuid/v5 v5.0.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/libdns/cloudflare v0.1.0
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/mholt/acmez v1.2.0
|
||||
github.com/miekg/dns v1.1.59
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/ooni/go-libtor v1.1.8
|
||||
github.com/oschwald/maxminddb-golang v1.12.0
|
||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
||||
github.com/sagernet/gomobile v0.1.3
|
||||
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311
|
||||
github.com/sagernet/quic-go v0.42.0-beta.3
|
||||
github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f
|
||||
github.com/sagernet/quic-go v0.41.0-beta.2
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.4.0-beta.18
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.16
|
||||
github.com/sagernet/sing v0.4.0-beta.3
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.15
|
||||
github.com/sagernet/sing-mux v0.2.0
|
||||
github.com/sagernet/sing-quic v0.1.13-beta.1
|
||||
github.com/sagernet/sing-quic v0.1.9-beta.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||
github.com/sagernet/sing-shadowtls v0.1.4
|
||||
github.com/sagernet/sing-tun v0.2.7-beta.1
|
||||
github.com/sagernet/sing-tun v0.2.5-beta.1
|
||||
github.com/sagernet/sing-vmess v0.1.8
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
||||
@@ -44,11 +44,11 @@ require (
|
||||
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.22.0
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/sys v0.19.0
|
||||
golang.org/x/crypto v0.21.0
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||
google.golang.org/grpc v1.63.2
|
||||
google.golang.org/grpc v1.62.1
|
||||
google.golang.org/protobuf v1.33.0
|
||||
howett.net/plist v1.0.1
|
||||
)
|
||||
@@ -64,6 +64,7 @@ require (
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
@@ -71,7 +72,7 @@ require (
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/libdns/libdns v0.2.2 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||
@@ -79,18 +80,18 @@ require (
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.20.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.2.1 // indirect
|
||||
|
||||
87
go.sum
87
go.sum
@@ -34,11 +34,14 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gofrs/uuid/v5 v5.1.0 h1:S5rqVKIigghZTCBKPCw0Y+bXkn26K3TB5mvQq2Ix8dk=
|
||||
github.com/gofrs/uuid/v5 v5.1.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
||||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
@@ -62,17 +65,17 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
|
||||
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
|
||||
github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
|
||||
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
|
||||
github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic=
|
||||
github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8=
|
||||
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
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.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
||||
@@ -97,31 +100,31 @@ github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQ
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
|
||||
github.com/sagernet/gomobile v0.1.3 h1:ohjIb1Ou2+1558PnZour3od69suSuvkdSVOlO1tC4B8=
|
||||
github.com/sagernet/gomobile v0.1.3/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
|
||||
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311 h1:eUQ6kJZXK77xYZeeNrBb/7JMv0S0Wkk7EpmKUb3fsfc=
|
||||
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311/go.mod h1:mDrXZSv401qiaFiiIUC59Zp4VG5f4nqXFqDmp5o3hYI=
|
||||
github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f h1:7hj/CcCkUiC6gfhX4D+QNyodmhfurW2L2Q4qzJ1bPnI=
|
||||
github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f/go.mod h1:bLmnT/4M4+yKB6F7JtRsbUr+YJ64yXwFIygjyYDFQzQ=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/quic-go v0.42.0-beta.3 h1:cspu1Uh1KriiDmW42OaPYokeGZT2OyfIcRMV2BdNtEo=
|
||||
github.com/sagernet/quic-go v0.42.0-beta.3/go.mod h1:lf8OYop+fMxIlrfM/ZHpENt/7ZD4JaVNqMhOlq2QMwg=
|
||||
github.com/sagernet/quic-go v0.41.0-beta.2 h1:NtFC1Ief+SYJkfRq68D1OEqZQTNh2jYSpyRLhjT+m6U=
|
||||
github.com/sagernet/quic-go v0.41.0-beta.2/go.mod h1:X10Mf9DVHuSEReOLov/XuflD13MVLH3WtppVVFnSItU=
|
||||
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.4.0-beta.18 h1:oK+pvyXnFwxwvQkeUqgxIeATiMHcrH5doLKKDGNmQkU=
|
||||
github.com/sagernet/sing v0.4.0-beta.18/go.mod h1:PFQKbElc2Pke7faBLv8oEba5ehtKO21Ho+TkYemTI3Y=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.16 h1:bzd4B8eHD7/WO3HrYknvgE8A56/R3n5oXBjNF97iPzQ=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.16/go.mod h1:XU6Vqr6aHcMz/34Fcv8jmXpRCEuShzW+B7Qg1Xe1nxY=
|
||||
github.com/sagernet/sing v0.4.0-beta.3 h1:TYA4DJtxs0dWDG6ahjU/Fh+eg6vintiqGjXN4h9BbiA=
|
||||
github.com/sagernet/sing v0.4.0-beta.3/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.15 h1:mriNN7ZjnPYlmoZ31HoDOkL9IzSO8RdkqegZ9DhAe30=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.15/go.mod h1:gfs585rEu+ZgsXJJiecEIK5avrF5SYlCAbFfZ1B66hs=
|
||||
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
||||
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-quic v0.1.13-beta.1 h1:/y4Io8m+C9CFUwgMqV2gWjT11I5fCROB0Z3afhhS66c=
|
||||
github.com/sagernet/sing-quic v0.1.13-beta.1/go.mod h1:Bny0k0Puf7yxhtXfovVyz3gfkHvS1T+/ieKLPhfnhY4=
|
||||
github.com/sagernet/sing-quic v0.1.9-beta.1 h1:rCmgLUq2d4EA643EAvjbfUYYVMPCss0GpmS4pJCT2Lw=
|
||||
github.com/sagernet/sing-quic v0.1.9-beta.1/go.mod h1:F4AXCZiwtRtYdLUTjVMO6elTpA/lLJe17sFlHhHmDVw=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
||||
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.2.7-beta.1 h1:rudjVa4Gjg9f3uYaUwH8qK5uMxl7MOIiYlmGhTqWgXI=
|
||||
github.com/sagernet/sing-tun v0.2.7-beta.1/go.mod h1:9pauo20NImopbZ3ixnJs6m5CbzhJitfvii6w4Rk3QMg=
|
||||
github.com/sagernet/sing-tun v0.2.5-beta.1 h1:a6KnZR1XbsEaowAR6bC32y86WPoZm3We57NGzZO3ryo=
|
||||
github.com/sagernet/sing-tun v0.2.5-beta.1/go.mod h1:lkefC8gty7FTuzz9ZoNASueutIhClEz7LHjFK3BLGco=
|
||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
||||
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
@@ -134,6 +137,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/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
|
||||
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
|
||||
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=
|
||||
@@ -163,18 +168,17 @@ 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -184,10 +188,10 @@ 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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
@@ -195,14 +199,17 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
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.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -5,9 +5,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
@@ -18,9 +16,6 @@ func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
|
||||
bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort)
|
||||
var tcpListener net.Listener
|
||||
var listenConfig net.ListenConfig
|
||||
// TODO: Add an option to customize the keep alive period
|
||||
listenConfig.KeepAlive = C.TCPKeepAliveInitial
|
||||
listenConfig.Control = control.Append(listenConfig.Control, control.SetKeepAlivePeriod(C.TCPKeepAliveInitial, C.TCPKeepAliveInterval))
|
||||
if a.listenOptions.TCPMultiPath {
|
||||
if !go121Available {
|
||||
return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.")
|
||||
|
||||
@@ -153,7 +153,7 @@ func (t *Tun) Start() error {
|
||||
tunInterface tun.Tun
|
||||
err error
|
||||
)
|
||||
monitor := taskmonitor.New(t.logger, C.StartTimeout)
|
||||
monitor := taskmonitor.New(t.logger, C.DefaultStartTimeout)
|
||||
monitor.Start("open tun interface")
|
||||
if t.platformInterface != nil {
|
||||
tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)
|
||||
|
||||
112
ntp/service.go
Normal file
112
ntp/service.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package ntp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
"github.com/sagernet/sing-box/common/settings"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"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"
|
||||
"github.com/sagernet/sing/common/ntp"
|
||||
)
|
||||
|
||||
var _ ntp.TimeService = (*Service)(nil)
|
||||
|
||||
type Service struct {
|
||||
ctx context.Context
|
||||
cancel common.ContextCancelCauseFunc
|
||||
server M.Socksaddr
|
||||
writeToSystem bool
|
||||
dialer N.Dialer
|
||||
logger logger.Logger
|
||||
ticker *time.Ticker
|
||||
clockOffset time.Duration
|
||||
}
|
||||
|
||||
func NewService(ctx context.Context, router adapter.Router, logger logger.Logger, options option.NTPOptions) (*Service, error) {
|
||||
ctx, cancel := common.ContextWithCancelCause(ctx)
|
||||
server := M.ParseSocksaddrHostPort(options.Server, options.ServerPort)
|
||||
if server.Port == 0 {
|
||||
server.Port = 123
|
||||
}
|
||||
var interval time.Duration
|
||||
if options.Interval > 0 {
|
||||
interval = time.Duration(options.Interval)
|
||||
} else {
|
||||
interval = 30 * time.Minute
|
||||
}
|
||||
outboundDialer, err := dialer.New(router, options.DialerOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Service{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
server: server,
|
||||
writeToSystem: options.WriteToSystem,
|
||||
dialer: outboundDialer,
|
||||
logger: logger,
|
||||
ticker: time.NewTicker(interval),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Start() error {
|
||||
err := s.update()
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize time")
|
||||
}
|
||||
s.logger.Info("updated time: ", s.TimeFunc()().Local().Format(C.TimeLayout))
|
||||
go s.loopUpdate()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Close() error {
|
||||
s.ticker.Stop()
|
||||
s.cancel(os.ErrClosed)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) TimeFunc() func() time.Time {
|
||||
return func() time.Time {
|
||||
return time.Now().Add(s.clockOffset)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) loopUpdate() {
|
||||
for {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
case <-s.ticker.C:
|
||||
}
|
||||
err := s.update()
|
||||
if err == nil {
|
||||
s.logger.Debug("updated time: ", s.TimeFunc()().Local().Format(C.TimeLayout))
|
||||
} else {
|
||||
s.logger.Warn("update time: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) update() error {
|
||||
response, err := ntp.Exchange(s.ctx, s.dialer, s.server)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.clockOffset = response.ClockOffset
|
||||
if s.writeToSystem {
|
||||
writeErr := settings.SetSystemTime(s.TimeFunc()())
|
||||
if writeErr != nil {
|
||||
s.logger.Warn("write time to system: ", writeErr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2,8 +2,9 @@ package option
|
||||
|
||||
type NTPOptions struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Server string `json:"server,omitempty"`
|
||||
ServerPort uint16 `json:"server_port,omitempty"`
|
||||
Interval Duration `json:"interval,omitempty"`
|
||||
WriteToSystem bool `json:"write_to_system,omitempty"`
|
||||
ServerOptions
|
||||
DialerOptions
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
||||
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
|
||||
fallbackDelay: time.Duration(options.FallbackDelay),
|
||||
dialer: outboundDialer,
|
||||
loopBack: newLoopBackDetector(router),
|
||||
loopBack: newLoopBackDetector(),
|
||||
}
|
||||
if options.ProxyProtocol != 0 {
|
||||
return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0")
|
||||
@@ -148,7 +148,7 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination)
|
||||
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn))
|
||||
if originDestination != destination {
|
||||
conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
|
||||
}
|
||||
@@ -156,14 +156,14 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
|
||||
}
|
||||
|
||||
func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||
if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
|
||||
if h.loopBack.CheckConn(metadata.Source.AddrPort()) {
|
||||
return E.New("reject loopback connection to ", metadata.Destination)
|
||||
}
|
||||
return NewConnection(ctx, h, conn, metadata)
|
||||
}
|
||||
|
||||
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
|
||||
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort()) {
|
||||
return E.New("reject loopback packet connection to ", metadata.Destination)
|
||||
}
|
||||
return NewPacketConnection(ctx, h, conn, metadata)
|
||||
|
||||
@@ -5,95 +5,63 @@ import (
|
||||
"net/netip"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type loopBackDetector struct {
|
||||
router adapter.Router
|
||||
connAccess sync.RWMutex
|
||||
packetConnAccess sync.RWMutex
|
||||
connMap map[netip.AddrPort]netip.AddrPort
|
||||
packetConnMap map[uint16]uint16
|
||||
connMap map[netip.AddrPort]bool
|
||||
packetConnMap map[netip.AddrPort]bool
|
||||
}
|
||||
|
||||
func newLoopBackDetector(router adapter.Router) *loopBackDetector {
|
||||
func newLoopBackDetector() *loopBackDetector {
|
||||
return &loopBackDetector{
|
||||
router: router,
|
||||
connMap: make(map[netip.AddrPort]netip.AddrPort),
|
||||
packetConnMap: make(map[uint16]uint16),
|
||||
connMap: make(map[netip.AddrPort]bool),
|
||||
packetConnMap: make(map[netip.AddrPort]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
|
||||
source := M.AddrPortFromNet(conn.LocalAddr())
|
||||
if !source.IsValid() {
|
||||
connAddr := M.AddrPortFromNet(conn.LocalAddr())
|
||||
if !connAddr.IsValid() {
|
||||
return conn
|
||||
}
|
||||
if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
|
||||
if !source.Addr().IsLoopback() {
|
||||
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
|
||||
if err != nil {
|
||||
return conn
|
||||
}
|
||||
}
|
||||
if !N.IsPublicAddr(source.Addr()) {
|
||||
return conn
|
||||
}
|
||||
l.packetConnAccess.Lock()
|
||||
l.packetConnMap[source.Port()] = M.AddrPortFromNet(conn.RemoteAddr()).Port()
|
||||
l.packetConnMap[connAddr] = true
|
||||
l.packetConnAccess.Unlock()
|
||||
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connPort: source.Port()}
|
||||
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connAddr: connAddr}
|
||||
} else {
|
||||
l.connAccess.Lock()
|
||||
l.connMap[source] = M.AddrPortFromNet(conn.RemoteAddr())
|
||||
l.connMap[connAddr] = true
|
||||
l.connAccess.Unlock()
|
||||
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: source}
|
||||
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: connAddr}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn, destination M.Socksaddr) N.NetPacketConn {
|
||||
source := M.AddrPortFromNet(conn.LocalAddr())
|
||||
if !source.IsValid() {
|
||||
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn) N.NetPacketConn {
|
||||
connAddr := M.AddrPortFromNet(conn.LocalAddr())
|
||||
if !connAddr.IsValid() {
|
||||
return conn
|
||||
}
|
||||
if !source.Addr().IsLoopback() {
|
||||
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
|
||||
if err != nil {
|
||||
return conn
|
||||
}
|
||||
}
|
||||
l.packetConnAccess.Lock()
|
||||
l.packetConnMap[source.Port()] = destination.AddrPort().Port()
|
||||
l.packetConnMap[connAddr] = true
|
||||
l.packetConnAccess.Unlock()
|
||||
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connPort: source.Port()}
|
||||
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connAddr: connAddr}
|
||||
}
|
||||
|
||||
func (l *loopBackDetector) CheckConn(source netip.AddrPort, local netip.AddrPort) bool {
|
||||
func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
|
||||
l.connAccess.RLock()
|
||||
defer l.connAccess.RUnlock()
|
||||
destination, loaded := l.connMap[source]
|
||||
return loaded && destination != local
|
||||
return l.connMap[connAddr]
|
||||
}
|
||||
|
||||
func (l *loopBackDetector) CheckPacketConn(source netip.AddrPort, local netip.AddrPort) bool {
|
||||
if !source.IsValid() {
|
||||
return false
|
||||
}
|
||||
if !source.Addr().IsLoopback() {
|
||||
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if N.IsPublicAddr(source.Addr()) {
|
||||
return false
|
||||
}
|
||||
func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
|
||||
l.packetConnAccess.RLock()
|
||||
defer l.packetConnAccess.RUnlock()
|
||||
destinationPort, loaded := l.packetConnMap[source.Port()]
|
||||
return loaded && destinationPort != local.Port()
|
||||
return l.packetConnMap[connAddr]
|
||||
}
|
||||
|
||||
type loopBackDetectWrapper struct {
|
||||
@@ -127,14 +95,14 @@ func (w *loopBackDetectWrapper) Upstream() any {
|
||||
type loopBackDetectPacketWrapper struct {
|
||||
N.NetPacketConn
|
||||
detector *loopBackDetector
|
||||
connPort uint16
|
||||
connAddr netip.AddrPort
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func (w *loopBackDetectPacketWrapper) Close() error {
|
||||
w.closeOnce.Do(func() {
|
||||
w.detector.packetConnAccess.Lock()
|
||||
delete(w.detector.packetConnMap, w.connPort)
|
||||
delete(w.detector.packetConnMap, w.connAddr)
|
||||
w.detector.packetConnAccess.Unlock()
|
||||
})
|
||||
return w.NetPacketConn.Close()
|
||||
@@ -160,14 +128,14 @@ type abstractUDPConn interface {
|
||||
type loopBackDetectUDPWrapper struct {
|
||||
abstractUDPConn
|
||||
detector *loopBackDetector
|
||||
connPort uint16
|
||||
connAddr netip.AddrPort
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func (w *loopBackDetectUDPWrapper) Close() error {
|
||||
w.closeOnce.Do(func() {
|
||||
w.detector.packetConnAccess.Lock()
|
||||
delete(w.detector.packetConnMap, w.connPort)
|
||||
delete(w.detector.packetConnMap, w.connAddr)
|
||||
w.detector.packetConnAccess.Unlock()
|
||||
})
|
||||
return w.abstractUDPConn.Close()
|
||||
|
||||
54
route/interface_finder.go
Normal file
54
route/interface_finder.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing/common/control"
|
||||
)
|
||||
|
||||
var _ control.InterfaceFinder = (*myInterfaceFinder)(nil)
|
||||
|
||||
type myInterfaceFinder struct {
|
||||
interfaces []net.Interface
|
||||
}
|
||||
|
||||
func (f *myInterfaceFinder) update() error {
|
||||
ifs, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.interfaces = ifs
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *myInterfaceFinder) updateInterfaces(interfaces []net.Interface) {
|
||||
f.interfaces = interfaces
|
||||
}
|
||||
|
||||
func (f *myInterfaceFinder) InterfaceIndexByName(name string) (interfaceIndex int, err error) {
|
||||
for _, netInterface := range f.interfaces {
|
||||
if netInterface.Name == name {
|
||||
return netInterface.Index, nil
|
||||
}
|
||||
}
|
||||
netInterface, err := net.InterfaceByName(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
f.update()
|
||||
return netInterface.Index, nil
|
||||
}
|
||||
|
||||
func (f *myInterfaceFinder) InterfaceNameByIndex(index int) (interfaceName string, err error) {
|
||||
for _, netInterface := range f.interfaces {
|
||||
if netInterface.Index == index {
|
||||
return netInterface.Name, nil
|
||||
}
|
||||
}
|
||||
netInterface, err := net.InterfaceByIndex(index)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
f.update()
|
||||
return netInterface.Name, nil
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/ntp"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/outbound"
|
||||
"github.com/sagernet/sing-box/transport/fakeip"
|
||||
@@ -39,7 +40,7 @@ import (
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/ntp"
|
||||
serviceNTP "github.com/sagernet/sing/common/ntp"
|
||||
"github.com/sagernet/sing/common/task"
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
"github.com/sagernet/sing/common/winpowrprof"
|
||||
@@ -80,7 +81,7 @@ type Router struct {
|
||||
transportDomainStrategy map[dns.Transport]dns.DomainStrategy
|
||||
dnsReverseMapping *DNSReverseMapping
|
||||
fakeIPStore adapter.FakeIPStore
|
||||
interfaceFinder *control.DefaultInterfaceFinder
|
||||
interfaceFinder myInterfaceFinder
|
||||
autoDetectInterface bool
|
||||
defaultInterface string
|
||||
defaultMark int
|
||||
@@ -126,7 +127,6 @@ func NewRouter(
|
||||
dnsIndependentCache: dnsOptions.IndependentCache,
|
||||
defaultDetour: options.Final,
|
||||
defaultDomainStrategy: dns.DomainStrategy(dnsOptions.Strategy),
|
||||
interfaceFinder: control.NewDefaultInterfaceFinder(),
|
||||
autoDetectInterface: options.AutoDetectInterface,
|
||||
defaultInterface: options.DefaultInterface,
|
||||
defaultMark: options.DefaultMark,
|
||||
@@ -336,7 +336,7 @@ func NewRouter(
|
||||
}
|
||||
router.networkMonitor = networkMonitor
|
||||
networkMonitor.RegisterCallback(func() {
|
||||
_ = router.interfaceFinder.Update()
|
||||
_ = router.interfaceFinder.update()
|
||||
})
|
||||
interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(router.networkMonitor, router.logger, tun.DefaultInterfaceMonitorOptions{
|
||||
OverrideAndroidVPN: options.OverrideAndroidVPN,
|
||||
@@ -363,19 +363,11 @@ func NewRouter(
|
||||
}
|
||||
|
||||
if ntpOptions.Enabled {
|
||||
ntpDialer, err := dialer.New(router, ntpOptions.DialerOptions)
|
||||
timeService, err := ntp.NewService(ctx, router, logFactory.NewLogger("ntp"), ntpOptions)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create NTP service")
|
||||
return nil, err
|
||||
}
|
||||
timeService := ntp.NewService(ntp.Options{
|
||||
Context: ctx,
|
||||
Dialer: ntpDialer,
|
||||
Logger: logFactory.NewLogger("ntp"),
|
||||
Server: ntpOptions.ServerOptions.Build(),
|
||||
Interval: time.Duration(ntpOptions.Interval),
|
||||
WriteToSystem: ntpOptions.WriteToSystem,
|
||||
})
|
||||
service.MustRegister[ntp.TimeService](ctx, timeService)
|
||||
service.ContextWith[serviceNTP.TimeService](ctx, timeService)
|
||||
router.timeService = timeService
|
||||
}
|
||||
return router, nil
|
||||
@@ -471,7 +463,7 @@ func (r *Router) Outbounds() []adapter.Outbound {
|
||||
}
|
||||
|
||||
func (r *Router) PreStart() error {
|
||||
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
||||
monitor := taskmonitor.New(r.logger, C.DefaultStartTimeout)
|
||||
if r.interfaceMonitor != nil {
|
||||
monitor.Start("initialize interface monitor")
|
||||
err := r.interfaceMonitor.Start()
|
||||
@@ -500,7 +492,7 @@ func (r *Router) PreStart() error {
|
||||
}
|
||||
|
||||
func (r *Router) Start() error {
|
||||
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
||||
monitor := taskmonitor.New(r.logger, C.DefaultStartTimeout)
|
||||
if r.needGeoIPDatabase {
|
||||
monitor.Start("initialize geoip database")
|
||||
err := r.prepareGeoIPDatabase()
|
||||
@@ -670,7 +662,7 @@ func (r *Router) Start() error {
|
||||
}
|
||||
|
||||
func (r *Router) Close() error {
|
||||
monitor := taskmonitor.New(r.logger, C.StopTimeout)
|
||||
monitor := taskmonitor.New(r.logger, C.DefaultStopTimeout)
|
||||
var err error
|
||||
for i, rule := range r.rules {
|
||||
monitor.Start("close rule[", i, "]")
|
||||
@@ -1099,18 +1091,24 @@ func (r *Router) match0(ctx context.Context, metadata *adapter.InboundContext, d
|
||||
}
|
||||
|
||||
func (r *Router) InterfaceFinder() control.InterfaceFinder {
|
||||
return r.interfaceFinder
|
||||
return &r.interfaceFinder
|
||||
}
|
||||
|
||||
func (r *Router) UpdateInterfaces() error {
|
||||
if r.platformInterface == nil || !r.platformInterface.UsePlatformInterfaceGetter() {
|
||||
return r.interfaceFinder.Update()
|
||||
return r.interfaceFinder.update()
|
||||
} else {
|
||||
interfaces, err := r.platformInterface.Interfaces()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.interfaceFinder.UpdateInterfaces(interfaces)
|
||||
r.interfaceFinder.updateInterfaces(common.Map(interfaces, func(it platform.NetworkInterface) net.Interface {
|
||||
return net.Interface{
|
||||
Name: it.Name,
|
||||
Index: it.Index,
|
||||
MTU: it.MTU,
|
||||
}
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, index int) (con
|
||||
if index != -1 {
|
||||
dnsRules = dnsRules[index+1:]
|
||||
}
|
||||
for currentRuleIndex, rule := range dnsRules {
|
||||
for ruleIndex, rule := range dnsRules {
|
||||
metadata.ResetRuleCache()
|
||||
if rule.Match(metadata) {
|
||||
detour := rule.Outbound()
|
||||
@@ -60,11 +60,11 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, index int) (con
|
||||
if isFakeIP && !allowFakeIP {
|
||||
continue
|
||||
}
|
||||
ruleIndex := currentRuleIndex
|
||||
displayRuleIndex := ruleIndex
|
||||
if index != -1 {
|
||||
ruleIndex += index + 1
|
||||
displayRuleIndex += index + 1
|
||||
}
|
||||
r.dnsLogger.DebugContext(ctx, "match[", ruleIndex, "] ", rule.String(), " => ", detour)
|
||||
r.dnsLogger.DebugContext(ctx, "match[", displayRuleIndex, "] ", rule.String(), " => ", detour)
|
||||
if (isFakeIP && !r.dnsIndependentCache) || rule.DisableCache() {
|
||||
ctx = dns.ContextWithDisableCache(ctx, true)
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ func (r *abstractDefaultRule) Match(metadata *adapter.InboundContext) bool {
|
||||
}
|
||||
|
||||
if !metadata.DidMatch {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
return !r.invert
|
||||
|
||||
@@ -247,7 +247,7 @@ func (r *DefaultDNSRule) WithAddressLimit() bool {
|
||||
if !isRuleSet {
|
||||
continue
|
||||
}
|
||||
if ruleSet.ContainsDestinationIPCIDRRule() {
|
||||
if ruleSet.ContainsIPCIDRRule() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,18 +129,14 @@ func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadles
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.WIFISSID) > 0 {
|
||||
if router != nil {
|
||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.WIFIBSSID) > 0 {
|
||||
if router != nil {
|
||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
@@ -24,14 +24,12 @@ func (r *IPIsPrivateItem) Match(metadata *adapter.InboundContext) bool {
|
||||
} else {
|
||||
destination = metadata.Destination.Addr
|
||||
}
|
||||
if destination.IsValid() {
|
||||
return !N.IsPublicAddr(destination)
|
||||
if destination.IsValid() && !N.IsPublicAddr(destination) {
|
||||
return true
|
||||
}
|
||||
if !r.isSource {
|
||||
for _, destinationAddress := range metadata.DestinationAddresses {
|
||||
if !N.IsPublicAddr(destinationAddress) {
|
||||
return true
|
||||
}
|
||||
for _, destinationAddress := range metadata.DestinationAddresses {
|
||||
if !N.IsPublicAddr(destinationAddress) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -47,10 +47,7 @@ func (r *RuleSetItem) Match(metadata *adapter.InboundContext) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *RuleSetItem) ContainsDestinationIPCIDRRule() bool {
|
||||
if r.ipcidrMatchSource {
|
||||
return false
|
||||
}
|
||||
func (r *RuleSetItem) ContainsIPCIDRRule() bool {
|
||||
return common.Any(r.setList, func(ruleSet adapter.RuleSet) bool {
|
||||
return ruleSet.Metadata().ContainsIPCIDRRule
|
||||
})
|
||||
|
||||
@@ -3,14 +3,12 @@ package route
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/srs"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/json"
|
||||
)
|
||||
|
||||
@@ -70,10 +68,6 @@ func (s *LocalRuleSet) Match(metadata *adapter.InboundContext) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *LocalRuleSet) String() string {
|
||||
return strings.Join(F.MapToString(s.rules), " ")
|
||||
}
|
||||
|
||||
func (s *LocalRuleSet) StartContext(ctx context.Context, startContext adapter.RuleSetStartContext) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -15,7 +14,6 @@ import (
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/json"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
@@ -70,10 +68,6 @@ func (s *RemoteRuleSet) Match(metadata *adapter.InboundContext) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *RemoteRuleSet) String() string {
|
||||
return strings.Join(F.MapToString(s.rules), " ")
|
||||
}
|
||||
|
||||
func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext adapter.RuleSetStartContext) error {
|
||||
var dialer N.Dialer
|
||||
if s.options.RemoteOptions.DownloadDetour != "" {
|
||||
|
||||
55
transport/fakeip/packet.go
Normal file
55
transport/fakeip/packet.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package fakeip
|
||||
|
||||
import (
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
var _ N.PacketConn = (*NATPacketConn)(nil)
|
||||
|
||||
type NATPacketConn struct {
|
||||
N.PacketConn
|
||||
origin M.Socksaddr
|
||||
destination M.Socksaddr
|
||||
}
|
||||
|
||||
func NewNATPacketConn(conn N.PacketConn, origin M.Socksaddr, destination M.Socksaddr) *NATPacketConn {
|
||||
return &NATPacketConn{
|
||||
PacketConn: conn,
|
||||
origin: socksaddrWithoutPort(origin),
|
||||
destination: socksaddrWithoutPort(destination),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *NATPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
||||
destination, err = c.PacketConn.ReadPacket(buffer)
|
||||
if socksaddrWithoutPort(destination) == c.origin {
|
||||
destination = M.Socksaddr{
|
||||
Addr: c.destination.Addr,
|
||||
Fqdn: c.destination.Fqdn,
|
||||
Port: destination.Port,
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *NATPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||
if socksaddrWithoutPort(destination) == c.destination {
|
||||
destination = M.Socksaddr{
|
||||
Addr: c.origin.Addr,
|
||||
Fqdn: c.origin.Fqdn,
|
||||
Port: destination.Port,
|
||||
}
|
||||
}
|
||||
return c.PacketConn.WritePacket(buffer, destination)
|
||||
}
|
||||
|
||||
func (c *NATPacketConn) Upstream() any {
|
||||
return c.PacketConn
|
||||
}
|
||||
|
||||
func socksaddrWithoutPort(destination M.Socksaddr) M.Socksaddr {
|
||||
destination.Port = 0
|
||||
return destination
|
||||
}
|
||||
37
transport/fakeip/packet_wait.go
Normal file
37
transport/fakeip/packet_wait.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package fakeip
|
||||
|
||||
import (
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
func (c *NATPacketConn) CreatePacketReadWaiter() (N.PacketReadWaiter, bool) {
|
||||
waiter, created := bufio.CreatePacketReadWaiter(c.PacketConn)
|
||||
if !created {
|
||||
return nil, false
|
||||
}
|
||||
return &waitNATPacketConn{c, waiter}, true
|
||||
}
|
||||
|
||||
type waitNATPacketConn struct {
|
||||
*NATPacketConn
|
||||
readWaiter N.PacketReadWaiter
|
||||
}
|
||||
|
||||
func (c *waitNATPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||
return c.readWaiter.InitializeReadWaiter(options)
|
||||
}
|
||||
|
||||
func (c *waitNATPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||
buffer, destination, err = c.readWaiter.WaitReadPacket()
|
||||
if err == nil && socksaddrWithoutPort(destination) == c.origin {
|
||||
destination = M.Socksaddr{
|
||||
Addr: c.destination.Addr,
|
||||
Fqdn: c.destination.Fqdn,
|
||||
Port: destination.Port,
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -89,8 +89,6 @@ func (c *Client) connect() (*grpc.ClientConn, error) {
|
||||
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
||||
return conn, nil
|
||||
}
|
||||
//nolint:staticcheck
|
||||
//goland:noinspection GoDeprecation
|
||||
conn, err := grpc.DialContext(c.ctx, c.serverAddr, c.dialOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -36,7 +36,6 @@ func NewClientBind(ctx context.Context, errorHandler E.Handler, dialer N.Dialer,
|
||||
errorHandler: errorHandler,
|
||||
dialer: dialer,
|
||||
reservedForEndpoint: make(map[netip.AddrPort][3]uint8),
|
||||
done: make(chan struct{}),
|
||||
isConnect: isConnect,
|
||||
connectAddr: connectAddr,
|
||||
reserved: reserved,
|
||||
@@ -89,7 +88,8 @@ func (c *ClientBind) connect() (*wireConn, error) {
|
||||
func (c *ClientBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err error) {
|
||||
select {
|
||||
case <-c.done:
|
||||
c.done = make(chan struct{})
|
||||
err = net.ErrClosed
|
||||
return
|
||||
default:
|
||||
}
|
||||
return []conn.ReceiveFunc{c.receive}, 0, nil
|
||||
@@ -129,8 +129,16 @@ func (c *ClientBind) receive(packets [][]byte, sizes []int, eps []conn.Endpoint)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *ClientBind) Reset() {
|
||||
common.Close(common.PtrOrNil(c.conn))
|
||||
}
|
||||
|
||||
func (c *ClientBind) Close() error {
|
||||
common.Close(common.PtrOrNil(c.conn))
|
||||
if c.done == nil {
|
||||
c.done = make(chan struct{})
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-c.done:
|
||||
default:
|
||||
@@ -157,7 +165,7 @@ func (c *ClientBind) Send(bufs [][]byte, ep conn.Endpoint) error {
|
||||
}
|
||||
copy(b[1:4], reserved[:])
|
||||
}
|
||||
_, err = udpConn.WriteToUDPAddrPort(b, destination)
|
||||
_, err = udpConn.WriteTo(b, M.SocksaddrFromNetIP(destination))
|
||||
if err != nil {
|
||||
udpConn.Close()
|
||||
return err
|
||||
@@ -184,18 +192,10 @@ func (c *ClientBind) SetReservedForEndpoint(destination netip.AddrPort, reserved
|
||||
|
||||
type wireConn struct {
|
||||
net.PacketConn
|
||||
conn net.Conn
|
||||
access sync.Mutex
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func (w *wireConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
||||
if w.conn != nil {
|
||||
return w.conn.Write(b)
|
||||
}
|
||||
return w.PacketConn.WriteTo(b, M.SocksaddrFromNetIP(addr).UDPAddr())
|
||||
}
|
||||
|
||||
func (w *wireConn) Close() error {
|
||||
w.access.Lock()
|
||||
defer w.access.Unlock()
|
||||
|
||||
Reference in New Issue
Block a user