mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 00:21:30 +00:00
Add wifi_ssid
and wifi_bssid
route and DNS rules
This commit is contained in:
parent
f0571b4122
commit
253976d6c0
|
@ -41,6 +41,7 @@ type Router interface {
|
|||
NetworkMonitor() tun.NetworkUpdateMonitor
|
||||
InterfaceMonitor() tun.DefaultInterfaceMonitor
|
||||
PackageManager() tun.PackageManager
|
||||
WIFIState() WIFIState
|
||||
Rules() []Rule
|
||||
|
||||
ClashServer() ClashServer
|
||||
|
@ -78,3 +79,8 @@ type DNSRule interface {
|
|||
type InterfaceUpdateListener interface {
|
||||
InterfaceUpdated()
|
||||
}
|
||||
|
||||
type WIFIState struct {
|
||||
SSID string
|
||||
BSSID string
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ type PlatformInterface interface {
|
|||
UsePlatformInterfaceGetter() bool
|
||||
GetInterfaces() (NetworkInterfaceIterator, error)
|
||||
UnderNetworkExtension() bool
|
||||
ReadWIFIState() *WIFIState
|
||||
ClearDNSCache()
|
||||
}
|
||||
|
||||
|
@ -38,6 +39,15 @@ type NetworkInterface struct {
|
|||
Addresses StringIterator
|
||||
}
|
||||
|
||||
type WIFIState struct {
|
||||
SSID string
|
||||
BSSID string
|
||||
}
|
||||
|
||||
func NewWIFIState(wifiSSID string, wifiBSSID string) *WIFIState {
|
||||
return &WIFIState{wifiSSID, wifiBSSID}
|
||||
}
|
||||
|
||||
type NetworkInterfaceIterator interface {
|
||||
Next() *NetworkInterface
|
||||
HasNext() bool
|
||||
|
|
|
@ -23,6 +23,7 @@ type Interface interface {
|
|||
Interfaces() ([]NetworkInterface, error)
|
||||
UnderNetworkExtension() bool
|
||||
ClearDNSCache()
|
||||
ReadWIFIState() adapter.WIFIState
|
||||
process.Searcher
|
||||
}
|
||||
|
||||
|
|
|
@ -210,6 +210,14 @@ func (w *platformInterfaceWrapper) ClearDNSCache() {
|
|||
w.iif.ClearDNSCache()
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) ReadWIFIState() adapter.WIFIState {
|
||||
wifiState := w.iif.ReadWIFIState()
|
||||
if wifiState == nil {
|
||||
return adapter.WIFIState{}
|
||||
}
|
||||
return (adapter.WIFIState)(*wifiState)
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) DisableColors() bool {
|
||||
return runtime.GOOS != "android"
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ type DefaultRule struct {
|
|||
User Listable[string] `json:"user,omitempty"`
|
||||
UserID Listable[int32] `json:"user_id,omitempty"`
|
||||
ClashMode string `json:"clash_mode,omitempty"`
|
||||
WIFISSID Listable[string] `json:"wifi_ssid,omitempty"`
|
||||
WIFIBSSID Listable[string] `json:"wifi_bssid,omitempty"`
|
||||
Invert bool `json:"invert,omitempty"`
|
||||
Outbound string `json:"outbound,omitempty"`
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ type DefaultDNSRule struct {
|
|||
UserID Listable[int32] `json:"user_id,omitempty"`
|
||||
Outbound Listable[string] `json:"outbound,omitempty"`
|
||||
ClashMode string `json:"clash_mode,omitempty"`
|
||||
WIFISSID Listable[string] `json:"wifi_ssid,omitempty"`
|
||||
WIFIBSSID Listable[string] `json:"wifi_bssid,omitempty"`
|
||||
Invert bool `json:"invert,omitempty"`
|
||||
Server string `json:"server,omitempty"`
|
||||
DisableCache bool `json:"disable_cache,omitempty"`
|
||||
|
|
|
@ -86,6 +86,8 @@ type Router struct {
|
|||
clashServer adapter.ClashServer
|
||||
v2rayServer adapter.V2RayServer
|
||||
platformInterface platform.Interface
|
||||
needWIFIState bool
|
||||
wifiState adapter.WIFIState
|
||||
}
|
||||
|
||||
func NewRouter(
|
||||
|
@ -116,6 +118,7 @@ func NewRouter(
|
|||
defaultMark: options.DefaultMark,
|
||||
pauseManager: pause.ManagerFromContext(ctx),
|
||||
platformInterface: platformInterface,
|
||||
needWIFIState: hasRule(options.Rules, isWIFIRule) || hasDNSRule(dnsOptions.Rules, isWIFIDNSRule),
|
||||
}
|
||||
router.dnsClient = dns.NewClient(dns.ClientOptions{
|
||||
DisableCache: dnsOptions.DNSClientOptions.DisableCache,
|
||||
|
@ -328,6 +331,11 @@ func NewRouter(
|
|||
service.ContextWith[serviceNTP.TimeService](ctx, timeService)
|
||||
router.timeService = timeService
|
||||
}
|
||||
if platformInterface != nil && router.interfaceMonitor != nil && router.needWIFIState {
|
||||
router.interfaceMonitor.RegisterCallback(func(_ int) {
|
||||
router.updateWIFIState()
|
||||
})
|
||||
}
|
||||
return router, nil
|
||||
}
|
||||
|
||||
|
@ -468,6 +476,9 @@ func (r *Router) Start() error {
|
|||
r.geositeCache = nil
|
||||
r.geositeReader = nil
|
||||
}
|
||||
if r.needWIFIState {
|
||||
r.updateWIFIState()
|
||||
}
|
||||
for i, rule := range r.rules {
|
||||
err := rule.Start()
|
||||
if err != nil {
|
||||
|
@ -940,6 +951,10 @@ func (r *Router) Rules() []adapter.Rule {
|
|||
return r.rules
|
||||
}
|
||||
|
||||
func (r *Router) WIFIState() adapter.WIFIState {
|
||||
return r.wifiState
|
||||
}
|
||||
|
||||
func (r *Router) NetworkMonitor() tun.NetworkUpdateMonitor {
|
||||
return r.networkMonitor
|
||||
}
|
||||
|
@ -1019,3 +1034,14 @@ func (r *Router) ResetNetwork() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Router) updateWIFIState() {
|
||||
if r.platformInterface == nil {
|
||||
return
|
||||
}
|
||||
state := r.platformInterface.ReadWIFIState()
|
||||
if state != r.wifiState {
|
||||
r.wifiState = state
|
||||
r.logger.Info("updated WIFI state: SSID=", state.SSID, ", BSSID=", state.BSSID)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,3 +307,11 @@ func isProcessDNSRule(rule option.DefaultDNSRule) bool {
|
|||
func notPrivateNode(code string) bool {
|
||||
return code != "private"
|
||||
}
|
||||
|
||||
func isWIFIRule(rule option.DefaultRule) bool {
|
||||
return len(rule.WIFISSID) > 0 || len(rule.WIFIBSSID) > 0
|
||||
}
|
||||
|
||||
func isWIFIDNSRule(rule option.DefaultDNSRule) bool {
|
||||
return len(rule.WIFISSID) > 0 || len(rule.WIFIBSSID) > 0
|
||||
}
|
||||
|
|
|
@ -184,6 +184,16 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt
|
|||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.WIFISSID) > 0 {
|
||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.WIFIBSSID) > 0 {
|
||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -180,6 +180,16 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
|
|||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.WIFISSID) > 0 {
|
||||
item := NewWIFISSIDItem(router, options.WIFISSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if len(options.WIFIBSSID) > 0 {
|
||||
item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
|
|
39
route/rule_item_wifi_bssid.go
Normal file
39
route/rule_item_wifi_bssid.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package route
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
var _ RuleItem = (*WIFIBSSIDItem)(nil)
|
||||
|
||||
type WIFIBSSIDItem struct {
|
||||
bssidList []string
|
||||
bssidMap map[string]bool
|
||||
router adapter.Router
|
||||
}
|
||||
|
||||
func NewWIFIBSSIDItem(router adapter.Router, bssidList []string) *WIFIBSSIDItem {
|
||||
bssidMap := make(map[string]bool)
|
||||
for _, bssid := range bssidList {
|
||||
bssidMap[bssid] = true
|
||||
}
|
||||
return &WIFIBSSIDItem{
|
||||
bssidList,
|
||||
bssidMap,
|
||||
router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *WIFIBSSIDItem) Match(metadata *adapter.InboundContext) bool {
|
||||
return r.bssidMap[r.router.WIFIState().BSSID]
|
||||
}
|
||||
|
||||
func (r *WIFIBSSIDItem) String() string {
|
||||
if len(r.bssidList) == 1 {
|
||||
return F.ToString("wifi_bssid=", r.bssidList[0])
|
||||
}
|
||||
return F.ToString("wifi_bssid=[", strings.Join(r.bssidList, " "), "]")
|
||||
}
|
39
route/rule_item_wifi_ssid.go
Normal file
39
route/rule_item_wifi_ssid.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package route
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
var _ RuleItem = (*WIFISSIDItem)(nil)
|
||||
|
||||
type WIFISSIDItem struct {
|
||||
ssidList []string
|
||||
ssidMap map[string]bool
|
||||
router adapter.Router
|
||||
}
|
||||
|
||||
func NewWIFISSIDItem(router adapter.Router, ssidList []string) *WIFISSIDItem {
|
||||
ssidMap := make(map[string]bool)
|
||||
for _, ssid := range ssidList {
|
||||
ssidMap[ssid] = true
|
||||
}
|
||||
return &WIFISSIDItem{
|
||||
ssidList,
|
||||
ssidMap,
|
||||
router,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *WIFISSIDItem) Match(metadata *adapter.InboundContext) bool {
|
||||
return r.ssidMap[r.router.WIFIState().SSID]
|
||||
}
|
||||
|
||||
func (r *WIFISSIDItem) String() string {
|
||||
if len(r.ssidList) == 1 {
|
||||
return F.ToString("wifi_ssid=", r.ssidList[0])
|
||||
}
|
||||
return F.ToString("wifi_ssid=[", strings.Join(r.ssidList, " "), "]")
|
||||
}
|
Loading…
Reference in a new issue