mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-05-13 20:44:12 +08:00
fix udp original destination on windows
This commit is contained in:
parent
e9b3c53a0d
commit
d5c53b1ddd
@ -1,5 +1,5 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
//go:build !linux && !windows
|
||||
// +build !linux,!windows
|
||||
|
||||
package dokodemo
|
||||
|
||||
|
27
proxy/dokodemo/fakeudp_windows.go
Normal file
27
proxy/dokodemo/fakeudp_windows.go
Normal file
@ -0,0 +1,27 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package dokodemo
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
|
||||
udpConn, err := net.ListenUDP("udp", addr)
|
||||
if err != nil {
|
||||
return udpConn, err
|
||||
}
|
||||
rawConn, err := udpConn.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = rawConn.Control(func(fd uintptr) {
|
||||
syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return udpConn, nil
|
||||
}
|
@ -11,6 +11,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -142,6 +143,15 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
||||
}
|
||||
}
|
||||
|
||||
if config.ReceiveOriginalDestAddress && isUDPSocket(network) {
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, windows.IP_PKTINFO, 1); err != nil {
|
||||
return errors.New("failed to set IP_PKTINFO").Base(err)
|
||||
}
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, windows.IPV6_PKTINFO, 1); err != nil {
|
||||
return errors.New("failed to set IPV6_PKTINFO").Base(err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.CustomSockopt) > 0 {
|
||||
for _, custom := range config.CustomSockopt {
|
||||
if custom.System != "" && custom.System != runtime.GOOS {
|
||||
|
@ -1,5 +1,5 @@
|
||||
//go:build !linux && !freebsd && !darwin
|
||||
// +build !linux,!freebsd,!darwin
|
||||
//go:build !linux && !freebsd && !darwin && !windows
|
||||
// +build !linux,!freebsd,!darwin,!windows
|
||||
|
||||
package udp
|
||||
|
||||
|
54
transport/internet/udp/hub_windows.go
Normal file
54
transport/internet/udp/hub_windows.go
Normal file
@ -0,0 +1,54 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package udp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"unsafe"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func RetrieveOriginalDest(oob []byte) net.Destination {
|
||||
dest := net.Destination{}
|
||||
port := binary.LittleEndian.Uint16(oob[:2])
|
||||
buf := buf.FromBytes(oob[2:])
|
||||
defer buf.Release()
|
||||
|
||||
for !buf.IsEmpty() {
|
||||
cm := &windows.WSACMSGHDR{}
|
||||
len := make([]byte, unsafe.Sizeof(cm.Len))
|
||||
nRead, err := buf.Read(len)
|
||||
if err != nil {
|
||||
return dest
|
||||
}
|
||||
cm.Len = uintptr(binary.LittleEndian.Uint16(len))
|
||||
binary.Read(buf, binary.LittleEndian, &cm.Level)
|
||||
binary.Read(buf, binary.LittleEndian, &cm.Type)
|
||||
nRead += 8 // len cm.Level + cm.Type
|
||||
|
||||
if cm.Type == windows.IP_PKTINFO {
|
||||
if cm.Level == windows.IPPROTO_IP { // IPv4
|
||||
pktinf := &windows.IN_PKTINFO{}
|
||||
binary.Read(buf, binary.LittleEndian, pktinf)
|
||||
return net.UDPDestination(net.IPAddress(pktinf.Addr[:]), net.Port(port))
|
||||
} else { // IPv6
|
||||
pktinfv6 := &windows.IN6_PKTINFO{}
|
||||
binary.Read(buf, binary.LittleEndian, pktinfv6)
|
||||
return net.UDPDestination(net.IPAddress(pktinfv6.Addr[:]), net.Port(port))
|
||||
}
|
||||
}
|
||||
buf.Advance(int32(cm.Len) - int32(nRead))
|
||||
}
|
||||
return dest
|
||||
}
|
||||
|
||||
func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
|
||||
udpAddr, _ := net.ResolveUDPAddr(conn.LocalAddr().Network(), conn.LocalAddr().String())
|
||||
binary.LittleEndian.PutUint16(oob[:2], uint16(udpAddr.Port))
|
||||
n, oobn, flags, addr, err := conn.ReadMsgUDP(payload, oob[2:])
|
||||
return n, oobn + 2, flags, addr, err
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user