mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-04-30 17:38:41 +00:00
Sockopt: Allow customSockopt
work for Windows & Darwin (#4576)
* Sockopt: Add custom sockopt on Windows & Darwin * fix windows udp by the way * use resolved addr https://github.com/XTLS/Xray-core/pull/4504#issuecomment-2769153797
This commit is contained in:
parent
7a2f42f8d5
commit
5f3ae64f0c
7 changed files with 306 additions and 118 deletions
|
@ -1,8 +1,12 @@
|
|||
package internet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
|
@ -33,7 +37,10 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||
if err != nil {
|
||||
return errors.New("failed to find the interface").Base(err)
|
||||
}
|
||||
isV4 := (network == "tcp4" || network == "udp4")
|
||||
// easy way to check if the address is ipv4
|
||||
isV4 := strings.Contains(address, ".")
|
||||
// note: DO NOT trust the passed network variable, it can be udp6 even if the address is ipv4
|
||||
// because operating system might(always) use ipv6 socket to process ipv4
|
||||
if isV4 {
|
||||
var bytes [4]byte
|
||||
binary.BigEndian.PutUint32(bytes[:], uint32(inf.Index))
|
||||
|
@ -69,6 +76,42 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||
}
|
||||
}
|
||||
|
||||
if len(config.CustomSockopt) > 0 {
|
||||
for _, custom := range config.CustomSockopt {
|
||||
if custom.System != "" && custom.System != runtime.GOOS {
|
||||
errors.LogDebug(context.Background(), "CustomSockopt system not match: ", "want ", custom.System, " got ", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
// Skip unwanted network type
|
||||
// network might be tcp4 or tcp6
|
||||
// use HasPrefix so that "tcp" can match tcp4/6 with "tcp" if user want to control all tcp (udp is also the same)
|
||||
// if it is empty, strings.HasPrefix will always return true to make it apply for all networks
|
||||
if !strings.HasPrefix(network, custom.Network) {
|
||||
continue
|
||||
}
|
||||
var level = 0x6 // default TCP
|
||||
var opt int
|
||||
if len(custom.Opt) == 0 {
|
||||
return errors.New("No opt!")
|
||||
} else {
|
||||
opt, _ = strconv.Atoi(custom.Opt)
|
||||
}
|
||||
if custom.Level != "" {
|
||||
level, _ = strconv.Atoi(custom.Level)
|
||||
}
|
||||
if custom.Type == "int" {
|
||||
value, _ := strconv.Atoi(custom.Value)
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), level, opt, value); err != nil {
|
||||
return errors.New("failed to set CustomSockoptInt", opt, value, err)
|
||||
}
|
||||
} else if custom.Type == "str" {
|
||||
return errors.New("failed to set CustomSockoptString: Str type does not supported on windows")
|
||||
} else {
|
||||
return errors.New("unknown CustomSockopt type:", custom.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -94,6 +137,42 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
|||
}
|
||||
}
|
||||
|
||||
if len(config.CustomSockopt) > 0 {
|
||||
for _, custom := range config.CustomSockopt {
|
||||
if custom.System != "" && custom.System != runtime.GOOS {
|
||||
errors.LogDebug(context.Background(), "CustomSockopt system not match: ", "want ", custom.System, " got ", runtime.GOOS)
|
||||
continue
|
||||
}
|
||||
// Skip unwanted network type
|
||||
// network might be tcp4 or tcp6
|
||||
// use HasPrefix so that "tcp" can match tcp4/6 with "tcp" if user want to control all tcp (udp is also the same)
|
||||
// if it is empty, strings.HasPrefix will always return true to make it apply for all networks
|
||||
if !strings.HasPrefix(network, custom.Network) {
|
||||
continue
|
||||
}
|
||||
var level = 0x6 // default TCP
|
||||
var opt int
|
||||
if len(custom.Opt) == 0 {
|
||||
return errors.New("No opt!")
|
||||
} else {
|
||||
opt, _ = strconv.Atoi(custom.Opt)
|
||||
}
|
||||
if custom.Level != "" {
|
||||
level, _ = strconv.Atoi(custom.Level)
|
||||
}
|
||||
if custom.Type == "int" {
|
||||
value, _ := strconv.Atoi(custom.Value)
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), level, opt, value); err != nil {
|
||||
return errors.New("failed to set CustomSockoptInt", opt, value, err)
|
||||
}
|
||||
} else if custom.Type == "str" {
|
||||
return errors.New("failed to set CustomSockoptString: Str type does not supported on windows")
|
||||
} else {
|
||||
return errors.New("unknown CustomSockopt type:", custom.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue