Compare commits

..

65 Commits

Author SHA1 Message Date
世界
b1f24b0a32
Improve sniffer 2025-04-04 11:46:17 +08:00
世界
c1efd5638c
Fix build yml 2025-04-04 11:45:20 +08:00
世界
064adf66aa
documentation: Bump version 2025-04-03 16:23:31 +08:00
世界
6e77b60b6b
release: Update Go to 1.24.2 2025-04-03 16:23:31 +08:00
Mahdi
4972888354
Fix conn copy 2025-04-03 16:16:42 +08:00
世界
99ea4c7ea9
Allow direct outbounds without domain_resolver 2025-04-02 20:57:47 +08:00
世界
492e2826ca
Fix Tailscale dialer 2025-04-02 20:57:47 +08:00
dyhkwong
b0421bdcfc
Fix DNS over QUIC stream close 2025-04-02 20:57:47 +08:00
anytls
9e8eff51c0
Update anytls
Co-authored-by: anytls <anytls>
2025-04-02 20:57:47 +08:00
Rambling2076
b57274e1ec
Fix missing with_tailscale in Dockerfile
Signed-off-by: Rambling2076 <Rambling2076@proton.me>
2025-04-02 20:57:47 +08:00
世界
627bec7266
Fail when default DNS server not found 2025-04-02 20:57:47 +08:00
世界
31116ef3d2
Update gVisor to 20250319.0 2025-04-02 20:57:47 +08:00
世界
df5baa733d
release: Do not build tailscale on iOS and tvOS 2025-04-02 20:57:47 +08:00
世界
a64c520de2
Explicitly reject detour to empty direct outbounds 2025-04-02 16:54:47 +08:00
世界
74bfea713d
Add netns support 2025-04-02 16:54:47 +08:00
世界
63f10d37ff
Add wildcard name support for predefined records 2025-04-02 16:54:46 +08:00
世界
8c231fbc38
Remove map usage in options 2025-04-02 16:54:46 +08:00
世界
1cfbee8293
Fix unhandled DNS loop 2025-04-02 16:54:46 +08:00
世界
529d41ed6a
Add wildcard-sni support for shadow-tls inbound 2025-04-02 16:54:46 +08:00
世界
8af464eb7e
Fix Tailscale DNS 2025-04-02 16:51:29 +08:00
k9982874
3766bbbf9d
Add ntp protocol sniffing 2025-04-02 16:51:28 +08:00
世界
0d65af5d0a
option: Fix marshal legacy DNS options 2025-04-02 16:51:28 +08:00
世界
439f3c05ec
Make domain_resolver optional when only one DNS server is configured 2025-04-02 16:51:28 +08:00
世界
e3a1e71e4d
Fix DNS lookup context pollution 2025-04-02 16:51:27 +08:00
世界
83c284749e
Fix http3 DNS server connecting to wrong address 2025-04-02 16:51:26 +08:00
Restia-Ashbell
d95fc51be4
documentation: Fix typo 2025-04-02 16:51:26 +08:00
anytls
6cccfafc10
Update sing-anytls
Co-authored-by: anytls <anytls>
2025-04-02 16:51:25 +08:00
k9982874
650e85e684
Fix hosts DNS server 2025-04-02 16:51:25 +08:00
世界
edfd6fb29d
Fix UDP DNS server crash 2025-04-02 16:51:25 +08:00
世界
452ca3f5e6
documentation: Fix missing ip_accept_any DNS rule option 2025-04-02 16:51:24 +08:00
世界
693da37d62
Fix anytls dialer usage 2025-04-02 16:51:24 +08:00
世界
4f902b8507
Move predefined DNS server to rule action 2025-04-02 16:51:23 +08:00
世界
de9ceb82bb
Fix domain resolver on direct outbound 2025-04-02 16:51:23 +08:00
Zephyruso
112508ccbb
Fix missing AnyTLS display name 2025-04-02 16:51:23 +08:00
anytls
6fb224dd05
Update sing-anytls
Co-authored-by: anytls <anytls>
2025-04-02 16:51:23 +08:00
Estel
683c5b71ed
documentation: Fix typo
Signed-off-by: Estel <callmebedrockdigger@gmail.com>
2025-04-02 16:51:23 +08:00
TargetLocked
174b857658
Fix parsing legacy DNS options 2025-04-02 16:51:22 +08:00
世界
5d63c7a0da
Fix DNS fallback 2025-04-02 16:51:21 +08:00
世界
09f89b4181
documentation: Fix missing hosts DNS server 2025-04-02 16:51:21 +08:00
anytls
c9522fd6d6
Add MinIdleSession option to AnyTLS outbound
Co-authored-by: anytls <anytls>
2025-04-02 16:51:21 +08:00
ReleTor
9e9886b140
documentation: Minor fixes 2025-04-02 16:51:21 +08:00
libtry486
f5dc2ec1dc
documentation: Fix typo
fix typo

