Add android package rules support in tun routing

This commit is contained in:
世界
2022-08-15 11:40:49 +08:00
parent 3157593b6b
commit cd5e7055d2
16 changed files with 100 additions and 188 deletions

View File

@@ -4,6 +4,8 @@ import (
"context"
"net/netip"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-tun"
E "github.com/sagernet/sing/common/exceptions"
)
@@ -13,6 +15,11 @@ type Searcher interface {
var ErrNotFound = E.New("process not found")
type Config struct {
Logger log.ContextLogger
PackageManager tun.PackageManager
}
type Info struct {
ProcessPath string
PackageName string

View File

@@ -2,81 +2,19 @@ package process
import (
"context"
"encoding/xml"
"io"
"net/netip"
"os"
"strconv"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/fsnotify/fsnotify"
tun "github.com/sagernet/sing-tun"
)
var _ Searcher = (*androidSearcher)(nil)
type androidSearcher struct {
logger log.ContextLogger
watcher *fsnotify.Watcher
userMap map[string]int32
packageMap map[int32]string
sharedUserMap map[int32]string
packageManager tun.PackageManager
}
func NewSearcher(logger log.ContextLogger) (Searcher, error) {
return &androidSearcher{logger: logger}, nil
}
func (s *androidSearcher) Start() error {
err := s.updatePackages()
if err != nil {
return E.Cause(err, "read packages list")
}
err = s.startWatcher()
if err != nil {
s.logger.Warn("create fsnotify watcher: ", err)
}
return nil
}
func (s *androidSearcher) startWatcher() error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
err = watcher.Add("/data/system/packages.xml")
if err != nil {
return err
}
s.watcher = watcher
go s.loopUpdate()
return nil
}
func (s *androidSearcher) loopUpdate() {
for {
select {
case _, ok := <-s.watcher.Events:
if !ok {
return
}
err := s.updatePackages()
if err != nil {
s.logger.Error(E.Cause(err, "update packages list"))
}
case err, ok := <-s.watcher.Errors:
if !ok {
return
}
s.logger.Error(E.Cause(err, "fsnotify error"))
}
}
}
func (s *androidSearcher) Close() error {
return common.Close(common.PtrOrNil(s.watcher))
func NewSearcher(config Config) (Searcher, error) {
return &androidSearcher{config.PackageManager}, nil
}
func (s *androidSearcher) FindProcessInfo(ctx context.Context, network string, srcIP netip.Addr, srcPort int) (*Info, error) {
@@ -84,13 +22,13 @@ func (s *androidSearcher) FindProcessInfo(ctx context.Context, network string, s
if err != nil {
return nil, err
}
if sharedUser, loaded := s.sharedUserMap[uid]; loaded {
if sharedPackage, loaded := s.packageManager.SharedPackageByID(uint32(uid)); loaded {
return &Info{
UserId: uid,
PackageName: sharedUser,
PackageName: sharedPackage,
}, nil
}
if packageName, loaded := s.packageMap[uid]; loaded {
if packageName, loaded := s.packageManager.PackageByID(uint32(uid)); loaded {
return &Info{
UserId: uid,
PackageName: packageName,
@@ -98,74 +36,3 @@ func (s *androidSearcher) FindProcessInfo(ctx context.Context, network string, s
}
return &Info{UserId: uid}, nil
}
func (s *androidSearcher) updatePackages() error {
userMap := make(map[string]int32)
packageMap := make(map[int32]string)
sharedUserMap := make(map[int32]string)
packagesData, err := os.Open("/data/system/packages.xml")
if err != nil {
return err
}
decoder := xml.NewDecoder(packagesData)
var token xml.Token
for {
token, err = decoder.Token()
if err == io.EOF {
break
} else if err != nil {
return err
}
element, isStart := token.(xml.StartElement)
if !isStart {
continue
}
switch element.Name.Local {
case "package":
var name string
var userID int64
for _, attr := range element.Attr {
switch attr.Name.Local {
case "name":
name = attr.Value
case "userId", "sharedUserId":
userID, err = strconv.ParseInt(attr.Value, 10, 32)
if err != nil {
return err
}
}
}
if userID == 0 && name == "" {
continue
}
userMap[name] = int32(userID)
packageMap[int32(userID)] = name
case "shared-user":
var name string
var userID int64
for _, attr := range element.Attr {
switch attr.Name.Local {
case "name":
name = attr.Value
case "userId":
userID, err = strconv.ParseInt(attr.Value, 10, 32)
if err != nil {
return err
}
packageMap[int32(userID)] = name
}
}
if userID == 0 && name == "" {
continue
}
sharedUserMap[int32(userID)] = name
}
}
s.logger.Info("updated packages list: ", len(packageMap), " packages, ", len(sharedUserMap), " shared users")
s.userMap = userMap
s.packageMap = packageMap
s.sharedUserMap = sharedUserMap
return nil
}

View File

@@ -8,7 +8,6 @@ import (
"syscall"
"unsafe"
"github.com/sagernet/sing-box/log"
N "github.com/sagernet/sing/common/network"
"golang.org/x/sys/unix"
@@ -18,7 +17,7 @@ var _ Searcher = (*darwinSearcher)(nil)
type darwinSearcher struct{}
func NewSearcher(logger log.ContextLogger) (Searcher, error) {
func NewSearcher(_ Config) (Searcher, error) {
return &darwinSearcher{}, nil
}

View File

@@ -15,8 +15,8 @@ type linuxSearcher struct {
logger log.ContextLogger
}
func NewSearcher(logger log.ContextLogger) (Searcher, error) {
return &linuxSearcher{logger}, nil
func NewSearcher(config Config) (Searcher, error) {
return &linuxSearcher{config.Logger}, nil
}
func (s *linuxSearcher) FindProcessInfo(ctx context.Context, network string, srcIP netip.Addr, srcPort int) (*Info, error) {

View File

@@ -4,10 +4,8 @@ package process
import (
"os"
"github.com/sagernet/sing-box/log"
)
func NewSearcher(logger log.ContextLogger) (Searcher, error) {
func NewSearcher(_ Config) (Searcher, error) {
return nil, os.ErrInvalid
}

View File

@@ -8,7 +8,6 @@ import (
"syscall"
"unsafe"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
N "github.com/sagernet/sing/common/network"
@@ -19,7 +18,7 @@ var _ Searcher = (*windowsSearcher)(nil)
type windowsSearcher struct{}
func NewSearcher(logger log.ContextLogger) (Searcher, error) {
func NewSearcher(_ Config) (Searcher, error) {
err := initWin32API()
if err != nil {
return nil, E.Cause(err, "init win32 api")