mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-05 12:57:38 +03:00
Improve interface finder
This commit is contained in:
parent
2fa039945c
commit
eec2fc325a
5 changed files with 119 additions and 24 deletions
|
@ -1,30 +1,18 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
type InterfaceFinder interface {
|
type InterfaceFinder interface {
|
||||||
InterfaceIndexByName(name string) (int, error)
|
InterfaceIndexByName(name string) (int, error)
|
||||||
InterfaceNameByIndex(index int) (string, error)
|
InterfaceNameByIndex(index int) (string, error)
|
||||||
|
InterfaceByAddr(addr netip.Addr) (*Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultInterfaceFinder() InterfaceFinder {
|
type Interface struct {
|
||||||
return (*netInterfaceFinder)(nil)
|
Index int
|
||||||
}
|
MTU int
|
||||||
|
Name string
|
||||||
type netInterfaceFinder struct{}
|
Addresses []netip.Prefix
|
||||||
|
|
||||||
func (w *netInterfaceFinder) InterfaceIndexByName(name string) (int, error) {
|
|
||||||
netInterface, err := net.InterfaceByName(name)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return netInterface.Index, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *netInterfaceFinder) InterfaceNameByIndex(index int) (string, error) {
|
|
||||||
netInterface, err := net.InterfaceByIndex(index)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return netInterface.Name, nil
|
|
||||||
}
|
}
|
||||||
|
|
97
common/control/bind_finder_default.go
Normal file
97
common/control/bind_finder_default.go
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DefaultInterfaceFinder struct {
|
||||||
|
interfaces []Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultInterfaceFinder() *DefaultInterfaceFinder {
|
||||||
|
return &DefaultInterfaceFinder{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DefaultInterfaceFinder) Update() error {
|
||||||
|
netIfs, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
interfaces := make([]Interface, 0, len(netIfs))
|
||||||
|
for _, netIf := range netIfs {
|
||||||
|
ifAddrs, err := netIf.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
interfaces = append(interfaces, Interface{
|
||||||
|
Index: netIf.Index,
|
||||||
|
MTU: netIf.MTU,
|
||||||
|
Name: netIf.Name,
|
||||||
|
Addresses: common.Map(ifAddrs, M.PrefixFromNet),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
f.interfaces = interfaces
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DefaultInterfaceFinder) UpdateInterfaces(interfaces []Interface) {
|
||||||
|
f.interfaces = interfaces
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DefaultInterfaceFinder) InterfaceIndexByName(name string) (int, error) {
|
||||||
|
for _, netInterface := range f.interfaces {
|
||||||
|
if netInterface.Name == name {
|
||||||
|
return netInterface.Index, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netInterface, err := net.InterfaceByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
f.Update()
|
||||||
|
return netInterface.Index, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DefaultInterfaceFinder) InterfaceNameByIndex(index int) (string, error) {
|
||||||
|
for _, netInterface := range f.interfaces {
|
||||||
|
if netInterface.Index == index {
|
||||||
|
return netInterface.Name, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netInterface, err := net.InterfaceByIndex(index)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
f.Update()
|
||||||
|
return netInterface.Name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname errNoSuchInterface net.errNoSuchInterface
|
||||||
|
var errNoSuchInterface error
|
||||||
|
|
||||||
|
func (f *DefaultInterfaceFinder) InterfaceByAddr(addr netip.Addr) (*Interface, error) {
|
||||||
|
for _, netInterface := range f.interfaces {
|
||||||
|
for _, prefix := range netInterface.Addresses {
|
||||||
|
if prefix.Contains(addr) {
|
||||||
|
return &netInterface, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := f.Update()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, netInterface := range f.interfaces {
|
||||||
|
for _, prefix := range netInterface.Addresses {
|
||||||
|
if prefix.Contains(addr) {
|
||||||
|
return &netInterface, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: &net.IPAddr{IP: addr.AsSlice()}, Err: errNoSuchInterface}
|
||||||
|
}
|
|
@ -141,7 +141,7 @@ func SocksaddrFromNet(ap net.Addr) Socksaddr {
|
||||||
return ParseSocksaddr(ap.String())
|
return ParseSocksaddr(ap.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddrFromNetAddr(netAddr net.Addr) netip.Addr {
|
func AddrFromNet(netAddr net.Addr) netip.Addr {
|
||||||
if addr := AddrPortFromNet(netAddr); addr.Addr().IsValid() {
|
if addr := AddrPortFromNet(netAddr); addr.Addr().IsValid() {
|
||||||
return addr.Addr()
|
return addr.Addr()
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,16 @@ func AddrFromNetAddr(netAddr net.Addr) netip.Addr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PrefixFromNet(netAddr net.Addr) netip.Prefix {
|
||||||
|
switch addr := netAddr.(type) {
|
||||||
|
case *net.IPNet:
|
||||||
|
bits, _ := addr.Mask.Size()
|
||||||
|
return netip.PrefixFrom(AddrFromIP(addr.IP), bits)
|
||||||
|
default:
|
||||||
|
return netip.Prefix{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func AddrPortFromNet(netAddr net.Addr) netip.AddrPort {
|
func AddrPortFromNet(netAddr net.Addr) netip.AddrPort {
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
var port uint16
|
var port uint16
|
||||||
|
|
|
@ -13,7 +13,7 @@ func LocalAddrs() ([]netip.Addr, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return common.Map(interfaceAddrs, M.AddrFromNetAddr), nil
|
return common.Map(interfaceAddrs, M.AddrFromNet), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsPublicAddr(addr netip.Addr) bool {
|
func IsPublicAddr(addr netip.Addr) bool {
|
||||||
|
|
|
@ -203,7 +203,7 @@ func HandleConnection0(ctx context.Context, conn net.Conn, version byte, authent
|
||||||
return handler.NewConnection(ctx, conn, metadata)
|
return handler.NewConnection(ctx, conn, metadata)
|
||||||
case socks5.CommandUDPAssociate:
|
case socks5.CommandUDPAssociate:
|
||||||
var udpConn *net.UDPConn
|
var udpConn *net.UDPConn
|
||||||
udpConn, err = net.ListenUDP(M.NetworkFromNetAddr("udp", M.AddrFromNetAddr(conn.LocalAddr())), net.UDPAddrFromAddrPort(netip.AddrPortFrom(M.AddrFromNetAddr(conn.LocalAddr()), 0)))
|
udpConn, err = net.ListenUDP(M.NetworkFromNetAddr("udp", M.AddrFromNet(conn.LocalAddr())), net.UDPAddrFromAddrPort(netip.AddrPortFrom(M.AddrFromNet(conn.LocalAddr()), 0)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue