mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-21 23:46:51 +00:00
Fix Linux process search matching the wrong socket
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
//go:build linux
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/sagernet/sing-box/log"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func socketInode(t *testing.T, conn syscall.Conn) uint32 {
|
||||
rawConn, err := conn.SyscallConn()
|
||||
require.NoError(t, err)
|
||||
var inode uint32
|
||||
err = rawConn.Control(func(fd uintptr) {
|
||||
var stat syscall.Stat_t
|
||||
require.NoError(t, syscall.Fstat(int(fd), &stat))
|
||||
inode = uint32(stat.Ino)
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return inode
|
||||
}
|
||||
|
||||
func TestDumpSocketDiagTCP(t *testing.T) {
|
||||
t.Parallel()
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
defer listener.Close()
|
||||
first, err := (&net.Dialer{LocalAddr: &net.TCPAddr{IP: net.IPv4(127, 0, 0, 2)}}).Dial("tcp", listener.Addr().String())
|
||||
require.NoError(t, err)
|
||||
defer first.Close()
|
||||
second, err := (&net.Dialer{LocalAddr: &net.TCPAddr{IP: net.IPv4(127, 0, 0, 3), Port: int(M.AddrPortFromNet(first.LocalAddr()).Port())}}).Dial("tcp", listener.Addr().String())
|
||||
require.NoError(t, err)
|
||||
defer second.Close()
|
||||
destination := M.AddrPortFromNet(listener.Addr())
|
||||
for _, conn := range []net.Conn{second, first} {
|
||||
inode, uid, err := dumpSocketDiag(syscall.AF_INET, syscall.IPPROTO_TCP, M.AddrPortFromNet(conn.LocalAddr()), destination)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, socketInode(t, conn.(syscall.Conn)), inode)
|
||||
require.Equal(t, uint32(os.Getuid()), uid)
|
||||
inode, _, err = dumpSocketDiag(syscall.AF_INET, syscall.IPPROTO_TCP, M.AddrPortFromNet(conn.LocalAddr()), netip.AddrPort{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, socketInode(t, conn.(syscall.Conn)), inode)
|
||||
}
|
||||
_, _, err = dumpSocketDiag(syscall.AF_INET, syscall.IPPROTO_TCP, netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 4}), M.AddrPortFromNet(first.LocalAddr()).Port()), destination)
|
||||
require.ErrorIs(t, err, ErrNotFound)
|
||||
}
|
||||
|
||||
func TestDumpSocketDiagUDP(t *testing.T) {
|
||||
t.Parallel()
|
||||
first, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 2)})
|
||||
require.NoError(t, err)
|
||||
defer first.Close()
|
||||
port := M.AddrPortFromNet(first.LocalAddr()).Port()
|
||||
second, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 3), Port: int(port)})
|
||||
require.NoError(t, err)
|
||||
defer second.Close()
|
||||
for _, conn := range []*net.UDPConn{second, first} {
|
||||
inode, _, err := dumpSocketDiag(syscall.AF_INET, syscall.IPPROTO_UDP, M.AddrPortFromNet(conn.LocalAddr()), netip.AddrPort{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, socketInode(t, conn), inode)
|
||||
}
|
||||
_, _, err = dumpSocketDiag(syscall.AF_INET, syscall.IPPROTO_UDP, netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 4}), port), netip.AddrPort{})
|
||||
require.ErrorIs(t, err, ErrNotFound)
|
||||
|
||||
wildcard, err := net.ListenUDP("udp4", &net.UDPAddr{})
|
||||
require.NoError(t, err)
|
||||
defer wildcard.Close()
|
||||
inode, _, err := dumpSocketDiag(syscall.AF_INET, syscall.IPPROTO_UDP, netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 4}), M.AddrPortFromNet(wildcard.LocalAddr()).Port()), netip.AddrPort{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, socketInode(t, wildcard), inode)
|
||||
}
|
||||
|
||||
func TestLinuxSearcherFindProcessInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
searcher, err := NewSearcher(Config{Logger: log.NewNOPFactory().NewLogger("test")})
|
||||
require.NoError(t, err)
|
||||
defer searcher.Close()
|
||||
executable, err := os.Executable()
|
||||
require.NoError(t, err)
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
defer listener.Close()
|
||||
tcpConn, err := net.Dial("tcp", listener.Addr().String())
|
||||
require.NoError(t, err)
|
||||
defer tcpConn.Close()
|
||||
info, err := searcher.FindProcessInfo(context.Background(), N.NetworkTCP, M.AddrPortFromNet(tcpConn.LocalAddr()), M.AddrPortFromNet(listener.Addr()))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, executable, info.ProcessPath)
|
||||
require.Equal(t, int32(os.Getuid()), info.UserId)
|
||||
|
||||
udpConn, err := net.ListenUDP("udp4", &net.UDPAddr{})
|
||||
require.NoError(t, err)
|
||||
defer udpConn.Close()
|
||||
info, err = searcher.FindProcessInfo(context.Background(), N.NetworkUDP, netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), M.AddrPortFromNet(udpConn.LocalAddr()).Port()), netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), 53))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, executable, info.ProcessPath)
|
||||
}
|
||||
Reference in New Issue
Block a user