Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 62 additions & 12 deletions infra/conf/transport_internet.go
Original file line number Diff line number Diff line change
Expand Up @@ -1100,12 +1100,13 @@ func (p TransportProtocol) Build() (string, error) {
}

type CustomSockoptConfig struct {
Syetem string `json:"system"`
Network string `json:"network"`
Level string `json:"level"`
Opt string `json:"opt"`
Value string `json:"value"`
Type string `json:"type"`
Syetem string `json:"system"`
Network string `json:"network"`
TcpAfterConn bool `json:"tcpAfterConn"`
Level string `json:"level"`
Opt string `json:"opt"`
Type string `json:"type"`
Value json.RawMessage `json:"value"`
}

type HappyEyeballsConfig struct {
Expand Down Expand Up @@ -1213,13 +1214,28 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
var customSockopts []*internet.CustomSockopt

for _, copt := range c.CustomSockopt {
var err error
switch copt.Type {
case "int", "str":
copt.Value, err = PraseByteSlice(copt.Value, "str")
case "", "array", "hex", "base64":
copt.Value, err = PraseByteSlice(copt.Value, copt.Type)
copt.Type = "str"
default:
return nil, errors.New("unknown custom sockopt type")
}
if err != nil {
return nil, errors.New("custom sockopt").Base(err)
}

customSockopt := &internet.CustomSockopt{
System: copt.Syetem,
Network: copt.Network,
Level: copt.Level,
Opt: copt.Opt,
Value: copt.Value,
Type: copt.Type,
System: copt.Syetem,
Network: copt.Network,
TcpAfterConn: copt.TcpAfterConn,
Level: copt.Level,
Opt: copt.Opt,
Type: copt.Type,
Value: copt.Value,
}
customSockopts = append(customSockopts, customSockopt)
}
Expand Down Expand Up @@ -1276,6 +1292,40 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
}, nil
}

func PraseByteSlice(data json.RawMessage, typ string) ([]byte, error) {
switch strings.ToLower(typ) {
case "", "array":
if len(data) == 0 {
return data, nil
}
var packet []byte
if err := json.Unmarshal(data, &packet); err != nil {
return nil, err
}
return packet, nil
case "str":
var str string
if err := json.Unmarshal(data, &str); err != nil {
return nil, err
}
return []byte(str), nil
case "hex":
var str string
if err := json.Unmarshal(data, &str); err != nil {
return nil, err
}
return hex.DecodeString(str)
case "base64":
var str string
if err := json.Unmarshal(data, &str); err != nil {
return nil, err
}
return base64.StdEncoding.DecodeString(str)
default:
return nil, errors.New("unknown type")
}
}

