package tunnel import ( "crypto/sha1" "time" "github.com/pkg/errors" "github.com/xtaci/kcp-go/v5" "github.com/xtaci/smux" "golang.org/x/crypto/pbkdf2" ) type ClientConfig struct { ServerAddress string BlockCrypt kcp.BlockCrypt DataShards int ParityShards int Credentials interface{} ConfigureConn ConfigureConnFunc AuthenticationTimeout time.Duration ProxyRequestTimeout time.Duration SmuxConfig *smux.Config } // nolint: go-mnd func DefaultClientConfig() *ClientConfig { unencryptedBlock, err := kcp.NewNoneBlockCrypt(nil) if err != nil { // should never happen panic(errors.WithStack(err)) } smuxConfig := smux.DefaultConfig() smuxConfig.Version = 2 smuxConfig.KeepAliveInterval = 10 * time.Second smuxConfig.MaxReceiveBuffer = 4194304 smuxConfig.MaxStreamBuffer = 2097152 return &ClientConfig{ ServerAddress: "127.0.0.1:36543", BlockCrypt: unencryptedBlock, DataShards: 3, ParityShards: 10, Credentials: nil, ConfigureConn: DefaultClientConfigureConn, AuthenticationTimeout: 30 * time.Second, ProxyRequestTimeout: 5 * time.Second, SmuxConfig: smuxConfig, } } type ClientConfigFunc func(c *ClientConfig) func WithClientServerAddress(addr string) ClientConfigFunc { return func(conf *ClientConfig) { conf.ServerAddress = addr } } func WithClientCredentials(credentials interface{}) ClientConfigFunc { return func(conf *ClientConfig) { conf.Credentials = credentials } } func WithClientBlockCrypt(alg string, pass, salt string, iterations, keyLen int) ClientConfigFunc { return func(conf *ClientConfig) { key := pbkdf2.Key([]byte(pass), []byte(salt), iterations, keyLen, sha1.New) block, err := createBlockCrypt(alg, key) if err != nil { panic(errors.Wrap(err, "could not create block crypt")) } conf.BlockCrypt = block } } func WithClientConfigureConn(fn ConfigureConnFunc) ClientConfigFunc { return func(conf *ClientConfig) { conf.ConfigureConn = fn } } func WithClientSmuxConfig(c *smux.Config) ClientConfigFunc { return func(conf *ClientConfig) { conf.SmuxConfig = c } } // nolint: go-mnd func DefaultClientConfigureConn(conn *kcp.UDPSession) error { // Based on kcptun default configuration, mode 'fast3' conn.SetStreamMode(true) conn.SetWriteDelay(false) conn.SetNoDelay(1, 10, 2, 1) conn.SetWindowSize(128, 512) conn.SetMtu(1400) conn.SetACKNoDelay(true) if err := conn.SetReadBuffer(16777217); err != nil { return errors.WithStack(err) } if err := conn.SetWriteBuffer(16777217); err != nil { return errors.WithStack(err) } if err := conn.SetDSCP(46); err != nil { return errors.WithStack(err) } return nil }