Compare commits

..

30 Commits

Author SHA1 Message Date
世界
52167f5b94 documentation: Bump version 2024-04-23 23:41:37 +08:00
世界
22bb6a86e3 documentation: Update DNS manual 2024-04-23 23:40:37 +08:00
世界
5a6e0b6541 Add rule-set match command 2024-04-23 23:40:37 +08:00
世界
6ef266200f Add bypass_domain and search_domain platform HTTP proxy options 2024-04-23 23:40:37 +08:00
世界
61bab03fd3 Update gVisor to 20240212.0-65-g71212d503 2024-04-23 23:40:36 +08:00
世界
bc201898eb Update quic-go to v0.42.0 2024-04-23 23:40:36 +08:00
世界
3538205423 Fixed order for Clash modes 2024-04-23 23:40:36 +08:00
气息
ee0e1c9149 Fix DNS exchange index
Signed-off-by: 气息 <qdshizh@gmail.com>
2024-04-23 23:40:36 +08:00
PuerNya
53788a3521 Always disable cache for fake-ip DNS transport if independent_cache disabled 2024-04-23 23:40:36 +08:00
世界
0615f8f7d1 Fix missing rule_set_ipcidr_match_source item in DNS rules 2024-04-23 23:40:36 +08:00
世界
99a1ebd972 Improve DNS truncate behavior 2024-04-23 23:40:36 +08:00
世界
57b6f2aba8 Fix DNS fallthrough incorrectly 2024-04-23 23:40:35 +08:00
世界
eba3ed6f4a Add rejected DNS response cache support 2024-04-23 23:40:35 +08:00
世界
5797bec874 Add support for client-subnet DNS options 2024-04-23 23:40:35 +08:00
世界
f2df8affa8 Add address filter support for DNS rules 2024-04-23 23:40:35 +08:00
世界
889256ecca Fix timezone for Android and iOS 2024-04-23 23:40:22 +08:00
世界
4b1159bb3a Improve loopback detector 2024-04-23 23:40:22 +08:00
世界
2f2f3a368f Remove unused fakeip packet conn 2024-04-23 23:40:22 +08:00
世界
dae0e7eb76 Set the default TCP keep alive period 2024-04-23 23:40:22 +08:00
世界
95ea91bc31 Migrate ntp service to library 2024-04-23 23:40:22 +08:00
世界
de92f4ce89 Handle Windows power events 2024-04-23 23:40:22 +08:00
世界
1d028272b8 Improve domain suffix match behavior
For historical reasons, sing-box's `domain_suffix` rule matches literal prefixes instead of the same as other projects.

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

This change make QueryFullProcessImageNameW output a Win32 path (such as `C:\folder\program.exe`),
which will disrupt the existing `process_path` use cases in Windows.
2024-04-23 14:43:06 +08:00
世界
33d332db62 badtls: Support uTLS and TLS ECH for read waiter 2024-04-23 14:43:06 +08:00
世界
0ae1afef44 Bump version 2024-04-23 14:14:40 +08:00
世界
a5e2a4073b Update dependencies 2024-04-23 14:03:55 +08:00
世界
b6cb3948a3 Fix initial packet MTU for QUIC protocols 2024-04-23 11:12:31 +08:00
世界
7b0f5061dc Fix loopback detector 2024-04-17 21:45:54 +08:00
世界
76f20482f7 Fix linux repo 2024-04-12 22:52:37 +08:00
世界
e735a5bdc8 Update dependencies 2024-04-12 22:52:37 +08:00
21 changed files with 138 additions and 245 deletions

View File

@@ -17,6 +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:
@@ -27,3 +33,5 @@ jobs:
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 }}

View File

@@ -55,6 +55,14 @@ nfpms:
dst: /usr/lib/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
@@ -72,9 +80,8 @@ furies:
- account: sagernet
ids:
- package
skip: "{{ .Prerelease }}"
disable: "{{ not (not .Prerelease) }}"
- account: sagernet
ids:
- package_beta
skip: "{{ not .Prerelease }}"
disable: "{{ not .Prerelease }}"

View File

@@ -136,6 +136,8 @@ nfpms:
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 }}"

View File

@@ -2,7 +2,7 @@
icon: material/alert-decagram
---
#### 1.9.0-rc.6
#### 1.9.0-rc.11
* Fixes and improvements

View File

@@ -9,7 +9,7 @@ icon: material/package
=== ":material-debian: Debian / APT"
```bash
sudo curl -fsSL https://deb.sagernet.org/gpg.key -o /etc/apt/keyrings/sagernet.asc
sudo curl -fsSL https://sing-box.app/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/rpm.repo
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.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/rpm.repo
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
sudo yum install sing-box # or sing-box-beta
```

View File

