Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d735281f4 | ||
|
|
8760a0d94d | ||
|
|
2239b59933 | ||
|
|
425a63f59d | ||
|
|
b85725c009 | ||
|
|
17aebc56c1 | ||
|
|
f76b21b02c | ||
|
|
704545a2ec | ||
|
|
dc7b7afc06 | ||
|
|
e478d3c2dc | ||
|
|
c8318058bb | ||
|
|
abca2118e7 | ||
|
|
a8ee41715a | ||
|
|
94f76d6671 | ||
|
|
bf6cc8903c | ||
|
|
1b15e1692a | ||
|
|
017372db25 | ||
|
|
216a0380fe | ||
|
|
71b9e4ff17 | ||
|
|
9b7deb5246 | ||
|
|
a850a73e1a | ||
|
|
c4d9be9e0d | ||
|
|
f31c604b3d | ||
|
|
4c8a50a52b | ||
|
|
b326e60998 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
github: nekohasekai
|
||||||
36
.github/workflows/debug.yml
vendored
36
.github/workflows/debug.yml
vendored
@@ -25,22 +25,10 @@ jobs:
|
|||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get latest go version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ steps.version.outputs.go_version }}
|
go-version: ^1.21
|
||||||
- name: Add cache to Go proxy
|
|
||||||
run: |
|
|
||||||
version=`git rev-parse HEAD`
|
|
||||||
mkdir build
|
|
||||||
pushd build
|
|
||||||
go mod init build
|
|
||||||
go get -v github.com/sagernet/sing-box@$version
|
|
||||||
popd
|
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- name: Run Test
|
- name: Run Test
|
||||||
run: |
|
run: |
|
||||||
@@ -56,7 +44,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.10
|
go-version: ~1.18
|
||||||
- name: Cache go module
|
- name: Cache go module
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
@@ -76,13 +64,13 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.20.7
|
go-version: ^1.20
|
||||||
- name: Cache go module
|
- name: Cache go module
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
key: go118-${{ hashFiles('**/go.sum') }}
|
key: go120-${{ hashFiles('**/go.sum') }}
|
||||||
- name: Run Test
|
- name: Run Test
|
||||||
run: make ci_build
|
run: make ci_build
|
||||||
cross:
|
cross:
|
||||||
@@ -188,8 +176,7 @@ jobs:
|
|||||||
- name: freebsd-arm64
|
- name: freebsd-arm64
|
||||||
goos: freebsd
|
goos: freebsd
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
|
fail-fast: true
|
||||||
fail-fast: false
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
GOOS: ${{ matrix.goos }}
|
GOOS: ${{ matrix.goos }}
|
||||||
@@ -204,19 +191,10 @@ jobs:
|
|||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get latest go version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ steps.version.outputs.go_version }}
|
go-version: ^1.21
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
run: make
|
run: make
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sing-box-${{ matrix.name }}
|
|
||||||
path: sing-box*
|
|
||||||
22
.github/workflows/docker.yml
vendored
22
.github/workflows/docker.yml
vendored
@@ -1,9 +1,10 @@
|
|||||||
name: Build Docker Images
|
name: Build Docker Images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
release:
|
||||||
inputs:
|
types:
|
||||||
tag:
|
- published
|
||||||
description: "The tag version you want to build"
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -25,15 +26,6 @@ jobs:
|
|||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ghcr.io/sagernet/sing-box
|
images: ghcr.io/sagernet/sing-box
|
||||||
- name: Get tag to build
|
|
||||||
id: tag
|
|
||||||
run: |
|
|
||||||
echo "latest=ghcr.io/sagernet/sing-box:latest" >> $GITHUB_OUTPUT
|
|
||||||
if [[ -z "${{ github.event.inputs.tag }}" ]]; then
|
|
||||||
echo "versioned=ghcr.io/sagernet/sing-box:${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "versioned=ghcr.io/sagernet/sing-box:${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Build and release Docker images
|
- name: Build and release Docker images
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
@@ -42,6 +34,6 @@ jobs:
|
|||||||
build-args: |
|
build-args: |
|
||||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
||||||
tags: |
|
tags: |
|
||||||
${{ steps.tag.outputs.latest }}
|
ghcr.io/sagernet/sing-box:latest
|
||||||
${{ steps.tag.outputs.versioned }}
|
ghcr.io/sagernet/sing-box:${{ github.ref_name }}
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
8
.github/workflows/lint.yml
vendored
8
.github/workflows/lint.yml
vendored
@@ -25,10 +25,10 @@ jobs:
|
|||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get latest go version
|
- name: Setup Go
|
||||||
id: version
|
uses: actions/setup-go@v4
|
||||||
run: |
|
with:
|
||||||
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
|
go-version: ^1.21
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -85,8 +85,15 @@ var GoBinPath string
|
|||||||
|
|
||||||
func FindMobile() {
|
func FindMobile() {
|
||||||
goBin := filepath.Join(build.Default.GOPATH, "bin")
|
goBin := filepath.Join(build.Default.GOPATH, "bin")
|
||||||
if !rw.FileExists(goBin + "/" + "gobind") {
|
|
||||||
log.Fatal("missing gomobile installation")
|
if runtime.GOOS == "windows" {
|
||||||
|
if !rw.FileExists(goBin + "/" + "gobind.exe") {
|
||||||
|
log.Fatal("missing gomobile.exe installation")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !rw.FileExists(goBin + "/" + "gobind") {
|
||||||
|
log.Fatal("missing gomobile installation")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GoBinPath = goBin
|
GoBinPath = goBin
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ReadWaitConn) Upstream() any {
|
||||||
|
return c.STDConn
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname tlsReadRecord crypto/tls.(*Conn).readRecord
|
//go:linkname tlsReadRecord crypto/tls.(*Conn).readRecord
|
||||||
func tlsReadRecord(c *tls.STDConn) error
|
func tlsReadRecord(c *tls.STDConn) error
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
|||||||
c.conn = nil
|
c.conn = nil
|
||||||
c.err = E.Cause(err, "dial tcp fast open")
|
c.err = E.Cause(err, "dial tcp fast open")
|
||||||
}
|
}
|
||||||
|
n = len(b)
|
||||||
close(c.create)
|
close(c.create)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ func writeDefaultRule(writer io.Writer, rule option.DefaultHeadlessRule) error {
|
|||||||
if len(rule.SourceIPCIDR) > 0 {
|
if len(rule.SourceIPCIDR) > 0 {
|
||||||
err = writeRuleItemCIDR(writer, ruleItemSourceIPCIDR, rule.SourceIPCIDR)
|
err = writeRuleItemCIDR(writer, ruleItemSourceIPCIDR, rule.SourceIPCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "source_ipcidr")
|
return E.Cause(err, "source_ip_cidr")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(rule.IPCIDR) > 0 {
|
if len(rule.IPCIDR) > 0 {
|
||||||
|
|||||||
@@ -2,6 +2,22 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 1.8.5
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.4
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.2
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.1
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.8.0
|
#### 1.8.0
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|||||||
@@ -322,17 +322,7 @@ flowchart TB
|
|||||||
"server": "google"
|
"server": "google"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "logical",
|
"geosite": "geolocation-cn",
|
||||||
"mode": "and",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"geosite": "geolocation-!cn",
|
|
||||||
"invert": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"geosite": "cn",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"server": "local"
|
"server": "local"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -374,17 +364,7 @@ flowchart TB
|
|||||||
"server": "google"
|
"server": "google"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "logical",
|
"rule_set": "geosite-geolocation-cn",
|
||||||
"mode": "and",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"rule_set": "geosite-geolocation-!cn",
|
|
||||||
"invert": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rule_set": "geosite-cn",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"server": "local"
|
"server": "local"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -393,15 +373,9 @@ flowchart TB
|
|||||||
"rule_set": [
|
"rule_set": [
|
||||||
{
|
{
|
||||||
"type": "remote",
|
"type": "remote",
|
||||||
"tag": "geosite-cn",
|
"tag": "geosite-geolocation-cn",
|
||||||
"format": "binary",
|
"format": "binary",
|
||||||
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-cn.srs"
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "remote",
|
|
||||||
"tag": "geosite-geolocation-!cn",
|
|
||||||
"format": "binary",
|
|
||||||
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-!cn.srs"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -467,18 +441,7 @@ flowchart TB
|
|||||||
"outbound": "block"
|
"outbound": "block"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "logical",
|
"geosite": "geolocation-cn",
|
||||||
"mode": "and",
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"geosite": "geolocation-!cn",
|
|
||||||
"invert": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"geosite": "cn",
|
|
||||||
"geoip": "cn"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbound": "direct"
|
"outbound": "direct"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -545,19 +508,9 @@ flowchart TB
|
|||||||
"outbound": "block"
|
"outbound": "block"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "logical",
|
"rule_set": [
|
||||||
"mode": "and",
|
"geoip-cn",
|
||||||
"rules": [
|
"geosite-geolocation-cn"
|
||||||
{
|
|
||||||
"rule_set": "geosite-geolocation-!cn",
|
|
||||||
"invert": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rule_set": [
|
|
||||||
"geoip-cn",
|
|
||||||
"geosite-cn"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"outbound": "direct"
|
"outbound": "direct"
|
||||||
}
|
}
|
||||||
@@ -571,15 +524,9 @@ flowchart TB
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "remote",
|
"type": "remote",
|
||||||
"tag": "geosite-cn",
|
"tag": "geosite-geolocation-cn",
|
||||||
"format": "binary",
|
"format": "binary",
|
||||||
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-cn.srs"
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "remote",
|
|
||||||
"tag": "geosite-geolocation-!cn",
|
|
||||||
"format": "binary",
|
|
||||||
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-!cn.srs"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,13 +93,11 @@ func (s *CommandServer) listenUNIX() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "listen ", sockPath)
|
return E.Cause(err, "listen ", sockPath)
|
||||||
}
|
}
|
||||||
if sUserID > 0 {
|
err = os.Chown(sockPath, sUserID, sGroupID)
|
||||||
err = os.Chown(sockPath, sUserID, sGroupID)
|
if err != nil {
|
||||||
if err != nil {
|
listener.Close()
|
||||||
listener.Close()
|
os.Remove(sockPath)
|
||||||
os.Remove(sockPath)
|
return E.Cause(err, "chown")
|
||||||
return E.Cause(err, "chown")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
s.listener = listener
|
s.listener = listener
|
||||||
go s.loopConnection(listener)
|
go s.loopConnection(listener)
|
||||||
|
|||||||
@@ -20,13 +20,11 @@ func RedirectStderr(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if runtime.GOOS != "android" {
|
if runtime.GOOS != "android" {
|
||||||
if sUserID > 0 {
|
err = outputFile.Chown(sUserID, sGroupID)
|
||||||
err = outputFile.Chown(sUserID, sGroupID)
|
if err != nil {
|
||||||
if err != nil {
|
outputFile.Close()
|
||||||
outputFile.Close()
|
os.Remove(outputFile.Name())
|
||||||
os.Remove(outputFile.Name())
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = unix.Dup2(int(outputFile.Fd()), int(os.Stderr.Fd()))
|
err = unix.Dup2(int(outputFile.Fd()), int(os.Stderr.Fd()))
|
||||||
|
|||||||
@@ -97,6 +97,17 @@ func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Eleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
|
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
|
||||||
|
if interfaceName == "" || interfaceIndex32 == -1 {
|
||||||
|
m.defaultInterfaceName = ""
|
||||||
|
m.defaultInterfaceIndex = -1
|
||||||
|
m.access.Lock()
|
||||||
|
callbacks := m.callbacks.Array()
|
||||||
|
m.access.Unlock()
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
callback(tun.EventNoRoute)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
if m.iif.UsePlatformInterfaceGetter() {
|
if m.iif.UsePlatformInterfaceGetter() {
|
||||||
err = m.updateInterfacesPlatform()
|
err = m.updateInterfacesPlatform()
|
||||||
@@ -110,28 +121,6 @@ func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName s
|
|||||||
m.logger.Error(E.Cause(err, "update interfaces"))
|
m.logger.Error(E.Cause(err, "update interfaces"))
|
||||||
}
|
}
|
||||||
interfaceIndex := int(interfaceIndex32)
|
interfaceIndex := int(interfaceIndex32)
|
||||||
if interfaceName == "" {
|
|
||||||
for _, netIf := range m.networkAddresses {
|
|
||||||
if netIf.interfaceIndex == interfaceIndex {
|
|
||||||
interfaceName = netIf.interfaceName
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if interfaceIndex == -1 {
|
|
||||||
for _, netIf := range m.networkAddresses {
|
|
||||||
if netIf.interfaceName == interfaceName {
|
|
||||||
interfaceIndex = netIf.interfaceIndex
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if interfaceName == "" {
|
|
||||||
m.logger.Error(E.New("invalid interface name for ", interfaceIndex))
|
|
||||||
return
|
|
||||||
} else if interfaceIndex == -1 {
|
|
||||||
m.logger.Error(E.New("invalid interface index for ", interfaceName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if m.defaultInterfaceName == interfaceName && m.defaultInterfaceIndex == interfaceIndex {
|
if m.defaultInterfaceName == interfaceName && m.defaultInterfaceIndex == interfaceIndex {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
32
experimental/libbox/service_error.go
Normal file
32
experimental/libbox/service_error.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func serviceErrorPath() string {
|
||||||
|
return filepath.Join(sWorkingPath, "network_extension_error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClearServiceError() {
|
||||||
|
os.Remove(serviceErrorPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadServiceError() (string, error) {
|
||||||
|
data, err := os.ReadFile(serviceErrorPath())
|
||||||
|
if err == nil {
|
||||||
|
os.Remove(serviceErrorPath())
|
||||||
|
}
|
||||||
|
return string(data), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteServiceError(message string) error {
|
||||||
|
errorFile, err := os.Create(serviceErrorPath())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
errorFile.WriteString(message)
|
||||||
|
errorFile.Chown(sUserID, sGroupID)
|
||||||
|
return errorFile.Close()
|
||||||
|
}
|
||||||
@@ -25,6 +25,8 @@ func Setup(basePath string, workingPath string, tempPath string, isTVOS bool) {
|
|||||||
sUserID = os.Getuid()
|
sUserID = os.Getuid()
|
||||||
sGroupID = os.Getgid()
|
sGroupID = os.Getgid()
|
||||||
sTVOS = isTVOS
|
sTVOS = isTVOS
|
||||||
|
os.MkdirAll(sWorkingPath, 0o777)
|
||||||
|
os.MkdirAll(sTempPath, 0o777)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupWithUsername(basePath string, workingPath string, tempPath string, username string) error {
|
func SetupWithUsername(basePath string, workingPath string, tempPath string, username string) error {
|
||||||
@@ -37,6 +39,10 @@ func SetupWithUsername(basePath string, workingPath string, tempPath string, use
|
|||||||
}
|
}
|
||||||
sUserID, _ = strconv.Atoi(sUser.Uid)
|
sUserID, _ = strconv.Atoi(sUser.Uid)
|
||||||
sGroupID, _ = strconv.Atoi(sUser.Gid)
|
sGroupID, _ = strconv.Atoi(sUser.Gid)
|
||||||
|
os.MkdirAll(sWorkingPath, 0o777)
|
||||||
|
os.MkdirAll(sTempPath, 0o777)
|
||||||
|
os.Chown(sWorkingPath, sUserID, sGroupID)
|
||||||
|
os.Chown(sTempPath, sUserID, sGroupID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
go.mod
26
go.mod
@@ -5,7 +5,7 @@ go 1.20
|
|||||||
require (
|
require (
|
||||||
berty.tech/go-libtor v1.0.385
|
berty.tech/go-libtor v1.0.385
|
||||||
github.com/caddyserver/certmagic v0.20.0
|
github.com/caddyserver/certmagic v0.20.0
|
||||||
github.com/cloudflare/circl v1.3.6
|
github.com/cloudflare/circl v1.3.7
|
||||||
github.com/cretz/bine v0.2.0
|
github.com/cretz/bine v0.2.0
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/go-chi/chi/v5 v5.0.11
|
github.com/go-chi/chi/v5 v5.0.11
|
||||||
@@ -17,23 +17,23 @@ require (
|
|||||||
github.com/libdns/cloudflare v0.1.0
|
github.com/libdns/cloudflare v0.1.0
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/mholt/acmez v1.2.0
|
github.com/mholt/acmez v1.2.0
|
||||||
github.com/miekg/dns v1.1.57
|
github.com/miekg/dns v1.1.58
|
||||||
github.com/ooni/go-libtor v1.1.8
|
github.com/ooni/go-libtor v1.1.8
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0
|
github.com/oschwald/maxminddb-golang v1.12.0
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
||||||
github.com/sagernet/gomobile v0.1.1
|
github.com/sagernet/gomobile v0.1.1
|
||||||
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
|
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
|
||||||
github.com/sagernet/quic-go v0.40.1-beta.2
|
github.com/sagernet/quic-go v0.40.1
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.3.0-rc.7
|
github.com/sagernet/sing v0.3.0
|
||||||
github.com/sagernet/sing-dns v0.1.12
|
github.com/sagernet/sing-dns v0.1.12
|
||||||
github.com/sagernet/sing-mux v0.1.8-rc.1
|
github.com/sagernet/sing-mux v0.2.0
|
||||||
github.com/sagernet/sing-quic v0.1.7-rc.2
|
github.com/sagernet/sing-quic v0.1.8
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.6-rc.1
|
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4
|
github.com/sagernet/sing-shadowtls v0.1.4
|
||||||
github.com/sagernet/sing-tun v0.2.0-rc.1
|
github.com/sagernet/sing-tun v0.2.1
|
||||||
github.com/sagernet/sing-vmess v0.1.8
|
github.com/sagernet/sing-vmess v0.1.8
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
||||||
@@ -44,9 +44,9 @@ require (
|
|||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
go.uber.org/zap v1.26.0
|
go.uber.org/zap v1.26.0
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.17.0
|
golang.org/x/crypto v0.18.0
|
||||||
golang.org/x/net v0.19.0
|
golang.org/x/net v0.20.0
|
||||||
golang.org/x/sys v0.15.0
|
golang.org/x/sys v0.16.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
google.golang.org/grpc v1.60.1
|
google.golang.org/grpc v1.60.1
|
||||||
google.golang.org/protobuf v1.32.0
|
google.golang.org/protobuf v1.32.0
|
||||||
@@ -86,11 +86,11 @@ require (
|
|||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.16.0 // indirect
|
golang.org/x/tools v0.17.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|||||||
56
go.sum
56
go.sum
@@ -6,8 +6,8 @@ github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sx
|
|||||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
||||||
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
||||||
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
|
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||||
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/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.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 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
||||||
@@ -74,8 +74,8 @@ github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczG
|
|||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
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 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||||
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||||
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
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 h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
||||||
@@ -104,27 +104,27 @@ github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dks
|
|||||||
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
|
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
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/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.40.1-beta.2 h1:USRwm36XuAFdcrmv4vDRD+YUOO08DfvLNruXThrVHZU=
|
github.com/sagernet/quic-go v0.40.1 h1:qLeTIJR0d0JWRmDWo346nLsVN6EWihd1kalJYPEd0TM=
|
||||||
github.com/sagernet/quic-go v0.40.1-beta.2/go.mod h1:CcKTpzTAISxrM4PA5M20/wYuz9Tj6Tx4DwGbNl9UQrU=
|
github.com/sagernet/quic-go v0.40.1/go.mod h1:CcKTpzTAISxrM4PA5M20/wYuz9Tj6Tx4DwGbNl9UQrU=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
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/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.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing v0.3.0-rc.7 h1:FmnzFRYC6usVgWf112cUxiexwvL+iAurKmCL4Axa9+A=
|
github.com/sagernet/sing v0.3.0 h1:PIDVFZHnQAAYRL1UYqNM+0k5s8f/tb1lUW6UDcQiOc8=
|
||||||
github.com/sagernet/sing v0.3.0-rc.7/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
|
github.com/sagernet/sing v0.3.0/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
|
||||||
github.com/sagernet/sing-dns v0.1.12 h1:1HqZ+ln+Rezx/aJMStaS0d7oPeX2EobSV1NT537kyj4=
|
github.com/sagernet/sing-dns v0.1.12 h1:1HqZ+ln+Rezx/aJMStaS0d7oPeX2EobSV1NT537kyj4=
|
||||||
github.com/sagernet/sing-dns v0.1.12/go.mod h1:rx/DTOisneQpCgNQ4jbFU/JNEtnz0lYcHXenlVzpjEU=
|
github.com/sagernet/sing-dns v0.1.12/go.mod h1:rx/DTOisneQpCgNQ4jbFU/JNEtnz0lYcHXenlVzpjEU=
|
||||||
github.com/sagernet/sing-mux v0.1.8-rc.1 h1:5dsZgWmNr9W6JzQj4fb3xX2pMP0OyJH6kVtlqc2kFKA=
|
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
||||||
github.com/sagernet/sing-mux v0.1.8-rc.1/go.mod h1:KK5zCbNujj5kn36G+wLFROOXyJhaaXLyaZWY2w7kBNQ=
|
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||||
github.com/sagernet/sing-quic v0.1.7-rc.2 h1:rCWhtvzQwgkWbX4sVHYdNwzyPweoUPEgBCBatywHjMs=
|
github.com/sagernet/sing-quic v0.1.8 h1:G4iBXAKIII+uTzd55oZ/9cAQswGjlvHh/0yKMQioDS0=
|
||||||
github.com/sagernet/sing-quic v0.1.7-rc.2/go.mod h1:IbKCPWXP13zd3cdu0rirtYjkMlquc5zWtc3avfSUGAw=
|
github.com/sagernet/sing-quic v0.1.8/go.mod h1:2w7DZXtf4MPjIGpovA3+vpI6bvOf1n1f9cQ1E2qQJSg=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
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-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.6-rc.1 h1:E+8OyyVg0YfFNUmxMx9jYBEhjLYMQSAMzJrUmE934bo=
|
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.6-rc.1/go.mod h1:wFkU7sKxyZADS/idtJqBhtc+QBf5iwX9nZO7ymcn6MM=
|
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 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||||
github.com/sagernet/sing-tun v0.2.0-rc.1 h1:CnlxRgrJKAMKYNuJOcKie6TjRz8wremEq1wndLup7cA=
|
github.com/sagernet/sing-tun v0.2.1 h1:xZ/MkQbAX4yuOXq/s1pfhWa0lK1Ld7t4gOpSUbRl1Rs=
|
||||||
github.com/sagernet/sing-tun v0.2.0-rc.1/go.mod h1:hpbL9jNAbYT9G2EHCpCXVIgSrM/2Wgnrm/Hped+8zdY=
|
github.com/sagernet/sing-tun v0.2.1/go.mod h1:w1HTPPEL575m+Ob3GOIWaTs3ZrTdgLIwoldce/p3WPU=
|
||||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
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/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
@@ -168,17 +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=
|
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-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.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||||
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.14.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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
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-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-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -188,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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.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.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.16.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.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
@@ -199,8 +199,8 @@ 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 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
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.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
|
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||||
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.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 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ theme:
|
|||||||
logo: assets/icon.svg
|
logo: assets/icon.svg
|
||||||
favicon: assets/icon.svg
|
favicon: assets/icon.svg
|
||||||
palette:
|
palette:
|
||||||
- scheme: default
|
- media: "(prefers-color-scheme: light)"
|
||||||
|
scheme: default
|
||||||
primary: white
|
primary: white
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/brightness-7
|
icon: material/brightness-7
|
||||||
name: Switch to dark mode
|
name: Switch to dark mode
|
||||||
- scheme: slate
|
- media: "(prefers-color-scheme: dark)"
|
||||||
|
scheme: slate
|
||||||
primary: black
|
primary: black
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/brightness-4
|
icon: material/brightness-4
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type Direct struct {
|
|||||||
fallbackDelay time.Duration
|
fallbackDelay time.Duration
|
||||||
overrideOption int
|
overrideOption int
|
||||||
overrideDestination M.Socksaddr
|
overrideDestination M.Socksaddr
|
||||||
|
loopBack *loopBackDetector
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
|
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
|
||||||
@@ -50,6 +51,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
|||||||
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
|
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
|
||||||
fallbackDelay: time.Duration(options.FallbackDelay),
|
fallbackDelay: time.Duration(options.FallbackDelay),
|
||||||
dialer: outboundDialer,
|
dialer: outboundDialer,
|
||||||
|
loopBack: newLoopBackDetector(),
|
||||||
}
|
}
|
||||||
if options.ProxyProtocol != 0 {
|
if options.ProxyProtocol != 0 {
|
||||||
return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0")
|
return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0")
|
||||||
@@ -88,7 +90,11 @@ func (h *Direct) DialContext(ctx context.Context, network string, destination M.
|
|||||||
case N.NetworkUDP:
|
case N.NetworkUDP:
|
||||||
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||||
}
|
}
|
||||||
return h.dialer.DialContext(ctx, network, destination)
|
conn, err := h.dialer.DialContext(ctx, network, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return h.loopBack.NewConn(conn), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
|
func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
|
||||||
@@ -142,6 +148,7 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn))
|
||||||
if originDestination != destination {
|
if originDestination != destination {
|
||||||
conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
|
conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
|
||||||
}
|
}
|
||||||
@@ -149,9 +156,15 @@ 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 {
|
func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
|
if h.loopBack.CheckConn(metadata.Source.AddrPort()) {
|
||||||
|
return E.New("reject loopback connection to ", metadata.Destination)
|
||||||
|
}
|
||||||
return NewConnection(ctx, h, conn, metadata)
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
|
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort()) {
|
||||||
|
return E.New("reject loopback packet connection to ", metadata.Destination)
|
||||||
|
}
|
||||||
return NewPacketConnection(ctx, h, conn, metadata)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|||||||
154
outbound/direct_loopback_detect.go
Normal file
154
outbound/direct_loopback_detect.go
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package outbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type loopBackDetector struct {
|
||||||
|
connAccess sync.RWMutex
|
||||||
|
packetConnAccess sync.RWMutex
|
||||||
|
connMap map[netip.AddrPort]bool
|
||||||
|
packetConnMap map[netip.AddrPort]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLoopBackDetector() *loopBackDetector {
|
||||||
|
return &loopBackDetector{
|
||||||
|
connMap: make(map[netip.AddrPort]bool),
|
||||||
|
packetConnMap: make(map[netip.AddrPort]bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
|
||||||
|
connAddr := M.AddrPortFromNet(conn.LocalAddr())
|
||||||
|
if !connAddr.IsValid() {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
|
||||||
|
l.packetConnAccess.Lock()
|
||||||
|
l.packetConnMap[connAddr] = true
|
||||||
|
l.packetConnAccess.Unlock()
|
||||||
|
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connAddr: connAddr}
|
||||||
|
} else {
|
||||||
|
l.connAccess.Lock()
|
||||||
|
l.connMap[connAddr] = true
|
||||||
|
l.connAccess.Unlock()
|
||||||
|
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: connAddr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn) N.NetPacketConn {
|
||||||
|
connAddr := M.AddrPortFromNet(conn.LocalAddr())
|
||||||
|
if !connAddr.IsValid() {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
l.packetConnAccess.Lock()
|
||||||
|
l.packetConnMap[connAddr] = true
|
||||||
|
l.packetConnAccess.Unlock()
|
||||||
|
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connAddr: connAddr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
|
||||||
|
l.connAccess.RLock()
|
||||||
|
defer l.connAccess.RUnlock()
|
||||||
|
return l.connMap[connAddr]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
|
||||||
|
l.packetConnAccess.RLock()
|
||||||
|
defer l.packetConnAccess.RUnlock()
|
||||||
|
return l.packetConnMap[connAddr]
|
||||||
|
}
|
||||||
|
|
||||||
|
type loopBackDetectWrapper struct {
|
||||||
|
net.Conn
|
||||||
|
detector *loopBackDetector
|
||||||
|
connAddr netip.AddrPort
|
||||||
|
closeOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectWrapper) Close() error {
|
||||||
|
w.closeOnce.Do(func() {
|
||||||
|
w.detector.connAccess.Lock()
|
||||||
|
delete(w.detector.connMap, w.connAddr)
|
||||||
|
w.detector.connAccess.Unlock()
|
||||||
|
})
|
||||||
|
return w.Conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectWrapper) ReaderReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectWrapper) WriterReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectWrapper) Upstream() any {
|
||||||
|
return w.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
type loopBackDetectPacketWrapper struct {
|
||||||
|
N.NetPacketConn
|
||||||
|
detector *loopBackDetector
|
||||||
|
connAddr netip.AddrPort
|
||||||
|
closeOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectPacketWrapper) Close() error {
|
||||||
|
w.closeOnce.Do(func() {
|
||||||
|
w.detector.packetConnAccess.Lock()
|
||||||
|
delete(w.detector.packetConnMap, w.connAddr)
|
||||||
|
w.detector.packetConnAccess.Unlock()
|
||||||
|
})
|
||||||
|
return w.NetPacketConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectPacketWrapper) ReaderReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectPacketWrapper) WriterReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectPacketWrapper) Upstream() any {
|
||||||
|
return w.NetPacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
type abstractUDPConn interface {
|
||||||
|
net.Conn
|
||||||
|
net.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
type loopBackDetectUDPWrapper struct {
|
||||||
|
abstractUDPConn
|
||||||
|
detector *loopBackDetector
|
||||||
|
connAddr netip.AddrPort
|
||||||
|
closeOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectUDPWrapper) Close() error {
|
||||||
|
w.closeOnce.Do(func() {
|
||||||
|
w.detector.packetConnAccess.Lock()
|
||||||
|
delete(w.detector.packetConnMap, w.connAddr)
|
||||||
|
w.detector.packetConnAccess.Unlock()
|
||||||
|
})
|
||||||
|
return w.abstractUDPConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectUDPWrapper) ReaderReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectUDPWrapper) WriterReplaceable() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *loopBackDetectUDPWrapper) Upstream() any {
|
||||||
|
return w.abstractUDPConn
|
||||||
|
}
|
||||||
@@ -241,7 +241,8 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
timeout.Update()
|
timeout.Update()
|
||||||
responseBuffer := buf.NewPacket()
|
response = truncateDNSMessage(response, 512) // TODO: add an option to custom UDP buffer size
|
||||||
|
responseBuffer := buf.NewSize(dns.FixedPacketSize)
|
||||||
responseBuffer.Resize(1024, 0)
|
responseBuffer.Resize(1024, 0)
|
||||||
n, err := response.PackBuffer(responseBuffer.FreeBytes())
|
n, err := response.PackBuffer(responseBuffer.FreeBytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -263,3 +264,21 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
|
|||||||
})
|
})
|
||||||
return group.Run(fastClose)
|
return group.Run(fastClose)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func truncateDNSMessage(response *mDNS.Msg, maxLen int) *mDNS.Msg {
|
||||||
|
responseLen := response.Len()
|
||||||
|
if responseLen <= maxLen {
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
response = response.Copy()
|
||||||
|
for len(response.Answer) > 0 && responseLen > maxLen {
|
||||||
|
response.Answer = response.Answer[:len(response.Answer)-1]
|
||||||
|
response.Truncated = true
|
||||||
|
responseLen = response.Len()
|
||||||
|
}
|
||||||
|
if responseLen > maxLen {
|
||||||
|
response.Ns = nil
|
||||||
|
response.Extra = nil
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|||||||
@@ -125,7 +125,18 @@ func (s *URLTest) CheckOutbounds() {
|
|||||||
|
|
||||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
s.group.Touch()
|
s.group.Touch()
|
||||||
outbound := s.group.Select(network)
|
var outbound adapter.Outbound
|
||||||
|
switch N.NetworkName(network) {
|
||||||
|
case N.NetworkTCP:
|
||||||
|
outbound = s.group.selectedOutboundTCP
|
||||||
|
case N.NetworkUDP:
|
||||||
|
outbound = s.group.selectedOutboundUDP
|
||||||
|
default:
|
||||||
|
return nil, E.Extend(N.ErrUnknownNetwork, network)
|
||||||
|
}
|
||||||
|
if outbound == nil {
|
||||||
|
outbound, _ = s.group.Select(network)
|
||||||
|
}
|
||||||
if outbound == nil {
|
if outbound == nil {
|
||||||
return nil, E.New("missing supported outbound")
|
return nil, E.New("missing supported outbound")
|
||||||
}
|
}
|
||||||
@@ -140,7 +151,10 @@ func (s *URLTest) DialContext(ctx context.Context, network string, destination M
|
|||||||
|
|
||||||
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
s.group.Touch()
|
s.group.Touch()
|
||||||
outbound := s.group.Select(N.NetworkUDP)
|
outbound := s.group.selectedOutboundUDP
|
||||||
|
if outbound == nil {
|
||||||
|
outbound, _ = s.group.Select(N.NetworkUDP)
|
||||||
|
}
|
||||||
if outbound == nil {
|
if outbound == nil {
|
||||||
return nil, E.New("missing supported outbound")
|
return nil, E.New("missing supported outbound")
|
||||||
}
|
}
|
||||||
@@ -271,7 +285,7 @@ func (g *URLTestGroup) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
func (g *URLTestGroup) Select(network string) (adapter.Outbound, bool) {
|
||||||
var minDelay uint16
|
var minDelay uint16
|
||||||
var minTime time.Time
|
var minTime time.Time
|
||||||
var minOutbound adapter.Outbound
|
var minOutbound adapter.Outbound
|
||||||
@@ -294,11 +308,11 @@ func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
|||||||
if !common.Contains(detour.Network(), network) {
|
if !common.Contains(detour.Network(), network) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
minOutbound = detour
|
return detour, false
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
return minOutbound
|
return minOutbound, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
func (g *URLTestGroup) loopCheck() {
|
||||||
@@ -382,14 +396,12 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) performUpdateCheck() {
|
func (g *URLTestGroup) performUpdateCheck() {
|
||||||
outbound := g.Select(N.NetworkTCP)
|
|
||||||
var updated bool
|
var updated bool
|
||||||
if outbound != nil && outbound != g.selectedOutboundTCP {
|
if outbound, exists := g.Select(N.NetworkTCP); outbound != nil && (g.selectedOutboundTCP == nil || (exists && outbound != g.selectedOutboundTCP)) {
|
||||||
g.selectedOutboundTCP = outbound
|
g.selectedOutboundTCP = outbound
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
outbound = g.Select(N.NetworkUDP)
|
if outbound, exists := g.Select(N.NetworkUDP); outbound != nil && (g.selectedOutboundUDP == nil || (exists && outbound != g.selectedOutboundUDP)) {
|
||||||
if outbound != nil && outbound != g.selectedOutboundUDP {
|
|
||||||
g.selectedOutboundUDP = outbound
|
g.selectedOutboundUDP = outbound
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=sing-box service
|
Description=sing-box service
|
||||||
Documentation=https://sing-box.sagernet.org
|
Documentation=https://sing-box.sagernet.org
|
||||||
After=network.target nss-lookup.target
|
After=network.target nss-lookup.target network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=sing-box service
|
Description=sing-box service
|
||||||
Documentation=https://sing-box.sagernet.org
|
Documentation=https://sing-box.sagernet.org
|
||||||
After=network.target nss-lookup.target
|
After=network.target nss-lookup.target network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=sing-box service
|
Description=sing-box service
|
||||||
Documentation=https://sing-box.sagernet.org
|
Documentation=https://sing-box.sagernet.org
|
||||||
After=network.target nss-lookup.target
|
After=network.target nss-lookup.target network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (r *abstractDefaultRule) Match(metadata *adapter.InboundContext) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.sourcePortItems) > 0 && !metadata.SourceAddressMatch {
|
if len(r.sourcePortItems) > 0 && !metadata.SourcePortMatch {
|
||||||
for _, item := range r.sourcePortItems {
|
for _, item := range r.sourcePortItems {
|
||||||
if item.Match(metadata) {
|
if item.Match(metadata) {
|
||||||
metadata.SourcePortMatch = true
|
metadata.SourcePortMatch = true
|
||||||
@@ -81,7 +81,7 @@ func (r *abstractDefaultRule) Match(metadata *adapter.InboundContext) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.destinationAddressItems) > 0 && !metadata.SourceAddressMatch {
|
if len(r.destinationAddressItems) > 0 && !metadata.DestinationAddressMatch {
|
||||||
for _, item := range r.destinationAddressItems {
|
for _, item := range r.destinationAddressItems {
|
||||||
if item.Match(metadata) {
|
if item.Match(metadata) {
|
||||||
metadata.DestinationAddressMatch = true
|
metadata.DestinationAddressMatch = true
|
||||||
@@ -90,7 +90,7 @@ func (r *abstractDefaultRule) Match(metadata *adapter.InboundContext) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.destinationPortItems) > 0 && !metadata.SourceAddressMatch {
|
if len(r.destinationPortItems) > 0 && !metadata.DestinationPortMatch {
|
||||||
for _, item := range r.destinationPortItems {
|
for _, item := range r.destinationPortItems {
|
||||||
if item.Match(metadata) {
|
if item.Match(metadata) {
|
||||||
metadata.DestinationPortMatch = true
|
metadata.DestinationPortMatch = true
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt
|
|||||||
if len(options.SourceIPCIDR) > 0 {
|
if len(options.SourceIPCIDR) > 0 {
|
||||||
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "source_ipcidr")
|
return nil, E.Cause(err, "source_ip_cidr")
|
||||||
}
|
}
|
||||||
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
|
|||||||
if len(options.SourceIPCIDR) > 0 {
|
if len(options.SourceIPCIDR) > 0 {
|
||||||
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "source_ipcidr")
|
return nil, E.Cause(err, "source_ip_cidr")
|
||||||
}
|
}
|
||||||
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadles
|
|||||||
if len(options.SourceIPCIDR) > 0 {
|
if len(options.SourceIPCIDR) > 0 {
|
||||||
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "source_ipcidr")
|
return nil, E.Cause(err, "source_ip_cidr")
|
||||||
}
|
}
|
||||||
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
rule.sourceAddressItems = append(rule.sourceAddressItems, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
|
|||||||
}
|
}
|
||||||
var description string
|
var description string
|
||||||
if isSource {
|
if isSource {
|
||||||
description = "source_ipcidr="
|
description = "source_ip_cidr="
|
||||||
} else {
|
} else {
|
||||||
description = "ipcidr="
|
description = "ip_cidr="
|
||||||
}
|
}
|
||||||
if dLen := len(prefixStrings); dLen == 1 {
|
if dLen := len(prefixStrings); dLen == 1 {
|
||||||
description += prefixStrings[0]
|
description += prefixStrings[0]
|
||||||
@@ -60,9 +60,9 @@ func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
|
|||||||
func NewRawIPCIDRItem(isSource bool, ipSet *netipx.IPSet) *IPCIDRItem {
|
func NewRawIPCIDRItem(isSource bool, ipSet *netipx.IPSet) *IPCIDRItem {
|
||||||
var description string
|
var description string
|
||||||
if isSource {
|
if isSource {
|
||||||
description = "source_ipcidr="
|
description = "source_ip_cidr="
|
||||||
} else {
|
} else {
|
||||||
description = "ipcidr="
|
description = "ip_cidr="
|
||||||
}
|
}
|
||||||
description += "<binary>"
|
description += "<binary>"
|
||||||
return &IPCIDRItem{
|
return &IPCIDRItem{
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
|||||||
description += " "
|
description += " "
|
||||||
}
|
}
|
||||||
if dsLen == 1 {
|
if dsLen == 1 {
|
||||||
description += "domainSuffix=" + domainSuffixes[0]
|
description += "domain_suffix=" + domainSuffixes[0]
|
||||||
} else if dsLen > 3 {
|
} else if dsLen > 3 {
|
||||||
description += "domainSuffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
|
description += "domain_suffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
|
||||||
} else {
|
} else {
|
||||||
description += "domainSuffix=[" + strings.Join(domainSuffixes, " ") + "]"
|
description += "domain_suffix=[" + strings.Join(domainSuffixes, " ") + "]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &DomainItem{
|
return &DomainItem{
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ var tlsRegistry []func(conn net.Conn) (loaded bool, netConn net.Conn, reflectTyp
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer uintptr) {
|
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer uintptr) {
|
||||||
tlsConn, loaded := conn.(*tls.Conn)
|
tlsConn, loaded := common.Cast[*tls.Conn](conn)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user