package tunnel import ( "context" "io" "net" "github.com/pkg/errors" "github.com/xtaci/kcp-go/v5" "gitlab.com/wpetit/goweb/logger" ) func pipe(ctx context.Context, client net.Conn, server net.Conn) (err error) { stop := make(chan bool) go func() { err = relay(client, server, stop) if err != nil { err = errors.WithStack(err) logger.Debug(ctx, "client->server error", logger.E(err)) } }() go func() { err = relay(server, client, stop) if err != nil { err = errors.WithStack(err) logger.Debug(ctx, "server->client error", logger.E(err)) } }() select { case <-stop: return err } } func relay(src net.Conn, dst net.Conn, stop chan bool) (err error) { _, err = io.Copy(dst, src) if errors.Is(err, io.EOF) { err = nil } if err != nil { err = errors.WithStack(err) } stop <- true return } func createBlockCrypt(algorithm string, pass []byte) (kcp.BlockCrypt, error) { switch algorithm { case "sm4": return kcp.NewSM4BlockCrypt(pass[:16]) case "tea": return kcp.NewTEABlockCrypt(pass[:16]) case "xor": return kcp.NewSimpleXORBlockCrypt(pass) case "none": return kcp.NewNoneBlockCrypt(pass) case "aes-128": return kcp.NewAESBlockCrypt(pass[:16]) case "aes-192": return kcp.NewAESBlockCrypt(pass[:24]) case "blowfish": return kcp.NewBlowfishBlockCrypt(pass) case "twofish": return kcp.NewTwofishBlockCrypt(pass) case "cast5": return kcp.NewCast5BlockCrypt(pass[:16]) case "3des": return kcp.NewTripleDESBlockCrypt(pass[:24]) case "xtea": return kcp.NewXTEABlockCrypt(pass[:16]) case "salsa20": return kcp.NewSalsa20BlockCrypt(pass) default: return nil, errors.Errorf("unknown algorithm '%s'", algorithm) } }