@@ -9,7 +9,7 @@ icon: material/package
=== ":material-debian: Debian / APT"
```bash
sudo curl -fsSL https://deb.sagernet.org/gpg.key -o /etc/apt/keyrings/sagernet.asc
sudo curl -fsSL https://sing-box.app/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/rpm.repo
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.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/rpm.repo
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
sudo yum install sing-box # or sing-box-beta
```

View File

@@ -1,6 +0,0 @@
[sing-box]
name=sing-box
baseurl=https://rpm.sagernet.org/
enabled=1
gpgcheck=1
gpgkey=https://deb.sagernet.org/gpg.key

View File

@@ -0,0 +1,8 @@
[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

View File

@@ -9,7 +9,6 @@ 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"
@@ -75,7 +74,7 @@ func (s *platformInterfaceStub) UsePlatformInterfaceGetter() bool {
return true
}
func (s *platformInterfaceStub) Interfaces() ([]platform.NetworkInterface, error) {
func (s *platformInterfaceStub) Interfaces() ([]control.Interface, error) {
return nil, os.ErrInvalid
}

View File

@@ -2,7 +2,6 @@ package platform
import (
"context"
"net/netip"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/process"
@@ -20,16 +19,9 @@ type Interface interface {
UsePlatformDefaultInterfaceMonitor() bool
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
UsePlatformInterfaceGetter() bool
Interfaces() ([]NetworkInterface, error)
Interfaces() ([]control.Interface, error)
UnderNetworkExtension() bool
ClearDNSCache()
ReadWIFIState() adapter.WIFIState
process.Searcher
}
type NetworkInterface struct {
Index int
MTU int
Name string
Addresses []netip.Prefix
}

View File

@@ -192,14 +192,14 @@ func (w *platformInterfaceWrapper) UsePlatformInterfaceGetter() bool {
return w.iif.UsePlatformInterfaceGetter()
}
func (w *platformInterfaceWrapper) Interfaces() ([]platform.NetworkInterface, error) {
func (w *platformInterfaceWrapper) Interfaces() ([]control.Interface, error) {
interfaceIterator, err := w.iif.GetInterfaces()
if err != nil {
return nil, err
}
var interfaces []platform.NetworkInterface
var interfaces []control.Interface
for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) {
interfaces = append(interfaces, platform.NetworkInterface{
interfaces = append(interfaces, control.Interface{
Index: int(netInterface.Index),
MTU: int(netInterface.MTU),
Name: netInterface.Name,

19
go.mod
View File

@@ -11,25 +11,25 @@ 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.0.0
github.com/gofrs/uuid/v5 v5.1.0
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
github.com/libdns/alidns v1.0.3
github.com/libdns/cloudflare v0.1.1
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/mholt/acmez v1.2.0
github.com/miekg/dns v1.1.58
github.com/miekg/dns v1.1.59
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.2
github.com/sagernet/quic-go v0.42.0-beta.3
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.4.0-beta.12
github.com/sagernet/sing v0.4.0-beta.18
github.com/sagernet/sing-dns v0.2.0-beta.16
github.com/sagernet/sing-mux v0.2.0
github.com/sagernet/sing-quic v0.1.12-beta.1
github.com/sagernet/sing-quic v0.1.13-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
@@ -48,7 +48,7 @@ require (
golang.org/x/net v0.24.0
golang.org/x/sys v0.19.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.63.0
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.33.0
howett.net/plist v1.0.1
)
@@ -84,11 +84,12 @@ require (
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-20240325151524-a685a6edb6d8 // indirect
golang.org/x/mod v0.16.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/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.19.0 // indirect
golang.org/x/tools v0.20.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

39
go.sum
View File

@@ -34,8 +34,8 @@ 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.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
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/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
@@ -71,8 +71,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/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
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/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
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=
@@ -101,19 +101,19 @@ github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311 h1:eUQ6kJZXK77xYZe
github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311/go.mod h1:mDrXZSv401qiaFiiIUC59Zp4VG5f4nqXFqDmp5o3hYI=
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.2 h1:E6vTGhveFE9Tnhu5rrt3M5fnENuqBJOv8gPcFPz0cSM=
github.com/sagernet/quic-go v0.42.0-beta.2/go.mod h1:lf8OYop+fMxIlrfM/ZHpENt/7ZD4JaVNqMhOlq2QMwg=
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/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.12 h1:f0f8DBPNf91NoAnJWm25LjPy/rC6u0R/nWIsGysl1cc=
github.com/sagernet/sing v0.4.0-beta.12/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
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-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.12-beta.1 h1:6vh9AIuJfCYYsUSLZEgoAtb7kD97TQmPYgInA881lF8=
github.com/sagernet/sing-quic v0.1.12-beta.1/go.mod h1:TTnOMr3o3rI+zNxTo+SGBJwouzjIEC3FchJJY1F1ca4=
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-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=
@@ -165,15 +165,16 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
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-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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/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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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=
@@ -194,14 +195,14 @@ 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.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
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.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
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/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=

View File

@@ -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(),
loopBack: newLoopBackDetector(router),
}
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))
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination)
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()) {
if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
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()) {
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
return E.New("reject loopback packet connection to ", metadata.Destination)
}
return NewPacketConnection(ctx, h, conn, metadata)

View File

@@ -5,63 +5,95 @@ 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]bool
packetConnMap map[netip.AddrPort]bool
connMap map[netip.AddrPort]netip.AddrPort
packetConnMap map[uint16]uint16
}
func newLoopBackDetector() *loopBackDetector {
func newLoopBackDetector(router adapter.Router) *loopBackDetector {
return &loopBackDetector{
connMap: make(map[netip.AddrPort]bool),
packetConnMap: make(map[netip.AddrPort]bool),
router: router,
connMap: make(map[netip.AddrPort]netip.AddrPort),
packetConnMap: make(map[uint16]uint16),
}
}
func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
connAddr := M.AddrPortFromNet(conn.LocalAddr())
if !connAddr.IsValid() {
source := M.AddrPortFromNet(conn.LocalAddr())
if !source.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[connAddr] = true
l.packetConnMap[source.Port()] = M.AddrPortFromNet(conn.RemoteAddr()).Port()
l.packetConnAccess.Unlock()
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connAddr: connAddr}
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connPort: source.Port()}
} else {
l.connAccess.Lock()
l.connMap[connAddr] = true
l.connMap[source] = M.AddrPortFromNet(conn.RemoteAddr())
l.connAccess.Unlock()
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: connAddr}
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: source}
}
}
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn) N.NetPacketConn {
connAddr := M.AddrPortFromNet(conn.LocalAddr())
if !connAddr.IsValid() {
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn, destination M.Socksaddr) N.NetPacketConn {
source := M.AddrPortFromNet(conn.LocalAddr())
if !source.IsValid() {
return conn
}
if !source.Addr().IsLoopback() {
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
if err != nil {
return conn
}
}
l.packetConnAccess.Lock()
l.packetConnMap[connAddr] = true
l.packetConnMap[source.Port()] = destination.AddrPort().Port()
l.packetConnAccess.Unlock()
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connAddr: connAddr}
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connPort: source.Port()}
}
func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
func (l *loopBackDetector) CheckConn(source netip.AddrPort, local netip.AddrPort) bool {
l.connAccess.RLock()
defer l.connAccess.RUnlock()
return l.connMap[connAddr]
destination, loaded := l.connMap[source]
return loaded && destination != local
}
func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
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
}
l.packetConnAccess.RLock()
defer l.packetConnAccess.RUnlock()
return l.packetConnMap[connAddr]
destinationPort, loaded := l.packetConnMap[source.Port()]
return loaded && destinationPort != local.Port()
}
type loopBackDetectWrapper struct {
@@ -95,14 +127,14 @@ func (w *loopBackDetectWrapper) Upstream() any {
type loopBackDetectPacketWrapper struct {
N.NetPacketConn
detector *loopBackDetector
connAddr netip.AddrPort
connPort uint16
closeOnce sync.Once
}
func (w *loopBackDetectPacketWrapper) Close() error {
w.closeOnce.Do(func() {
w.detector.packetConnAccess.Lock()
delete(w.detector.packetConnMap, w.connAddr)
delete(w.detector.packetConnMap, w.connPort)
w.detector.packetConnAccess.Unlock()
})
return w.NetPacketConn.Close()
@@ -128,14 +160,14 @@ type abstractUDPConn interface {
type loopBackDetectUDPWrapper struct {
abstractUDPConn
detector *loopBackDetector
connAddr netip.AddrPort
connPort uint16
closeOnce sync.Once
}
func (w *loopBackDetectUDPWrapper) Close() error {
w.closeOnce.Do(func() {
w.detector.packetConnAccess.Lock()
delete(w.detector.packetConnMap, w.connAddr)
delete(w.detector.packetConnMap, w.connPort)
w.detector.packetConnAccess.Unlock()
})
return w.abstractUDPConn.Close()

View File

@@ -1,54 +0,0 @@
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
}

View File

@@ -80,7 +80,7 @@ type Router struct {
transportDomainStrategy map[dns.Transport]dns.DomainStrategy
dnsReverseMapping *DNSReverseMapping
fakeIPStore adapter.FakeIPStore
interfaceFinder myInterfaceFinder
interfaceFinder *control.DefaultInterfaceFinder
autoDetectInterface bool
defaultInterface string
defaultMark int
@@ -126,6 +126,7 @@ 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,
@@ -335,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,
@@ -1098,24 +1099,18 @@ 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(common.Map(interfaces, func(it platform.NetworkInterface) net.Interface {
return net.Interface{
Name: it.Name,
Index: it.Index,
MTU: it.MTU,
}
}))
r.interfaceFinder.UpdateInterfaces(interfaces)
return nil
}
}

View File

@@ -1,55 +0,0 @@
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
}

View File

@@ -1,37 +0,0 @@
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
}