Signed-off-by: libtry486 <89328481+libtry486@users.noreply.github.com>
2025-04-02 16:51:21 +08:00
Alireza Ahmadi
e0202da833
Fix Outbound deadlock 2025-04-02 16:51:20 +08:00
世界
db01fe90e4
documentation: Fix AnyTLS doc 2025-04-02 16:51:20 +08:00
anytls
104ea172c0
Add AnyTLS protocol 2025-04-02 16:51:20 +08:00
世界
341958d7c1
Migrate to stdlib ECH support 2025-04-02 16:51:19 +08:00
世界
05fea2a199
Add fallback local DNS server for iOS 2025-04-02 16:51:18 +08:00
世界
cc294c4616
Get darwin local DNS server from libresolv 2025-04-02 16:51:18 +08:00
世界
b99c6a0025
Improve resolve action 2025-04-02 16:51:18 +08:00
世界
845138a1d8
Fix toolchain version 2025-04-02 16:51:17 +08:00
世界
0645ebe73f
Add back port hopping to hysteria 1 2025-04-02 16:51:17 +08:00
世界
1847cb6dfb
Update dependencies 2025-04-02 16:51:17 +08:00
xchacha20-poly1305
1dd716453d
Remove single quotes of raw Moziila certs 2025-04-02 16:51:16 +08:00
世界
456eb3dcdc
Add Tailscale endpoint 2025-04-02 16:51:16 +08:00
世界
8f9454ce72
Build legacy binaries with latest Go 2025-04-02 16:51:15 +08:00
世界
3bae0c96bc
documentation: Remove outdated icons 2025-04-02 16:51:15 +08:00
世界
0153fc7e08
documentation: Certificate store 2025-04-02 16:51:15 +08:00
世界
a52ee299e6
documentation: TLS fragment 2025-04-02 16:51:15 +08:00
世界
bf0e71f32a
documentation: Outbound domain resolver 2025-04-02 16:51:15 +08:00
世界
b2dcb4dc03
documentation: Refactor DNS 2025-04-02 16:51:13 +08:00
世界
221c003ce0
Add certificate store 2025-04-02 16:51:13 +08:00
世界
8b7c8dcdb4
Add TLS fragment support 2025-04-02 16:51:13 +08:00
世界
360b25e53c
refactor: Outbound domain resolver 2025-04-02 16:51:12 +08:00
世界
6c9e61a0a0
refactor: DNS 2025-04-02 16:51:12 +08:00
世界
572ee775b1
Bump version 2025-04-02 16:50:36 +08:00
21 changed files with 93 additions and 110 deletions

View File

@ -30,7 +30,7 @@ jobs:
with:
go-version: ^1.24.2
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
uses: golangci/golangci-lint-action@v6
with:
version: latest
args: --timeout=30m

View File

@ -24,7 +24,7 @@ type Router interface {
RuleSet(tag string) (RuleSet, bool)
NeedWIFIState() bool
Rules() []Rule
AppendTracker(tracker ConnectionTracker)
SetTracker(tracker ConnectionTracker)
ResetNetwork()
}

4
box.go
View File

@ -314,7 +314,7 @@ func New(options Options) (*Box, error) {
if err != nil {
return nil, E.Cause(err, "create clash-server")
}
router.AppendTracker(clashServer)
router.SetTracker(clashServer)
service.MustRegister[adapter.ClashServer](ctx, clashServer)
services = append(services, clashServer)
}
@ -324,7 +324,7 @@ func New(options Options) (*Box, error) {
return nil, E.Cause(err, "create v2ray-server")
}
if v2rayServer.StatsService() != nil {
router.AppendTracker(v2rayServer.StatsService())
router.SetTracker(v2rayServer.StatsService())
services = append(services, v2rayServer)
service.MustRegister[adapter.V2RayServer](ctx, v2rayServer)
}

View File

