github.com/eagleql/xray-core@v1.4.4/proxy/dokodemo/fakeudp_linux.go (about) 1 // +build linux 2 3 package dokodemo 4 5 import ( 6 "fmt" 7 "net" 8 "os" 9 "syscall" 10 11 "golang.org/x/sys/unix" 12 ) 13 14 func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) { 15 var af int 16 var sockaddr syscall.Sockaddr 17 18 if len(addr.IP) == 4 { 19 af = syscall.AF_INET 20 sockaddr = &syscall.SockaddrInet4{Port: addr.Port} 21 copy(sockaddr.(*syscall.SockaddrInet4).Addr[:], addr.IP) 22 } else { 23 af = syscall.AF_INET6 24 sockaddr = &syscall.SockaddrInet6{Port: addr.Port} 25 copy(sockaddr.(*syscall.SockaddrInet6).Addr[:], addr.IP) 26 } 27 28 var fd int 29 var err error 30 31 if fd, err = syscall.Socket(af, syscall.SOCK_DGRAM, 0); err != nil { 32 return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("socket open: %s", err)} 33 } 34 35 if mark != 0 { 36 if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, mark); err != nil { 37 syscall.Close(fd) 38 return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: SO_MARK: %s", err)} 39 } 40 } 41 42 if err = syscall.SetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil { 43 syscall.Close(fd) 44 return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: IP_TRANSPARENT: %s", err)} 45 } 46 47 syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) 48 49 syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1) 50 51 if err = syscall.Bind(fd, sockaddr); err != nil { 52 syscall.Close(fd) 53 return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("socket bind: %s", err)} 54 } 55 56 fdFile := os.NewFile(uintptr(fd), fmt.Sprintf("net-udp-fake-%s", addr.String())) 57 defer fdFile.Close() 58 59 packetConn, err := net.FilePacketConn(fdFile) 60 if err != nil { 61 syscall.Close(fd) 62 return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("convert file descriptor to connection: %s", err)} 63 } 64 65 return packetConn, nil 66 }