Skip to content

Commit f28076a

Browse files
committed
tun: Set address sets to routes
1 parent ed70a93 commit f28076a

File tree

8 files changed

+131
-62
lines changed

8 files changed

+131
-62
lines changed

experimental/libbox/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ func (s *platformInterfaceStub) OpenTun(options *tun.Options, platformOptions op
6666
return nil, os.ErrInvalid
6767
}
6868

69+
func (s *platformInterfaceStub) UpdateRouteOptions(options *tun.Options, platformInterface option.TunPlatformOptions) error {
70+
return os.ErrInvalid
71+
}
72+
6973
func (s *platformInterfaceStub) UsePlatformDefaultInterfaceMonitor() bool {
7074
return true
7175
}

experimental/libbox/platform.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type PlatformInterface interface {
99
UsePlatformAutoDetectInterfaceControl() bool
1010
AutoDetectInterfaceControl(fd int32) error
1111
OpenTun(options TunOptions) (int32, error)
12+
UpdateRouteOptions(options TunOptions) error
1213
WriteLog(message string)
1314
UseProcFS() bool
1415
FindConnectionOwner(ipProtocol int32, sourceAddress string, sourcePort int32, destinationAddress string, destinationPort int32) (int32, error)

experimental/libbox/platform/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type Interface interface {
1313
UsePlatformAutoDetectInterfaceControl() bool
1414
AutoDetectInterfaceControl(fd int) error
1515
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
16+
UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error
1617
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
1718
Interfaces() ([]adapter.NetworkInterface, error)
1819
SetUnderlyingNetworks(networks []adapter.NetworkInterface) error

experimental/libbox/service.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,10 @@ func (w *platformInterfaceWrapper) AutoDetectInterfaceControl(fd int) error {
148148

149149
func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
150150
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
151-
return nil, E.New("android: unsupported uid options")
151+
return nil, E.New("platform: unsupported uid options")
152152
}
153153
if len(options.IncludeAndroidUser) > 0 {
154-
return nil, E.New("android: unsupported android_user option")
154+
return nil, E.New("platform: unsupported android_user option")
155155
}
156156
routeRanges, err := options.BuildAutoRouteRanges(true)
157157
if err != nil {
@@ -174,6 +174,20 @@ func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions
174174
return tun.New(*options)
175175
}
176176

177+
func (w *platformInterfaceWrapper) UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error {
178+
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
179+
return E.New("android: unsupported uid options")
180+
}
181+
if len(options.IncludeAndroidUser) > 0 {
182+
return E.New("android: unsupported android_user option")
183+
}
184+
routeRanges, err := options.BuildAutoRouteRanges(true)
185+
if err != nil {
186+
return err
187+
}
188+
return w.iif.UpdateRouteOptions(&tunOptions{options, routeRanges, platformOptions})
189+
}
190+
177191
func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor {
178192
return &platformDefaultInterfaceMonitor{
179193
platformInterfaceWrapper: w,

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ require (
3333
github.com/sagernet/sing-shadowsocks v0.2.7
3434
github.com/sagernet/sing-shadowsocks2 v0.2.0
3535
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2
36-
github.com/sagernet/sing-tun v0.6.0-beta.6
36+
github.com/sagernet/sing-tun v0.6.0-beta.6.0.20241223141727-f4579880903f
3737
github.com/sagernet/sing-vmess v0.2.0-beta.1
3838
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
3939
github.com/sagernet/utls v1.6.7

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
133133
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
134134
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0=
135135
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA=
136-
github.com/sagernet/sing-tun v0.6.0-beta.6 h1:xaIHoH78MqTSvZqQ4SQto8pC1A+X4qXReDRNaC8DQeI=
137-
github.com/sagernet/sing-tun v0.6.0-beta.6/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
136+
github.com/sagernet/sing-tun v0.6.0-beta.6.0.20241223141727-f4579880903f h1:QT/ZpJ+6nek1DwR8kKHu/DXuS89w4gLHFYyw4zLSZnM=
137+
github.com/sagernet/sing-tun v0.6.0-beta.6.0.20241223141727-f4579880903f/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
138138
github.com/sagernet/sing-vmess v0.2.0-beta.1 h1:5sXQ23uwNlZuDvygzi0dFtnG0Csm/SNqTjAHXJkpuj4=
139139
github.com/sagernet/sing-vmess v0.2.0-beta.1/go.mod h1:fLyE1emIcvQ5DV8reFWnufquZ7MkCSYM5ThodsR9NrQ=
140140
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=

protocol/tun/inbound.go

Lines changed: 105 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,22 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
209209
platformInterface: service.FromContext[platform.Interface](ctx),
210210
platformOptions: common.PtrValueOrDefault(options.Platform),
211211
}
212+
for _, routeAddressSet := range options.RouteAddressSet {
213+
ruleSet, loaded := router.RuleSet(routeAddressSet)
214+
if !loaded {
215+
return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet)
216+
}
217+
ruleSet.IncRef()
218+
inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet)
219+
}
220+
for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet {
221+
ruleSet, loaded := router.RuleSet(routeExcludeAddressSet)
222+
if !loaded {
223+
return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet)
224+
}
225+
ruleSet.IncRef()
226+
inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet)
227+
}
212228
if options.AutoRedirect {
213229
if !options.AutoRoute {
214230
return nil, E.New("`auto_route` is required by `auto_redirect`")
@@ -229,32 +245,11 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
229245
if err != nil {
230246
return nil, E.Cause(err, "initialize auto-redirect")
231247
}
232-
if runtime.GOOS != "android" {
233-
var markMode bool
234-
for _, routeAddressSet := range options.RouteAddressSet {
235-
ruleSet, loaded := router.RuleSet(routeAddressSet)
236-
if !loaded {
237-
return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet)
238-
}
239-
ruleSet.IncRef()
240-
inbound.routeRuleSet = append(inbound.routeRuleSet, ruleSet)
241-
markMode = true
242-
}
243-
for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet {
244-
ruleSet, loaded := router.RuleSet(routeExcludeAddressSet)
245-
if !loaded {
246-
return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet)
247-
}
248-
ruleSet.IncRef()
249-
inbound.routeExcludeRuleSet = append(inbound.routeExcludeRuleSet, ruleSet)
250-
markMode = true
251-
}
252-
if markMode {
253-
inbound.tunOptions.AutoRedirectMarkMode = true
254-
err = networkManager.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
255-
if err != nil {
256-
return nil, err
257-
}
248+
if runtime.GOOS != "android" && len(inbound.routeAddressSet) > 0 || len(inbound.routeExcludeAddressSet) > 0 {
249+
inbound.tunOptions.AutoRedirectMarkMode = true
250+
err = networkManager.RegisterAutoRedirectOutputMark(inbound.tunOptions.AutoRedirectOutputMark)
251+
if err != nil {
252+
return nil, err
258253
}
259254
}
260255
}
@@ -310,18 +305,62 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
310305
if t.tunOptions.Name == "" {
311306
t.tunOptions.Name = tun.CalculateInterfaceName("")
312307
}
308+
if t.platformInterface == nil || runtime.GOOS != "android" {
309+
t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
310+
for _, routeRuleSet := range t.routeRuleSet {
311+
ipSets := routeRuleSet.ExtractIPSet()
312+
if len(ipSets) == 0 {
313+
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name())
314+
}
315+
t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet))
316+
routeRuleSet.DecRef()
317+
t.routeAddressSet = append(t.routeAddressSet, ipSets...)
318+
}
319+
t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
320+
for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
321+
ipSets := routeExcludeRuleSet.ExtractIPSet()
322+
if len(ipSets) == 0 {
323+
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name())
324+
}
325+
t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
326+
routeExcludeRuleSet.DecRef()
327+
t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...)
328+
}
329+
}
313330
var (
314331
tunInterface tun.Tun
315332
err error
316333
)
317334
monitor := taskmonitor.New(t.logger, C.StartTimeout)
318-
monitor.Start("open tun interface")
335+
tunOptions := t.tunOptions
336+
if t.autoRedirect == nil && !(runtime.GOOS == "android" && t.platformInterface != nil) {
337+
for _, ipSet := range t.routeAddressSet {
338+
for _, prefix := range ipSet.Prefixes() {
339+
if prefix.Addr().Is4() {
340+
tunOptions.Inet4RouteAddress = append(tunOptions.Inet4RouteAddress, prefix)
341+
} else {
342+
tunOptions.Inet6RouteAddress = append(tunOptions.Inet6RouteAddress, prefix)
343+
}
344+
}
345+
}
346+
for _, ipSet := range t.routeExcludeAddressSet {
347+
for _, prefix := range ipSet.Prefixes() {
348+
if prefix.Addr().Is4() {
349+
tunOptions.Inet4RouteExcludeAddress = append(tunOptions.Inet4RouteExcludeAddress, prefix)
350+
} else {
351+
tunOptions.Inet6RouteExcludeAddress = append(tunOptions.Inet6RouteExcludeAddress, prefix)
352+
}
353+
}
354+
}
355+
}
356+
monitor.Start("open interface")
319357
if t.platformInterface != nil {
320-
tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)
358+
tunInterface, err = t.platformInterface.OpenTun(&tunOptions, t.platformOptions)
321359
} else {
322-
tunInterface, err = tun.New(t.tunOptions)
360+
tunInterface, err = tun.New(tunOptions)
323361
}
324362
monitor.Finish()
363+
t.tunOptions.Name = tunOptions.Name
325364
if err != nil {
326365
return E.Cause(err, "configure tun interface")
327366
}
@@ -366,47 +405,57 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
366405
return E.Cause(err, "starting TUN interface")
367406
}
368407
if t.autoRedirect != nil {
369-
t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
370-
for _, routeRuleSet := range t.routeRuleSet {
371-
ipSets := routeRuleSet.ExtractIPSet()
372-
if len(ipSets) == 0 {
373-
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name())
374-
}
375-
t.routeAddressSet = append(t.routeAddressSet, ipSets...)
376-
}
377-
t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
378-
for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
379-
ipSets := routeExcludeRuleSet.ExtractIPSet()
380-
if len(ipSets) == 0 {
381-
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name())
382-
}
383-
t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...)
384-
}
385408
monitor.Start("initialize auto-redirect")
386409
err := t.autoRedirect.Start()
387410
monitor.Finish()
388411
if err != nil {
389412
return E.Cause(err, "auto-redirect")
390413
}
391-
for _, routeRuleSet := range t.routeRuleSet {
392-
t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet))
393-
routeRuleSet.DecRef()
394-
}
395-
for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
396-
t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
397-
routeExcludeRuleSet.DecRef()
398-
}
399-
t.routeAddressSet = nil
400-
t.routeExcludeAddressSet = nil
401414
}
415+
t.routeAddressSet = nil
416+
t.routeExcludeAddressSet = nil
402417
}
403418
return nil
404419
}
405420