@ -68,9 +68,7 @@ func UTP(_ context.Context, metadata *adapter.InboundContext, packet []byte) err
if err != nil {
return err
}
if extension > 0x04 {
return os.ErrInvalid
}
var length byte
err = binary.Read(reader, binary.BigEndian, &length)
if err != nil {

View File

@ -71,19 +71,3 @@ func TestSniffUDPTracker(t *testing.T) {
require.Equal(t, C.ProtocolBitTorrent, metadata.Protocol)
}
}
func TestSniffNotUTP(t *testing.T) {
t.Parallel()
packets := []string{
"0102736470696e674958d580121500000000000079aaed6717a39c27b07c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
}
for _, pkt := range packets {
pkt, err := hex.DecodeString(pkt)
require.NoError(t, err)
var metadata adapter.InboundContext
err = sniff.UTP(context.TODO(), &metadata, pkt)
require.Error(t, err)
}
}

View File

@ -123,7 +123,6 @@ func (s *STDECHClientConfig) ClientHandshake(ctx context.Context, conn net.Conn)
if response.Rcode != mDNS.RcodeSuccess {
return nil, E.Cause(dns.RcodeError(response.Rcode), "fetch ECH config list")
}
match:
for _, rr := range response.Answer {
switch resource := rr.(type) {
case *mDNS.HTTPS:
@ -134,14 +133,11 @@ func (s *STDECHClientConfig) ClientHandshake(ctx context.Context, conn net.Conn)
return nil, E.Cause(err, "decode ECH config")
}
s.config.EncryptedClientHelloConfigList = echConfigList
break match
}
}
}
}
if len(s.config.EncryptedClientHelloConfigList) == 0 {
return nil, E.New("no ECH config found in DNS records")
}
return nil, E.New("no ECH config found in DNS records")
}
tlsConn, err := s.Client(conn)
if err != nil {

View File

@ -11,6 +11,7 @@ const (
ProtocolSSH = "ssh"
ProtocolRDP = "rdp"
ProtocolNTP = "ntp"
ProtocolMTProto = "mtproto"
)
const (

View File

@ -212,8 +212,8 @@ type dnsConnection struct {
func (c *dnsConnection) Close(err error) {
c.closeOnce.Do(func() {
c.err = err
close(c.done)
c.err = err
})
c.Conn.Close()
}

View File

@ -26,7 +26,7 @@ If enabled in the inbound, the protocol and domain name (if present) of by the c
| QUIC Client | Type |
|:------------------------:|:----------:|
| Chromium/Cronet | `chromium` |
| Chromium/Cronet | `chrimium` |
| Safari/Apple Network API | `safari` |
| Firefox / uquic firefox | `firefox` |
| quic-go / uquic chrome | `quic-go` |
| quic-go / uquic chrome | `quic-go` |

View File

@ -39,7 +39,7 @@ type BoxService struct {
clashServer adapter.ClashServer
pauseManager pause.Manager
iOSPauseFields
servicePauseFields
}
func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {

View File

@ -1,33 +1,31 @@
package libbox
import (
"sync"
"time"
C "github.com/sagernet/sing-box/constant"
)
type iOSPauseFields struct {
endPauseTimer *time.Timer
type servicePauseFields struct {
pauseAccess sync.Mutex
pauseTimer *time.Timer
}
func (s *BoxService) Pause() {
s.pauseManager.DevicePause()
if !C.IsIos {
s.instance.Router().ResetNetwork()
} else {
if s.endPauseTimer == nil {
s.endPauseTimer = time.AfterFunc(time.Minute, s.pauseManager.DeviceWake)
} else {
s.endPauseTimer.Reset(time.Minute)
}
s.pauseAccess.Lock()
defer s.pauseAccess.Unlock()
if s.pauseTimer != nil {
s.pauseTimer.Stop()
}
s.pauseTimer = time.AfterFunc(3*time.Second, s.ResetNetwork)
}
func (s *BoxService) Wake() {
if !C.IsIos {
s.pauseManager.DeviceWake()
s.instance.Router().ResetNetwork()
s.pauseAccess.Lock()
defer s.pauseAccess.Unlock()
if s.pauseTimer != nil {
s.pauseTimer.Stop()
}
s.pauseTimer = time.AfterFunc(3*time.Minute, s.ResetNetwork)
}
func (s *BoxService) ResetNetwork() {

6
go.mod
View File

@ -9,7 +9,7 @@ require (
github.com/cretz/bine v0.2.0
github.com/go-chi/chi/v5 v5.2.1
github.com/go-chi/render v1.0.3
github.com/gofrs/uuid/v5 v5.3.2
github.com/gofrs/uuid/v5 v5.3.1
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905
github.com/libdns/alidns v1.0.3
github.com/libdns/cloudflare v0.1.1
@ -26,9 +26,9 @@ require (
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
github.com/sagernet/quic-go v0.49.0-beta.1
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.6.6-0.20250406122223-d47540857e58
github.com/sagernet/sing v0.6.6-0.20250403102645-159e489fc399
github.com/sagernet/sing-mux v0.3.1
github.com/sagernet/sing-quic v0.4.1
github.com/sagernet/sing-quic v0.4.1-beta.1
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056

12
go.sum
View File

@ -66,8 +66,8 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg=
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU=
github.com/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0=
github.com/gofrs/uuid/v5 v5.3.2/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/gofrs/uuid/v5 v5.3.1 h1:aPx49MwJbekCzOyhZDjJVb0hx3A0KLjlbLx6p2gY0p0=
github.com/gofrs/uuid/v5 v5.3.1/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@ -178,12 +178,12 @@ github.com/sagernet/quic-go v0.49.0-beta.1/go.mod h1:uesWD1Ihrldq1M3XtjuEvIUqi8W
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
github.com/sagernet/sing v0.6.6-0.20250406122223-d47540857e58 h1:hq0W1/K6/UOrv+tCm9YrZ/yDFZJlPVtLmBvayuwUxDM=
github.com/sagernet/sing v0.6.6-0.20250406122223-d47540857e58/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing v0.6.6-0.20250403102645-159e489fc399 h1:jQ5sGyxICxdPqoakOEE6TbSTYOf/grmt31e/ad749O4=
github.com/sagernet/sing v0.6.6-0.20250403102645-159e489fc399/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-mux v0.3.1 h1:kvCc8HyGAskDHDQ0yQvoTi/7J4cZPB/VJMsAM3MmdQI=
github.com/sagernet/sing-mux v0.3.1/go.mod h1:Mkdz8LnDstthz0HWuA/5foncnDIdcNN5KZ6AdJX+x78=
github.com/sagernet/sing-quic v0.4.1 h1:pxlMa4efZu/M07RgGagNNDDyl6ZUwpmNUjRTpgHOWK4=
github.com/sagernet/sing-quic v0.4.1/go.mod h1:tqPa0/Wqa19MkkSlKVZZX5sHxtiDR9BROcn4ufcbVdY=
github.com/sagernet/sing-quic v0.4.1-beta.1 h1:V2VfMckT3EQR3ZdfSzJgZZDsvfZZH42QAZpnOnHKa0s=
github.com/sagernet/sing-quic v0.4.1-beta.1/go.mod h1:c+CytOEyeN20KCTFIP8YQUkNDVFLSzjrEPqP7Hlnxys=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=

View File

@ -19,7 +19,6 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/x/list"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/pause"
)
@ -28,7 +27,10 @@ func RegisterURLTest(registry *outbound.Registry) {
outbound.Register[option.URLTestOutboundOptions](registry, C.TypeURLTest, NewURLTest)
}
var _ adapter.OutboundGroup = (*URLTest)(nil)
var (
_ adapter.OutboundGroup = (*URLTest)(nil)
_ adapter.InterfaceUpdateListener = (*URLTest)(nil)
)
type URLTest struct {
outbound.Adapter
@ -170,12 +172,15 @@ func (s *URLTest) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn,
s.connection.NewPacketConnection(ctx, s, conn, metadata, onClose)
}
func (s *URLTest) InterfaceUpdated() {
go s.group.CheckOutbounds(true)
return
}
type URLTestGroup struct {
ctx context.Context
router adapter.Router
outbound adapter.OutboundManager
pause pause.Manager
pauseCallback *list.Element[pause.Callback]
outboundManager adapter.OutboundManager
logger log.Logger
outbounds []adapter.Outbound
link string
@ -184,15 +189,17 @@ type URLTestGroup struct {
idleTimeout time.Duration
history adapter.URLTestHistoryStorage
checking atomic.Bool
pauseManager pause.Manager
selectedOutboundTCP adapter.Outbound
selectedOutboundUDP adapter.Outbound
interruptGroup *interrupt.Group
interruptExternalConnections bool
access sync.Mutex
ticker *time.Ticker
close chan struct{}
started bool
lastActive atomic.TypedValue[time.Time]
access sync.Mutex
ticker *time.Ticker
close chan struct{}
started bool
lastActive atomic.TypedValue[time.Time]
}
func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManager, logger log.Logger, outbounds []adapter.Outbound, link string, interval time.Duration, tolerance uint16, idleTimeout time.Duration, interruptExternalConnections bool) (*URLTestGroup, error) {
@ -218,7 +225,7 @@ func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManage
}
return &URLTestGroup{
ctx: ctx,
outbound: outboundManager,
outboundManager: outboundManager,
logger: logger,
outbounds: outbounds,
link: link,
@ -227,15 +234,13 @@ func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManage
idleTimeout: idleTimeout,
history: history,
close: make(chan struct{}),
pause: service.FromContext[pause.Manager](ctx),
pauseManager: service.FromContext[pause.Manager](ctx),
interruptGroup: interrupt.NewGroup(),
interruptExternalConnections: interruptExternalConnections,
}, nil
}
func (g *URLTestGroup) PostStart() {
g.access.Lock()
defer g.access.Unlock()
g.started = true
g.lastActive.Store(time.Now())
go g.CheckOutbounds(false)
@ -245,25 +250,24 @@ func (g *URLTestGroup) Touch() {
if !g.started {
return
}
g.access.Lock()
defer g.access.Unlock()
if g.ticker != nil {
g.lastActive.Store(time.Now())
return
}
g.access.Lock()
defer g.access.Unlock()
if g.ticker != nil {
return
}
g.ticker = time.NewTicker(g.interval)
go g.loopCheck()
g.pauseCallback = pause.RegisterTicker(g.pause, g.ticker, g.interval, nil)
}
func (g *URLTestGroup) Close() error {
g.access.Lock()
defer g.access.Unlock()
if g.ticker == nil {
return nil
}
g.ticker.Stop()
g.pause.UnregisterCallback(g.pauseCallback)
close(g.close)
return nil
}
@ -327,11 +331,10 @@ func (g *URLTestGroup) loopCheck() {
g.access.Lock()
g.ticker.Stop()
g.ticker = nil
g.pause.UnregisterCallback(g.pauseCallback)
g.pauseCallback = nil
g.access.Unlock()
return
}
g.pauseManager.WaitActive()
g.CheckOutbounds(false)
}
}
@ -364,7 +367,7 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
continue
}
checked[realTag] = true
p, loaded := g.outbound.Outbound(realTag)
p, loaded := g.outboundManager.Outbound(realTag)
if !loaded {
continue
}

View File

@ -129,6 +129,7 @@ func (w *Endpoint) Close() error {
func (w *Endpoint) InterfaceUpdated() {
w.endpoint.BindUpdate()
return
}
func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error {

View File

@ -133,6 +133,7 @@ func (o *Outbound) Close() error {
func (o *Outbound) InterfaceUpdated() {
o.endpoint.BindUpdate()
return
}
func (o *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {

View File

@ -59,6 +59,10 @@ func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata
}
func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
if r.pauseManager.IsDevicePaused() {
return E.New("reject connection to ", metadata.Destination, " while device paused")
}
//nolint:staticcheck
if metadata.InboundDetour != "" {
if metadata.LastInbound == metadata.InboundDetour {
@ -135,8 +139,8 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
for _, buffer := range buffers {
conn = bufio.NewCachedConn(conn, buffer)
}
for _, tracker := range r.trackers {
conn = tracker.RoutedConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
if r.tracker != nil {
conn = r.tracker.RoutedConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
}
if outboundHandler, isHandler := selectedOutbound.(adapter.ConnectionHandlerEx); isHandler {
outboundHandler.NewConnectionEx(ctx, conn, metadata, onClose)
@ -181,6 +185,9 @@ func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn,
}
func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
if r.pauseManager.IsDevicePaused() {
return E.New("reject packet connection to ", metadata.Destination, " while device paused")
}
//nolint:staticcheck
if metadata.InboundDetour != "" {
if metadata.LastInbound == metadata.InboundDetour {
@ -250,8 +257,8 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
N.PutPacketBuffer(buffer)
}
for _, tracker := range r.trackers {
conn = tracker.RoutedPacketConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
if r.tracker != nil {
conn = r.tracker.RoutedPacketConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
}
if metadata.FakeIP {
conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)

View File

@ -36,7 +36,7 @@ type Router struct {
ruleSetMap map[string]adapter.RuleSet
processSearcher process.Searcher
pauseManager pause.Manager
trackers []adapter.ConnectionTracker
tracker adapter.ConnectionTracker
platformInterface platform.Interface
needWIFIState bool
started bool
@ -203,8 +203,8 @@ func (r *Router) Rules() []adapter.Rule {
return r.rules
}
func (r *Router) AppendTracker(tracker adapter.ConnectionTracker) {
r.trackers = append(r.trackers, tracker)
func (r *Router) SetTracker(tracker adapter.ConnectionTracker) {
r.tracker = tracker
}
func (r *Router) ResetNetwork() {

View File

@ -305,9 +305,6 @@ func (r *RuleActionReject) Error(ctx context.Context) error {
default:
panic(F.ToString("unknown reject method: ", r.Method))
}
if r.NoDrop {
return returnErr
}
r.dropAccess.Lock()
defer r.dropAccess.Unlock()
timeNow := time.Now()

View File

@ -105,7 +105,7 @@ func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.
}
}
if s.lastUpdated.IsZero() {
err := s.fetch(ctx, startContext)
err := s.fetchOnce(ctx, startContext)
if err != nil {
return E.Cause(err, "initial rule-set: ", s.options.Tag)
}
@ -200,7 +200,7 @@ func (s *RemoteRuleSet) loadBytes(content []byte) error {
func (s *RemoteRuleSet) loopUpdate() {
if time.Since(s.lastUpdated) > s.updateInterval {
err := s.fetch(s.ctx, nil)
err := s.fetchOnce(s.ctx, nil)
if err != nil {
s.logger.Error("fetch rule-set ", s.options.Tag, ": ", err)
} else if s.refs.Load() == 0 {
@ -213,21 +213,18 @@ func (s *RemoteRuleSet) loopUpdate() {
case <-s.ctx.Done():
return
case <-s.updateTicker.C:
s.updateOnce()
s.pauseManager.WaitActive()
err := s.fetchOnce(s.ctx, nil)
if err != nil {
s.logger.Error("fetch rule-set ", s.options.Tag, ": ", err)
} else if s.refs.Load() == 0 {
s.rules = nil
}
}
}
}
func (s *RemoteRuleSet) updateOnce() {
err := s.fetch(s.ctx, nil)
if err != nil {
s.logger.Error("fetch rule-set ", s.options.Tag, ": ", err)
} else if s.refs.Load() == 0 {
s.rules = nil
}
}
func (s *RemoteRuleSet) fetch(ctx context.Context, startContext *adapter.HTTPStartContext) error {
func (s *RemoteRuleSet) fetchOnce(ctx context.Context, startContext *adapter.HTTPStartContext) error {
s.logger.Debug("updating rule-set ", s.options.Tag, " from URL: ", s.options.RemoteOptions.URL)
var httpClient *http.Client
if startContext != nil {

View File

@ -30,7 +30,7 @@ type Endpoint struct {
allowedAddress []netip.Prefix
tunDevice Device
device *device.Device
pause pause.Manager
pauseManager pause.Manager
pauseCallback *list.Element[pause.Callback]
}
@ -187,9 +187,9 @@ func (e *Endpoint) Start(resolve bool) error {
return E.Cause(err, "setup wireguard: \n", ipcConf)
}
e.device = wgDevice
e.pause = service.FromContext[pause.Manager](e.options.Context)
if e.pause != nil {
e.pauseCallback = e.pause.RegisterCallback(e.onPauseUpdated)
e.pauseManager = service.FromContext[pause.Manager](e.options.Context)
if e.pauseManager != nil {
e.pauseCallback = e.pauseManager.RegisterCallback(e.onPauseUpdated)
}
return nil
}
@ -217,16 +217,16 @@ func (e *Endpoint) Close() error {
e.device.Close()
}
if e.pauseCallback != nil {
e.pause.UnregisterCallback(e.pauseCallback)
e.pauseManager.UnregisterCallback(e.pauseCallback)
}
return nil
}
func (e *Endpoint) onPauseUpdated(event int) {
switch event {
case pause.EventDevicePaused, pause.EventNetworkPause:
case pause.EventDevicePaused:
e.device.Down()
case pause.EventDeviceWake, pause.EventNetworkWake:
case pause.EventDeviceWake:
e.device.Up()
}
}