var (
udpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
"header-dns": func() interface{} { return new(Dns) },
Expand Down
37 changes: 23 additions & 14 deletions transport/internet/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions transport/internet/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,11 @@ message ProxyConfig {
message CustomSockopt {
string system = 1;
string network = 2;
string level = 3;
string opt = 4;
string value = 5;
bool tcp_after_conn = 3;
string level = 4;
string opt = 5;
string type = 6;
bytes value = 7;
}

// SocketConfig is options to be applied on network sockets.
Expand Down
23 changes: 17 additions & 6 deletions transport/internet/sockopt_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
level, _ = strconv.Atoi(custom.Level)
}
if custom.Type == "int" {
value, _ := strconv.Atoi(custom.Value)
if err := syscall.SetsockoptInt(int(fd), level, opt, value); err != nil {
value, _ := strconv.Atoi(string(custom.Value))
if err := setsockoptInt(fd, level, opt, value); err != nil {
return errors.New("failed to set CustomSockoptInt", opt, value, err)
}
} else if custom.Type == "str" {
if err := syscall.SetsockoptString(int(fd), level, opt, custom.Value); err != nil {
if err := setsockoptString(fd, level, opt, string(custom.Value)); err != nil {
return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
}
} else {
Expand Down Expand Up @@ -260,6 +260,9 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
if !strings.HasPrefix(network, custom.Network) {
continue
}
if custom.TcpAfterConn {
continue
}
var level = 0x6 // default TCP
var opt int
if len(custom.Opt) == 0 {
Expand All @@ -271,12 +274,12 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
level, _ = strconv.Atoi(custom.Level)
}
if custom.Type == "int" {
value, _ := strconv.Atoi(custom.Value)
if err := syscall.SetsockoptInt(int(fd), level, opt, value); err != nil {
value, _ := strconv.Atoi(string(custom.Value))
if err := setsockoptInt(fd, level, opt, value); err != nil {
return errors.New("failed to set CustomSockoptInt", opt, value, err)
}
} else if custom.Type == "str" {
if err := syscall.SetsockoptString(int(fd), level, opt, custom.Value); err != nil {
if err := setsockoptString(fd, level, opt, string(custom.Value)); err != nil {
return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
}
} else {
Expand Down Expand Up @@ -327,3 +330,11 @@ func setReusePort(fd uintptr) error {
}
return nil
}

func setsockoptInt(fd uintptr, level, opt, value int) error {
return syscall.SetsockoptInt(int(fd), level, opt, value)
}

func setsockoptString(fd uintptr, level, opt int, s string) error {
return syscall.SetsockoptString(int(fd), level, opt, s)
}
8 changes: 8 additions & 0 deletions transport/internet/sockopt_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,11 @@ func setReusePort(fd uintptr) error {
}
return nil
}

func setsockoptInt(fd uintptr, level, opt, value int) error {
return syscall.SetsockoptInt(int(fd), level, opt, value)
}

func setsockoptString(fd uintptr, level, opt int, s string) error {
return syscall.SetsockoptString(int(fd), level, opt, s)
}
23 changes: 17 additions & 6 deletions transport/internet/sockopt_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
level, _ = strconv.Atoi(custom.Level)
}
if custom.Type == "int" {
value, _ := strconv.Atoi(custom.Value)
if err := syscall.SetsockoptInt(int(fd), level, opt, value); err != nil {
value, _ := strconv.Atoi(string(custom.Value))
if err := setsockoptInt(fd, level, opt, value); err != nil {
return errors.New("failed to set CustomSockoptInt", opt, value, err)
}
} else if custom.Type == "str" {
if err := syscall.SetsockoptString(int(fd), level, opt, custom.Value); err != nil {
if err := setsockoptString(fd, level, opt, string(custom.Value)); err != nil {
return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
}
} else {
Expand Down Expand Up @@ -209,6 +209,9 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
if !strings.HasPrefix(network, custom.Network) {
continue
}
if custom.TcpAfterConn {
continue
}
var level = 0x6 // default TCP
var opt int
if len(custom.Opt) == 0 {
Expand All @@ -220,12 +223,12 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
level, _ = strconv.Atoi(custom.Level)
}
if custom.Type == "int" {
value, _ := strconv.Atoi(custom.Value)
if err := syscall.SetsockoptInt(int(fd), level, opt, value); err != nil {
value, _ := strconv.Atoi(string(custom.Value))
if err := setsockoptInt(fd, level, opt, value); err != nil {
return errors.New("failed to set CustomSockoptInt", opt, value, err)
}
} else if custom.Type == "str" {
if err := syscall.SetsockoptString(int(fd), level, opt, custom.Value); err != nil {
if err := setsockoptString(fd, level, opt, string(custom.Value)); err != nil {
return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
}
} else {
Expand Down Expand Up @@ -271,3 +274,11 @@ func setReusePort(fd uintptr) error {
}
return nil
}

func setsockoptInt(fd uintptr, level, opt, value int) error {
return syscall.SetsockoptInt(int(fd), level, opt, value)
}

func setsockoptString(fd uintptr, level, opt int, s string) error {
return syscall.SetsockoptString(int(fd), level, opt, s)
}
8 changes: 8 additions & 0 deletions transport/internet/sockopt_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ func setReuseAddr(fd uintptr) error {
func setReusePort(fd uintptr) error {
return nil
}

func setsockoptInt(fd uintptr, level, opt, value int) error {
return nil
}

func setsockoptString(fd uintptr, level, opt int, s string) error {
return nil
}
31 changes: 25 additions & 6 deletions transport/internet/sockopt_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
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 {
value, _ := strconv.Atoi(string(custom.Value))
if err := setsockoptInt(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")
if err := setsockoptString(fd, level, opt, string(custom.Value)); err != nil {
return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
}
} else {
return errors.New("unknown CustomSockopt type:", custom.Type)
}
Expand Down Expand Up @@ -155,6 +157,9 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
if !strings.HasPrefix(network, custom.Network) {
continue
}
if custom.TcpAfterConn {
continue
}
var level = 0x6 // default TCP
var opt int
if len(custom.Opt) == 0 {
Expand All @@ -166,12 +171,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
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 {
value, _ := strconv.Atoi(string(custom.Value))
if err := setsockoptInt(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")
if err := setsockoptString(fd, level, opt, string(custom.Value)); err != nil {
return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
}
} else {
return errors.New("unknown CustomSockopt type:", custom.Type)
}
Expand All @@ -192,3 +199,15 @@ func setReuseAddr(fd uintptr) error {
func setReusePort(fd uintptr) error {
return nil
}

func setsockoptInt(fd uintptr, level, opt, value int) error {
return syscall.SetsockoptInt(syscall.Handle(fd), level, opt, value)
}

func setsockoptString(fd uintptr, level, opt int, s string) error {
var p *byte
if len(s) > 0 {
p = &[]byte(s)[0]
}
return syscall.Setsockopt(syscall.Handle(fd), int32(level), int32(opt), p, int32(len(s)))
}
Loading