406421
func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) {
407422
t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
408423
t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
409-
t.autoRedirect.UpdateRouteAddressSet()
424+
if t.autoRedirect != nil {
425+
t.autoRedirect.UpdateRouteAddressSet()
426+
} else {
427+
tunOptions := t.tunOptions
428+
for _, ipSet := range t.routeAddressSet {
429+
for _, prefix := range ipSet.Prefixes() {
430+
if prefix.Addr().Is4() {
431+
tunOptions.Inet4RouteAddress = append(tunOptions.Inet4RouteAddress, prefix)
432+
} else {
433+
tunOptions.Inet6RouteAddress = append(tunOptions.Inet6RouteAddress, prefix)
434+
}
435+
}
436+
}
437+
for _, ipSet := range t.routeExcludeAddressSet {
438+
for _, prefix := range ipSet.Prefixes() {
439+
if prefix.Addr().Is4() {
440+
tunOptions.Inet4RouteExcludeAddress = append(tunOptions.Inet4RouteExcludeAddress, prefix)
441+
} else {
442+
tunOptions.Inet6RouteExcludeAddress = append(tunOptions.Inet6RouteExcludeAddress, prefix)
443+
}
444+
}
445+
}
446+
if t.platformInterface != nil {
447+
err := t.platformInterface.UpdateRouteOptions(&tunOptions, t.platformOptions)
448+
if err != nil {
449+
t.logger.Error("update route addresses: ", err)
450+
}
451+
} else {
452+
err := t.tunIf.UpdateRouteOptions(tunOptions)
453+
if err != nil {
454+
t.logger.Error("update route addresses: ", err)
455+
}
456+
}
457+
t.logger.Info("updated route addresses")
458+
}
410459
t.routeAddressSet = nil
411460
t.routeExcludeAddressSet = nil
412461
}

route/router.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,6 @@ func (r *Router) Start(stage adapter.StartStage) error {
363363
return E.Cause(err, "initialize DNS server[", i, "]")
364364
}
365365
}
366-
case adapter.StartStatePostStart:
367366
var cacheContext *adapter.HTTPStartContext
368367
if len(r.ruleSets) > 0 {
369368
monitor.Start("initialize rule-set")
@@ -419,6 +418,7 @@ func (r *Router) Start(stage adapter.StartStage) error {
419418
}
420419
}
421420
}
421+
case adapter.StartStatePostStart:
422422
for i, rule := range r.rules {
423423
monitor.Start("initialize rule[", i, "]")
424424
err := rule.Start()

0 commit comments

Comments
 (0)