Skip to content

Commit 687e631

Browse files
committed
Add inline rule-set & Add reload for local rule-set
1 parent a276121 commit 687e631

File tree

13 files changed

+298
-270
lines changed

13 files changed

+298
-270
lines changed

cmd/sing-box/cmd_rule_set_compile.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ func compileRuleSet(sourcePath string) error {
5555
if err != nil {
5656
return err
5757
}
58-
ruleSet := plainRuleSet.Upgrade()
58+
ruleSet, err := plainRuleSet.Upgrade()
59+
if err != nil {
60+
return err
61+
}
5962
var outputPath string
6063
if flagRuleSetCompileOutput == flagRuleSetCompileDefaultOutput {
6164
if strings.HasSuffix(sourcePath, ".json") {

cmd/sing-box/cmd_rule_set_match.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ func ruleSetMatch(sourcePath string, domain string) error {
6363
if err != nil {
6464
return err
6565
}
66-
plainRuleSet = compat.Upgrade()
66+
plainRuleSet, err = compat.Upgrade()
67+
if err != nil {
68+
return err
69+
}
6770
case C.RuleSetFormatBinary:
6871
plainRuleSet, err = srs.Read(bytes.NewReader(content), false)
6972
if err != nil {

common/tls/ech_server.go

Lines changed: 58 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ import (
1111
"strings"
1212

1313
cftls "github.com/sagernet/cloudflare-tls"
14+
"github.com/sagernet/fswatch"
1415
"github.com/sagernet/sing-box/log"
1516
"github.com/sagernet/sing-box/option"
1617
E "github.com/sagernet/sing/common/exceptions"
1718
"github.com/sagernet/sing/common/ntp"
18-
19-
"github.com/fsnotify/fsnotify"
2019
)
2120

2221
type echServerConfig struct {
@@ -26,9 +25,8 @@ type echServerConfig struct {
2625
key []byte
2726
certificatePath string
2827
keyPath string
29-
watcher *fsnotify.Watcher
3028
echKeyPath string
31-
echWatcher *fsnotify.Watcher
29+
watcher *fswatch.Watcher
3230
}
3331

3432
func (c *echServerConfig) ServerName() string {
@@ -66,159 +64,92 @@ func (c *echServerConfig) Clone() Config {
6664
}
6765

6866
func (c *echServerConfig) Start() error {
69-
if c.certificatePath != "" && c.keyPath != "" {
70-
err := c.startWatcher()
71-
if err != nil {
72-
c.logger.Warn("create fsnotify watcher: ", err)
73-
}
74-
}
75-
if c.echKeyPath != "" {
76-
err := c.startECHWatcher()
77-
if err != nil {
78-
c.logger.Warn("create fsnotify watcher: ", err)
79-
}
67+
err := c.startWatcher()
68+
if err != nil {
69+
c.logger.Warn("create credentials watcher: ", err)
8070
}
8171
return nil
8272
}
8373

8474
func (c *echServerConfig) startWatcher() error {
85-
watcher, err := fsnotify.NewWatcher()
86-
if err != nil {
87-
return err
88-
}
75+
var watchPath []string
8976
if c.certificatePath != "" {
90-
err = watcher.Add(c.certificatePath)
91-
if err != nil {
92-
return err
93-
}
77+
watchPath = append(watchPath, c.certificatePath)
9478
}
9579
if c.keyPath != "" {
96-
err = watcher.Add(c.keyPath)
97-
if err != nil {
98-
return err
99-
}
80+
watchPath = append(watchPath, c.keyPath)
81+
}
82+
if c.echKeyPath != "" {
83+
watchPath = append(watchPath, c.echKeyPath)
84+
}
85+
if len(watchPath) == 0 {
86+
return nil
87+
}
88+
watcher, err := fswatch.NewWatcher(fswatch.Options{
89+
Path: watchPath,
90+
Callback: func(path string) {
91+
err := c.credentialsUpdated(path)
92+
if err != nil {
93+
c.logger.Error(E.Cause(err, "reload credentials from ", path))
94+
}
95+
},
96+
})
97+
if err != nil {
98+
return err
10099
}
101100
c.watcher = watcher
102-
go c.loopUpdate()
103101
return nil
104102
}
105103

106-
func (c *echServerConfig) loopUpdate() {
107-
for {
108-
select {
109-
case event, ok := <-c.watcher.Events:
110-
if !ok {
111-
return
112-
}
113-
if event.Op&fsnotify.Write != fsnotify.Write {
114-
continue
115-
}
116-
err := c.reloadKeyPair()
104+
func (c *echServerConfig) credentialsUpdated(path string) error {
105+
if path == c.certificatePath || path == c.keyPath {
106+
if path == c.certificatePath {
107+
certificate, err := os.ReadFile(c.certificatePath)
117108
if err != nil {
118-
c.logger.Error(E.Cause(err, "reload TLS key pair"))
109+
return err
119110
}
120-
case err, ok := <-c.watcher.Errors:
121-
if !ok {
122-
return
111+
c.certificate = certificate
112+
} else {
113+
key, err := os.ReadFile(c.keyPath)
114+
if err != nil {
115+
return err
123116
}
124-
c.logger.Error(E.Cause(err, "fsnotify error"))
117+
c.key = key
125118
}
126-
}
127-
}
128-
129-
func (c *echServerConfig) reloadKeyPair() error {
130-
if c.certificatePath != "" {
131-
certificate, err := os.ReadFile(c.certificatePath)
119+
keyPair, err := cftls.X509KeyPair(c.certificate, c.key)
132120
if err != nil {
133-
return E.Cause(err, "reload certificate from ", c.certificatePath)
121+
return E.Cause(err, "parse key pair")
134122
}
135-
c.certificate = certificate
136-
}
137-
if c.keyPath != "" {
138-
key, err := os.ReadFile(c.keyPath)
123+
c.config.Certificates = []cftls.Certificate{keyPair}
124+
c.logger.Info("reloaded TLS certificate")
125+
} else {
126+
echKeyContent, err := os.ReadFile(c.echKeyPath)
139127
if err != nil {
140-
return E.Cause(err, "reload key from ", c.keyPath)
128+
return err
141129
}
142-
c.key = key
143-
}
144-
keyPair, err := cftls.X509KeyPair(c.certificate, c.key)
145-
if err != nil {
146-
return E.Cause(err, "reload key pair")
147-
}
148-
c.config.Certificates = []cftls.Certificate{keyPair}
149-
c.logger.Info("reloaded TLS certificate")
150-
return nil
151-
}
152-
153-
func (c *echServerConfig) startECHWatcher() error {
154-
watcher, err := fsnotify.NewWatcher()
155-
if err != nil {
156-
return err
157-
}
158-
err = watcher.Add(c.echKeyPath)
159-
if err != nil {
160-
return err
161-
}
162-
c.echWatcher = watcher
163-
go c.loopECHUpdate()
164-
return nil
165-
}
166-
167-
func (c *echServerConfig) loopECHUpdate() {
168-
for {
169-
select {
170-
case event, ok := <-c.echWatcher.Events:
171-
if !ok {
172-
return
173-
}
174-
if event.Op&fsnotify.Write != fsnotify.Write {
175-
continue
176-
}
177-
err := c.reloadECHKey()
178-
if err != nil {
179-
c.logger.Error(E.Cause(err, "reload ECH key"))
180-
}
181-
case err, ok := <-c.echWatcher.Errors:
182-
if !ok {
183-
return
184-
}
185-
c.logger.Error(E.Cause(err, "fsnotify error"))
130+
block, rest := pem.Decode(echKeyContent)
131+
if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 {
132+
return E.New("invalid ECH keys pem")
186133
}
134+
echKeys, err := cftls.EXP_UnmarshalECHKeys(block.Bytes)
135+
if err != nil {
136+
return E.Cause(err, "parse ECH keys")
137+
}
138+
echKeySet, err := cftls.EXP_NewECHKeySet(echKeys)
139+
if err != nil {
140+
return E.Cause(err, "create ECH key set")
141+
}
142+
c.config.ServerECHProvider = echKeySet
143+
c.logger.Info("reloaded ECH keys")
187144
}
188-
}
189-
190-
func (c *echServerConfig) reloadECHKey() error {
191-
echKeyContent, err := os.ReadFile(c.echKeyPath)
192-
if err != nil {
193-
return err
194-
}
195-
block, rest := pem.Decode(echKeyContent)
196-
if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 {
197-
return E.New("invalid ECH keys pem")
198-
}
199-
echKeys, err := cftls.EXP_UnmarshalECHKeys(block.Bytes)
200-
if err != nil {
201-
return E.Cause(err, "parse ECH keys")
202-
}
203-
echKeySet, err := cftls.EXP_NewECHKeySet(echKeys)
204-
if err != nil {
205-
return E.Cause(err, "create ECH key set")
206-
}
207-
c.config.ServerECHProvider = echKeySet
208-
c.logger.Info("reloaded ECH keys")
209145
return nil
210146
}
211147

212148
func (c *echServerConfig) Close() error {
213149
var err error
214150
if c.watcher != nil {
215151
err = E.Append(err, c.watcher.Close(), func(err error) error {
216-
return E.Cause(err, "close certificate watcher")
217-
})
218-
}
219-
if c.echWatcher != nil {
220-
err = E.Append(err, c.echWatcher.Close(), func(err error) error {
221-
return E.Cause(err, "close ECH key watcher")
152+
return E.Cause(err, "close credentials watcher")
222153
})
223154
}
224155
return err

common/tls/std_server.go

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ import (
77
"os"
88
"strings"
99

10+
"github.com/sagernet/fswatch"
1011
"github.com/sagernet/sing-box/adapter"
1112
"github.com/sagernet/sing-box/log"
1213
"github.com/sagernet/sing-box/option"
1314
"github.com/sagernet/sing/common"
1415
E "github.com/sagernet/sing/common/exceptions"
1516
"github.com/sagernet/sing/common/ntp"
16-
17-
"github.com/fsnotify/fsnotify"
1817
)
1918

2019
var errInsecureUnused = E.New("tls: insecure unused")
@@ -27,7 +26,7 @@ type STDServerConfig struct {
2726
key []byte
2827
certificatePath string
2928
keyPath string
30-
watcher *fsnotify.Watcher
29+
watcher *fswatch.Watcher
3130
}
3231

3332
func (c *STDServerConfig) ServerName() string {
@@ -88,59 +87,37 @@ func (c *STDServerConfig) Start() error {
8887
}
8988

9089
func (c *STDServerConfig) startWatcher() error {
91-
watcher, err := fsnotify.NewWatcher()
92-
if err != nil {
93-
return err
94-
}
90+
var watchPath []string
9591
if c.certificatePath != "" {
96-
err = watcher.Add(c.certificatePath)
97-
if err != nil {
98-
return err
99-
}
92+
watchPath = append(watchPath, c.certificatePath)
10093
}
10194
if c.keyPath != "" {
102-
err = watcher.Add(c.keyPath)
103-
if err != nil {
104-
return err
105-
}
95+
watchPath = append(watchPath, c.keyPath)
10696
}
107-
c.watcher = watcher
108-
go c.loopUpdate()
109-
return nil
110-
}
111-
112-
func (c *STDServerConfig) loopUpdate() {
113-
for {
114-
select {
115-
case event, ok := <-c.watcher.Events:
116-
if !ok {
117-
return
118-
}
119-
if event.Op&fsnotify.Write != fsnotify.Write {
120-
continue
121-
}
122-
err := c.reloadKeyPair()
97+
watcher, err := fswatch.NewWatcher(fswatch.Options{
98+
Path: watchPath,
99+
Callback: func(path string) {
100+
err := c.certificateUpdated(path)
123101
if err != nil {
124-
c.logger.Error(E.Cause(err, "reload TLS key pair"))
125-
}
126-
case err, ok := <-c.watcher.Errors:
127-
if !ok {
128-
return
102+
c.logger.Error(err)
129103
}
130-
c.logger.Error(E.Cause(err, "fsnotify error"))
131-
}
104+
},
105+
})
106+
if err != nil {
107+
return err
132108
}
109+
c.watcher = watcher
110+
return nil
133111
}
134112

135-
func (c *STDServerConfig) reloadKeyPair() error {
136-
if c.certificatePath != "" {
113+
func (c *STDServerConfig) certificateUpdated(path string) error {
114+
if path == c.certificatePath {
137115
certificate, err := os.ReadFile(c.certificatePath)
138116
if err != nil {
139117
return E.Cause(err, "reload certificate from ", c.certificatePath)
140118
}
141119
c.certificate = certificate
142-
}
143-
if c.keyPath != "" {
120+
} else if path == c.keyPath {
144121
key, err := os.ReadFile(c.keyPath)
145122
if err != nil {
146123
return E.Cause(err, "reload key from ", c.keyPath)

constant/rule.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const (
1111
)
1212

1313
const (
14+
RuleSetTypeInline = "inline"
1415
RuleSetTypeLocal = "local"
1516
RuleSetTypeRemote = "remote"
1617
RuleSetVersion1 = 1

0 commit comments

Comments
 (0)