Add protect path dialer option

This commit is contained in:
世界 2022-07-06 14:45:56 +08:00
parent dcd7ca78fc
commit 46f28a9de9
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
4 changed files with 61 additions and 0 deletions

View file

@ -67,6 +67,7 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
type DialerOptions struct {
Detour string `json:"detour,omitempty"`
BindInterface string `json:"bind_interface,omitempty"`
ProtectPath string `json:"protect_path,omitempty"`
RoutingMark int `json:"routing_mark,omitempty"`
ReuseAddr bool `json:"reuse_addr,omitempty"`
ConnectTimeout int `json:"connect_timeout,omitempty"`

View file

@ -32,6 +32,10 @@ func newDefault(options option.DialerOptions) N.Dialer {
if options.ReuseAddr {
listener.Control = control.Append(listener.Control, control.ReuseAddr())
}
if options.ProtectPath != "" {
dialer.Control = control.Append(dialer.Control, ProtectPath(options.ProtectPath))
listener.Control = control.Append(listener.Control, ProtectPath(options.ProtectPath))
}
if options.ConnectTimeout != 0 {
dialer.Timeout = time.Duration(options.ConnectTimeout) * time.Second
}

View file

@ -0,0 +1,47 @@
//go:build android || with_protect
package dialer
import (
"syscall"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
)
func sendAncillaryFileDescriptors(protectPath string, fileDescriptors []int) error {
socket, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
if err != nil {
return E.Cause(err, "open protect socket")
}
defer syscall.Close(socket)
err = syscall.Connect(socket, &syscall.SockaddrUnix{Name: protectPath})
if err != nil {
return E.Cause(err, "connect protect path")
}
oob := syscall.UnixRights(fileDescriptors...)
dummy := []byte{1}
err = syscall.Sendmsg(socket, dummy, oob, nil, 0)
if err != nil {
return err
}
n, err := syscall.Read(socket, dummy)
if err != nil {
return err
}
if n != 1 {
return E.New("failed to protect fd")
}
return nil
}
func ProtectPath(protectPath string) control.Func {
return func(network, address string, conn syscall.RawConn) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = sendAncillaryFileDescriptors(protectPath, []int{int(fd)})
})
return common.AnyError(innerErr, err)
}
}

View file

@ -0,0 +1,9 @@
//go:build !android && !with_protect
package dialer
import "github.com/sagernet/sing/common/control"
func ProtectPath(protectPath string) control.Func {
return nil
}