diff --git a/cmd/ck-client/ck-client.go b/cmd/ck-client/ck-client.go index 1a43651..8014790 100644 --- a/cmd/ck-client/ck-client.go +++ b/cmd/ck-client/ck-client.go @@ -201,6 +201,6 @@ func main() { if err != nil { log.Fatal(err) } - client.RouteTCP(listener, localConfig.Timeout, remoteConfig.Singleplex, seshMaker) + client.RouteTCP(listener, localConfig.Timeout, remoteConfig.Singleplex, localConfig.TcpSendBuffer, localConfig.TcpReceiveBuffer, seshMaker) } } diff --git a/internal/client/piper.go b/internal/client/piper.go index 43186ac..bc53b67 100644 --- a/internal/client/piper.go +++ b/internal/client/piper.go @@ -4,6 +4,7 @@ import ( "io" "net" "sync" + "syscall" "time" "github.com/cbeuw/Cloak/internal/common" @@ -95,7 +96,7 @@ func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration } } -func RouteTCP(listener net.Listener, streamTimeout time.Duration, singleplex bool, newSeshFunc func() *mux.Session) { +func RouteTCP(listener net.Listener, streamTimeout time.Duration, singleplex bool, sendBufferSize int, receiveBufferSize int, newSeshFunc func() *mux.Session) { var sesh *mux.Session for { localConn, err := listener.Accept() @@ -103,6 +104,29 @@ func RouteTCP(listener net.Listener, streamTimeout time.Duration, singleplex boo log.Fatal(err) continue } + + file, err := localConn.(*net.TCPConn).File() + if err != nil { + log.Fatal(err) + continue + } + + if sendBufferSize > 0 { + log.Debugf("Setting loopback connection tcp send buffer: %d", sendBufferSize) + err := syscall.SetsockoptInt(common.Platformfd(file.Fd()), syscall.SOL_SOCKET, syscall.SO_SNDBUF, sendBufferSize) + if err != nil { + log.Errorf("setsocketopt SO_SNDBUF: %s\n", err) + } + } + + if receiveBufferSize > 0 { + log.Debugf("Setting loopback connection tcp receive buffer: %d", receiveBufferSize) + err = syscall.SetsockoptInt(common.Platformfd(file.Fd()), syscall.SOL_SOCKET, syscall.SO_RCVBUF, receiveBufferSize) + if err != nil { + log.Errorf("setsocketopt SO_RCVBUF: %s\n", err) + } + } + if !singleplex && (sesh == nil || sesh.IsClosed()) { sesh = newSeshFunc() } diff --git a/internal/client/state.go b/internal/client/state.go index 3979f2d..f87c19b 100644 --- a/internal/client/state.go +++ b/internal/client/state.go @@ -33,13 +33,15 @@ type RawConfig struct { RemotePort string // jsonOptional AlternativeNames []string // jsonOptional // defaults set in ProcessRawConfig - UDP bool // nullable - BrowserSig string // nullable - Transport string // nullable - CDNOriginHost string // nullable - CDNWsUrlPath string // nullable - StreamTimeout int // nullable - KeepAlive int // nullable + UDP bool // nullable + BrowserSig string // nullable + Transport string // nullable + CDNOriginHost string // nullable + CDNWsUrlPath string // nullable + StreamTimeout int // nullable + KeepAlive int // nullable + LoopbackTcpSendBuffer int // nullable + LoopbackTcpReceiveBuffer int // nullable } type RemoteConnConfig struct { @@ -51,9 +53,11 @@ type RemoteConnConfig struct { } type LocalConnConfig struct { - LocalAddr string - Timeout time.Duration - MockDomainList []string + LocalAddr string + Timeout time.Duration + MockDomainList []string + TcpSendBuffer int + TcpReceiveBuffer int } type AuthInfo struct { @@ -279,5 +283,13 @@ func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (local Loca local.Timeout = time.Duration(raw.StreamTimeout) * time.Second } + if raw.LoopbackTcpSendBuffer > 0 { + local.TcpSendBuffer = raw.LoopbackTcpSendBuffer + } + + if raw.LoopbackTcpReceiveBuffer > 0 { + local.TcpReceiveBuffer = raw.LoopbackTcpReceiveBuffer + } + return } diff --git a/internal/common/platformfd_android.go b/internal/common/platformfd_android.go new file mode 100644 index 0000000..81937fe --- /dev/null +++ b/internal/common/platformfd_android.go @@ -0,0 +1,8 @@ +//go:build android +// +build android + +package common + +func Platformfd(fd uintptr) int { + return int(fd) +} diff --git a/internal/common/platformfd_darwin.go b/internal/common/platformfd_darwin.go new file mode 100644 index 0000000..cfdb699 --- /dev/null +++ b/internal/common/platformfd_darwin.go @@ -0,0 +1,8 @@ +//go:build darwin +// +build darwin + +package common + +func Platformfd(fd uintptr) int { + return int(fd) +} diff --git a/internal/server/platformfd_linux.go b/internal/common/platformfd_linux.go similarity index 51% rename from internal/server/platformfd_linux.go rename to internal/common/platformfd_linux.go index d0815c4..bc56635 100644 --- a/internal/server/platformfd_linux.go +++ b/internal/common/platformfd_linux.go @@ -1,8 +1,8 @@ //go:build linux // +build linux -package server +package common -func platformfd(fd uintptr) int { +func Platformfd(fd uintptr) int { return int(fd) } diff --git a/internal/server/platformfd_windows.go b/internal/common/platformfd_windows.go similarity index 58% rename from internal/server/platformfd_windows.go rename to internal/common/platformfd_windows.go index bb14a46..bb0948b 100644 --- a/internal/server/platformfd_windows.go +++ b/internal/common/platformfd_windows.go @@ -1,10 +1,10 @@ //go:build windows // +build windows -package server +package common import "syscall" -func platformfd(fd uintptr) syscall.Handle { +func Platformfd(fd uintptr) syscall.Handle { return syscall.Handle(fd) } diff --git a/internal/server/state.go b/internal/server/state.go index 66ed480..62a1121 100644 --- a/internal/server/state.go +++ b/internal/server/state.go @@ -180,7 +180,7 @@ func InitState(preParse RawConfig, worldState common.WorldState) (sta *State, er return c.Control(func(fd uintptr) { if preParse.LoopbackTcpSendBuffer > 0 { log.Debugf("Setting loopback connection tcp send buffer: %d", preParse.LoopbackTcpSendBuffer) - err := syscall.SetsockoptInt(platformfd(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, preParse.LoopbackTcpSendBuffer) + err := syscall.SetsockoptInt(common.Platformfd(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, preParse.LoopbackTcpSendBuffer) if err != nil { log.Errorf("setsocketopt SO_SNDBUF: %s\n", err) } @@ -188,7 +188,7 @@ func InitState(preParse RawConfig, worldState common.WorldState) (sta *State, er if preParse.LoopbackTcpReceiveBuffer > 0 { log.Debugf("Setting loopback connection tcp receive buffer: %d", preParse.LoopbackTcpReceiveBuffer) - err = syscall.SetsockoptInt(platformfd(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, preParse.LoopbackTcpReceiveBuffer) + err = syscall.SetsockoptInt(common.Platformfd(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, preParse.LoopbackTcpReceiveBuffer) if err != nil { log.Errorf("setsocketopt SO_RCVBUF: %s\n", err) }