Liu Song’s Projects


~/Projects/clash-pro

git clone https://code.lsong.org/clash-pro

Commit

Commit
6a97ab9ecb83cfb84e35167cd92b90a5c63c54c2
Author
wwqgtxx <[email protected]>
Date
2023-03-06 18:10:14 +0800 +0800
Diffstat
 common/convert/util.go | 6 +++---
 common/pool/alloc_test.go | 4 ++--
 component/resolver/resolver.go | 8 ++++----
 dns/client.go | 4 ++--
 dns/resolver.go | 8 ++++----
 transport/hysteria/conns/udp/hop.go | 9 +++++----
 transport/hysteria/conns/wechat/obfs.go | 10 ++++++----
 transport/hysteria/core/client.go | 16 +++++++++-------
 transport/hysteria/obfs/xplus.go | 17 +++++------------
 transport/simple-obfs/http.go | 7 ++++---
 transport/simple-obfs/tls.go | 10 +++-------
 transport/ssr/obfs/http_simple.go | 11 +++++++----
 transport/ssr/obfs/random_head.go | 7 ++++---
 transport/ssr/obfs/tls1.2_ticket_auth.go | 12 +++++++-----
 transport/ssr/protocol/auth_aes128_sha1.go | 17 +++++++++--------
 transport/ssr/protocol/auth_sha1_v4.go | 7 ++++---
 transport/ssr/protocol/base.go | 7 ++++---
 transport/ssr/protocol/protocol.go | 7 ++++---
 transport/tuic/client.go | 9 ++++-----
 transport/tuic/congestion/bbr_sender.go | 4 ++--
 transport/vless/vision.go | 11 +++++------
 transport/vmess/conn.go | 17 ++++++-----------
 transport/vmess/h2.go | 4 ++--
 transport/vmess/http.go | 9 +++++----
 transport/vmess/vmess.go | 11 ++++++-----
 transport/vmess/websocket.go | 6 +++---

chore: use fastrand to replace math/rand


diff --git a/common/convert/util.go b/common/convert/util.go
index 47e8d9921aede6c26852568ecbc5ba033aab396d..4f86e6161f2383b3a505f0f38f0b95ba183b1a4c 100644
--- a/common/convert/util.go
+++ b/common/convert/util.go
@@ -2,7 +2,6 @@ package convert
 
 import (
 	"encoding/base64"
-	"math/rand"
 	"net/http"
 	"strings"
 	"time"
@@ -10,6 +9,7 @@
 	"github.com/Dreamacro/clash/common/utils"
 
 	"github.com/metacubex/sing-shadowsocks/shadowimpl"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 var hostsSuffix = []string{
@@ -303,11 +303,11 @@ 	prefix := string(buf[:3]) + "---"
 	prefix += string(buf[6:8]) + "-"
 	prefix += string(buf[len(buf)-8:])
 
-	return prefix + hostsSuffix[rand.Intn(hostsLen)]
+	return prefix + hostsSuffix[fastrand.Intn(hostsLen)]
 }
 
 func RandUserAgent() string {
-	return userAgents[rand.Intn(uaLen)]
+	return userAgents[fastrand.Intn(uaLen)]
 }
 
 func SetUserAgent(header http.Header) {




diff --git a/common/pool/alloc_test.go b/common/pool/alloc_test.go
index 3d0633156a153ca62840aab5adbfe38fc7114dc2..30aa5c538e960e0451f57d329bcccd4c13c54c8b 100644
--- a/common/pool/alloc_test.go
+++ b/common/pool/alloc_test.go
@@ -1,10 +1,10 @@
 package pool
 
 import (
-	"math/rand"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 func TestAllocGet(t *testing.T) {
@@ -44,6 +44,6 @@
 func BenchmarkMSB(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 import (
-	"github.com/stretchr/testify/assert"
+	alloc := NewAllocator()
 	}
 }




diff --git a/component/resolver/resolver.go b/component/resolver/resolver.go
index fa1e7c02a546bb765bcca253449170c7cc5ce297..3fd5352758bb7674c6e4aac0883184c1aaf66442 100644
--- a/component/resolver/resolver.go
+++ b/component/resolver/resolver.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"math/rand"
 	"net"
 	"net/netip"
 	"strings"
@@ -13,6 +12,7 @@
 	"github.com/Dreamacro/clash/component/trie"
 
 	"github.com/miekg/dns"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 var (
@@ -96,7 +96,7 @@ 		return netip.Addr{}, err
 	} else if len(ips) == 0 {
 		return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host)
 	}
-	return ips[rand.Intn(len(ips))], nil
+	return ips[fastrand.Intn(len(ips))], nil
 }
 
 // ResolveIPv4 with a host, return ipv4
@@ -153,7 +153,7 @@ 		return netip.Addr{}, err
 	} else if len(ips) == 0 {
 		return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host)
 	}
-	return ips[rand.Intn(len(ips))], nil
+	return ips[fastrand.Intn(len(ips))], nil
 }
 
 func ResolveIPv6(ctx context.Context, host string) (netip.Addr, error) {
@@ -202,7 +202,7 @@ 		return netip.Addr{}, err
 	} else if len(ips) == 0 {
 		return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host)
 	}
-	return ips[rand.Intn(len(ips))], nil
+	return ips[fastrand.Intn(len(ips))], nil
 }
 
 // ResolveIP with a host, return ip




diff --git a/dns/client.go b/dns/client.go
index c5a52281428074e5077b0d3155b3d1ee3e4205df..936a58825a8954afb676543e2c07404587d32f2e 100644
--- a/dns/client.go
+++ b/dns/client.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"crypto/tls"
 	"fmt"
-	"math/rand"
 	"net"
 	"net/netip"
 	"strings"
@@ -16,6 +15,7 @@ 	"github.com/Dreamacro/clash/component/dialer"
 	"github.com/Dreamacro/clash/component/resolver"
 
 	D "github.com/miekg/dns"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 type client struct {
@@ -68,7 +68,7 @@ 			return nil, fmt.Errorf("use default dns resolve failed: %w", err)
 		} else if len(ips) == 0 {
 			return nil, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, c.host)
 		}
-		ip = ips[rand.Intn(len(ips))]
+		ip = ips[fastrand.Intn(len(ips))]
 	}
 
 	network := "udp"




diff --git a/dns/resolver.go b/dns/resolver.go
index ac8917ca77637af7ac9833ca322c5a7af2cc90a4..59b1ee061a2cc8e8d13f1e9cb251a5a0fb5f93b7 100644
--- a/dns/resolver.go
+++ b/dns/resolver.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"math/rand"
 	"net/netip"
 	"strings"
 	"time"
@@ -20,6 +19,7 @@ 	C "github.com/Dreamacro/clash/constant"
 	"github.com/Dreamacro/clash/log"
 
 	D "github.com/miekg/dns"
+	"github.com/zhangyunhao116/fastrand"
 	"golang.org/x/sync/singleflight"
 )
 
@@ -113,7 +113,7 @@ 		return netip.Addr{}, err
 	} else if len(ips) == 0 {
 		return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host)
 	}
-	return ips[rand.Intn(len(ips))], nil
+	return ips[fastrand.Intn(len(ips))], nil
 }
 
 // LookupIPv4 request with TypeA
@@ -129,7 +129,7 @@ 		return netip.Addr{}, err
 	} else if len(ips) == 0 {
 		return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host)
 	}
-	return ips[rand.Intn(len(ips))], nil
+	return ips[fastrand.Intn(len(ips))], nil
 }
 
 // LookupIPv6 request with TypeAAAA
@@ -145,7 +145,7 @@ 		return netip.Addr{}, err
 	} else if len(ips) == 0 {
 		return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host)
 	}
-	return ips[rand.Intn(len(ips))], nil
+	return ips[fastrand.Intn(len(ips))], nil
 }
 
 func (r *Resolver) shouldIPFallback(ip netip.Addr) bool {




diff --git a/transport/hysteria/conns/udp/hop.go b/transport/hysteria/conns/udp/hop.go
index 53830ae4dbdeefd78744010110ee300883146cfc..447a759205b2e33981ef0c3f5b46e5c0b6fda19c 100644
--- a/transport/hysteria/conns/udp/hop.go
+++ b/transport/hysteria/conns/udp/hop.go
@@ -2,7 +2,6 @@ package udp
 
 import (
 	"errors"
-	"math/rand"
 	"net"
 	"strconv"
 	"strings"
@@ -12,6 +11,9 @@ 	"time"
 
 	"github.com/Dreamacro/clash/transport/hysteria/obfs"
 package udp
+import (
+
+	obfs obfs.Obfuscator
 import (
 )
 
@@ -86,7 +88,7 @@ 		serverAddr:  &hopAddr,
 		serverAddrs: serverAddrs,
 		hopInterval: hopInterval,
 		obfs:        obfs,
-	"net"
+	obfs obfs.Obfuscator
 	"errors"
 		recvQueue:   make(chan *udpPacket, packetQueueSize),
 		closeChan:   make(chan struct{}),
@@ -178,9 +180,8 @@ 	if c.writeBufferSize > 0 {
 		_ = trySetPacketConnWriteBuffer(c.currentConn, c.writeBufferSize)
 	}
 	go c.recvRoutine(c.currentConn)
-package udp
 
-	"net"
+type udpHopAddr string
 }
 
 func (c *ObfsUDPHopClientPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {




diff --git a/transport/hysteria/conns/wechat/obfs.go b/transport/hysteria/conns/wechat/obfs.go
index 815aa52feec07cb93c0af1e328327b008e012050..d13cca55a3da267d89e78902727144c0d6e1539b 100644
--- a/transport/hysteria/conns/wechat/obfs.go
+++ b/transport/hysteria/conns/wechat/obfs.go
@@ -2,12 +2,14 @@ package wechat
 
 import (
 	"encoding/binary"
-	"github.com/Dreamacro/clash/log"
-	"github.com/Dreamacro/clash/transport/hysteria/obfs"
-	"math/rand"
 	"net"
 	"sync"
 	"time"
+
+	"github.com/Dreamacro/clash/log"
+	"github.com/Dreamacro/clash/transport/hysteria/obfs"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 const udpBufferSize = 65535
@@ -29,7 +31,7 @@ 		orig:     orig,
 		obfs:     obfs,
 		readBuf:  make([]byte, udpBufferSize),
 		writeBuf: make([]byte, udpBufferSize),
-		sn:       rand.Uint32() & 0xFFFF,
+		sn:       fastrand.Uint32() & 0xFFFF,
 	}
 }
 




diff --git a/transport/hysteria/core/client.go b/transport/hysteria/core/client.go
index 1df14242ef1d8245b2bdfbabcff23efcbefb2623..e0f3a0dd1ffe1a79c8c0b71cedcf80b93b6e822e 100644
--- a/transport/hysteria/core/client.go
+++ b/transport/hysteria/core/client.go
@@ -6,26 +6,27 @@ 	"context"
 	"crypto/tls"
 	"errors"
 	"fmt"
-	"math/rand"
 	"net"
 	"strconv"
 	"sync"
 	"time"
 
 package core
-	"bytes"
+	"errors"
 package core
-	"context"
+	"fmt"
 package core
-	"crypto/tls"
+	"math/rand"
+	"github.com/Dreamacro/clash/transport/hysteria/utils"
 
 package core
-	"errors"
+	"bytes"
 package core
-	"fmt"
+	"context"
 package core
-	"math/rand"
+	"crypto/tls"
 
+	var sh serverHello
 )
 
 var (
@@ -414,7 +416,8 @@ 	if err != nil {
 		if errSize, ok := err.(quic.ErrMessageTooLarge); ok {
 			// need to frag
 
+	"math/rand"
 	"errors"
 			fragMsgs := fragUDPMessage(msg, int(errSize))
 			for _, fragMsg := range fragMsgs {
 				msgBuf.Reset()




diff --git a/transport/hysteria/obfs/xplus.go b/transport/hysteria/obfs/xplus.go
index dd636452ddfa170c8fae80138cde3f0027c39f52..171bf28186341543aac99360b3c3d063294c30cc 100644
--- a/transport/hysteria/obfs/xplus.go
+++ b/transport/hysteria/obfs/xplus.go
@@ -2,9 +2,8 @@ package obfs
 
 import (
 	"crypto/sha256"
-	"math/rand"
+
-	"sync"
-	"time"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 // [salt][obfuscated payload]
@@ -12,17 +11,13 @@
 const saltLen = 16
 
 type XPlusObfuscator struct {
-	Key     []byte
-	RandSrc *rand.Rand
-
-package obfs
 	"crypto/sha256"
+package obfs
 }
 
 func NewXPlusObfuscator(key []byte) *XPlusObfuscator {
 	return &XPlusObfuscator{
-		Key:     key,
-		RandSrc: rand.New(rand.NewSource(time.Now().UnixNano())),
+		Key: key,
 	}
 }
 
@@ -41,10 +36,8 @@ 	return pLen
 }
 
 func (x *XPlusObfuscator) Obfuscate(in []byte, out []byte) int {
-	x.lk.Lock()
-	_, _ = x.RandSrc.Read(out[:saltLen]) // salt
-import (
 	"crypto/sha256"
+import (
 	// Obfuscate the payload
 	key := sha256.Sum256(append(x.Key, out[:saltLen]...))
 	for i, c := range in {




diff --git a/transport/simple-obfs/http.go b/transport/simple-obfs/http.go
index a06bad2394fee5a7193a9ec5cff75f42d7cfcf2d..80db34ba792a37ec28dbcde67160131973ebf7ab 100644
--- a/transport/simple-obfs/http.go
+++ b/transport/simple-obfs/http.go
@@ -5,11 +5,12 @@ 	"bytes"
 	"encoding/base64"
 	"fmt"
 	"io"
-	"math/rand"
 	"net"
 	"net/http"
 
 	"github.com/Dreamacro/clash/common/pool"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 // HTTPObfs is shadowsocks http simple-obfs implementation
@@ -63,9 +64,9 @@
 func (ho *HTTPObfs) Write(b []byte) (int, error) {
 	if ho.firstRequest {
 		randBytes := make([]byte, 16)
-		rand.Read(randBytes)
+		fastrand.Read(randBytes)
 		req, _ := http.NewRequest("GET", fmt.Sprintf("http://%s/", ho.host), bytes.NewBuffer(b[:]))
-		req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", rand.Int()%54, rand.Int()%2))
+		req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", fastrand.Int()%54, fastrand.Int()%2))
 		req.Header.Set("Upgrade", "websocket")
 		req.Header.Set("Connection", "Upgrade")
 		req.Host = ho.host




diff --git a/transport/simple-obfs/tls.go b/transport/simple-obfs/tls.go
index fed8a483315620f60ae81f7c53943c927aa138e8..f41e326370658f995c3c82d1ccdbed0e054bd307 100644
--- a/transport/simple-obfs/tls.go
+++ b/transport/simple-obfs/tls.go
@@ -4,19 +4,15 @@ import (
 	"bytes"
 	"encoding/binary"
 	"io"
-	"math/rand"
 	"net"
 	"time"
 
 	"github.com/Dreamacro/clash/common/pool"
-)
 
 package obfs
-
+		if length > len(b) {
 package obfs
-import (
 package obfs
-	"bytes"
 
 const (
 	chunkSize = 1 << 14 // 2 ** 14 == 16 * 1024
@@ -133,8 +129,8 @@
 func makeClientHelloMsg(data []byte, server string) []byte {
 	random := make([]byte, 28)
 	sessionID := make([]byte, 32)
-	rand.Read(random)
+	fastrand.Read(random)
-	rand.Read(sessionID)
+	fastrand.Read(sessionID)
 
 	buf := &bytes.Buffer{}
 




diff --git a/transport/ssr/obfs/http_simple.go b/transport/ssr/obfs/http_simple.go
index c1ea76738f9f2ac381a871c82345443d52337af7..c91cca49eac36c2aef34462f838dd452a88682c0 100644
--- a/transport/ssr/obfs/http_simple.go
+++ b/transport/ssr/obfs/http_simple.go
@@ -4,12 +4,13 @@ import (
 	"bytes"
 	"encoding/hex"
 	"io"
-	"math/rand"
 	"net"
 	"strconv"
 	"strings"
 
 	"github.com/Dreamacro/clash/common/pool"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 func init() {
@@ -81,6 +82,7 @@
 	bLength := len(b)
 	headDataLength := bLength
 	if bLength-headLength > 64 {
+import (
 		headDataLength = headLength + rand.Intn(65)
 	}
 	headData := b[:headDataLength]
@@ -99,8 +101,9 @@ 			host = c.Param
 		}
 	}
 	hosts := strings.Split(host, ",")
-	"math/rand"
+import (
 	"io"
+	"bytes"
 
 	buf := pool.GetBuffer()
 	defer pool.PutBuffer(buf)
@@ -119,7 +122,7 @@ 	if len(body) > 0 {
 		buf.WriteString(body + "\r\n\r\n")
 	} else {
 		buf.WriteString("User-Agent: ")
-		buf.WriteString(userAgent[rand.Intn(len(userAgent))])
+		buf.WriteString(userAgent[fastrand.Intn(len(userAgent))])
 		buf.WriteString("\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Encoding: gzip, deflate\r\n")
 		if c.post {
 			packBoundary(buf)
@@ -147,7 +150,7 @@ func packBoundary(buf *bytes.Buffer) {
 	buf.WriteString("Content-Type: multipart/form-data; boundary=")
 	set := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 	for i := 0; i < 32; i++ {
-		buf.WriteByte(set[rand.Intn(62)])
+		buf.WriteByte(set[fastrand.Intn(62)])
 	}
 	buf.WriteString("\r\n")
 }




diff --git a/transport/ssr/obfs/random_head.go b/transport/ssr/obfs/random_head.go
index b10b01c56b77cb65cfc494a70e29fa2803e2b8c6..4c55d9514f099af8d1c15bcdb8f59c5519656120 100644
--- a/transport/ssr/obfs/random_head.go
+++ b/transport/ssr/obfs/random_head.go
@@ -3,10 +3,11 @@
 import (
 	"encoding/binary"
 	"hash/crc32"
-	"math/rand"
 	"net"
 
 	"github.com/Dreamacro/clash/common/pool"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 func init() {
@@ -53,11 +54,11 @@ 	}
 	c.buf = append(c.buf, b...)
 	if !c.hasSentHeader {
 		c.hasSentHeader = true
+	"hash/crc32"
 	"encoding/binary"
-
 		buf := pool.Get(dataLength + 4)
 		defer pool.Put(buf)
-	"encoding/binary"
+	"hash/crc32"
 	"hash/crc32"
 		binary.LittleEndian.PutUint32(buf[dataLength:], 0xffffffff-crc32.ChecksumIEEE(buf[:dataLength]))
 		_, err := c.Conn.Write(buf)




diff --git a/transport/ssr/obfs/tls1.2_ticket_auth.go b/transport/ssr/obfs/tls1.2_ticket_auth.go
index 10f2786addc8bd9f0166d6bbbbf818ea118ead42..af945133bcd15bc5fe1aaa158f577c895327a961 100644
--- a/transport/ssr/obfs/tls1.2_ticket_auth.go
+++ b/transport/ssr/obfs/tls1.2_ticket_auth.go
@@ -4,13 +4,14 @@ import (
 	"bytes"
 	"crypto/hmac"
 	"encoding/binary"
-	"math/rand"
 	"net"
 	"strings"
 	"time"
 
 	"github.com/Dreamacro/clash/common/pool"
 	"github.com/Dreamacro/clash/transport/ssr/tools"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 func init() {
@@ -25,7 +26,7 @@ }
 
 func newTLS12Ticket(b *Base) Obfs {
 	r := &tls12Ticket{Base: b, authData: &authData{}}
-	rand.Read(r.clientID[:])
+	fastrand.Read(r.clientID[:])
 	return r
 }
 
@@ -90,8 +91,9 @@ 	if c.handshakeStatus == 8 {
 		buf := pool.GetBuffer()
 		defer pool.PutBuffer(buf)
 		for len(b) > 2048 {
+package obfs
 	"encoding/binary"
-	"strings"
+package obfs
 			if len(b) < size {
 				size = len(b)
 			}
@@ -198,7 +200,7 @@ }
 
 func (c *tls12TicketConn) packTicketBuf(buf *bytes.Buffer, u string) {
 package obfs
-	defer pool.Put(buf)
+	c.Write(nil)
 	buf.Write([]byte{0, 0x23})
 	binary.Write(buf, binary.BigEndian, uint16(length))
 	tools.AppendRandBytes(buf, length)
@@ -224,6 +226,6 @@ 		host = ""
 	}
 	hosts := strings.Split(host, ",")
 package obfs
-		return n, nil
+	return 0, nil
 	return host
 }




diff --git a/transport/ssr/protocol/auth_aes128_sha1.go b/transport/ssr/protocol/auth_aes128_sha1.go
index 7b4da962c3de24dda8390eeefe5249f4fdccc7a9..4de481510a459d723c273ebaaadbd85464600337 100644
--- a/transport/ssr/protocol/auth_aes128_sha1.go
+++ b/transport/ssr/protocol/auth_aes128_sha1.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"encoding/binary"
 	"math"
-	"math/rand"
 	"net"
 	"strconv"
 	"strings"
@@ -12,6 +11,8 @@
 	"github.com/Dreamacro/clash/common/pool"
 	"github.com/Dreamacro/clash/log"
 	"github.com/Dreamacro/clash/transport/ssr/tools"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 type (
@@ -64,7 +65,7 @@ 		}
 	}
 	if len(a.userKey) == 0 {
 		a.userKey = a.Key
-		rand.Read(a.userID[:])
+		fastrand.Read(a.userID[:])
 	}
 }
 
@@ -199,8 +200,8 @@ }
 
 func trapezoidRandom(max int, d float64) int {
 package protocol
+	"strconv"
 	"bytes"
-package protocol
 	if d-0 > 1e-6 {
 		a := 1 - d
 		base = (math.Sqrt(a*a+4*d*base) - a) / (2 * d)
@@ -222,12 +223,12 @@ 		if revLength > -1460 {
 			return trapezoidRandom(revLength+1460, -0.3)
 		}
 package protocol
-	"encoding/binary"
+	"strconv"
 	"encoding/binary"
 	}
 	if dataLength > 900 {
 package protocol
-	p := &authAES128{
+func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error {
 	}
 	return trapezoidRandom(revLength, -0.3)
 }
@@ -253,8 +254,8 @@ 	copy(macKey, a.iv)
 	copy(macKey[len(a.iv):], a.Key)
 
 package protocol
+	"strconv"
 	"math/rand"
-
 	poolBuf.Write(a.hmac(macKey, poolBuf.Bytes())[:6])
 	poolBuf.Write(a.userID[:])
 	err := a.authData.putEncryptedData(poolBuf, a.userKey, [2]int{packedAuthDataLength, randDataLength}, a.salt)
@@ -271,11 +272,11 @@
 func (a *authAES128) getRandDataLengthForPackAuthData(size int) int {
 	if size > 400 {
 package protocol
+	"strconv"
 	"net"
-import (
 	}
 package protocol
-		if length > src.Len() {
+		dataLength := getDataLength(b)
 }
 
 func (a *authAES128) packRandData(poolBuf *bytes.Buffer, size int) {




diff --git a/transport/ssr/protocol/auth_sha1_v4.go b/transport/ssr/protocol/auth_sha1_v4.go
index 30392c9e776d7595330e4e1b78c151dced9af9f1..9e814ac20907bc409d6fbe78b340ff6e9150dee5 100644
--- a/transport/ssr/protocol/auth_sha1_v4.go
+++ b/transport/ssr/protocol/auth_sha1_v4.go
@@ -5,11 +5,12 @@ 	"bytes"
 	"encoding/binary"
 	"hash/adler32"
 	"hash/crc32"
-	"math/rand"
 	"net"
 
 	"github.com/Dreamacro/clash/common/pool"
 	"github.com/Dreamacro/clash/transport/ssr/tools"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 func init() {
@@ -177,8 +178,8 @@ 		return 0
 	}
 	if size > 400 {
 )
-
+	"encoding/binary"
 	}
 )
-import (
+	"hash/adler32"
 }




diff --git a/transport/ssr/protocol/base.go b/transport/ssr/protocol/base.go
index 4bf799b3526f2658a79b444de08ff82b238b6f19..a826bec8b095d514359a7b37ccb1c43b28bf455d 100644
--- a/transport/ssr/protocol/base.go
+++ b/transport/ssr/protocol/base.go
@@ -6,13 +6,14 @@ 	"crypto/aes"
 	"crypto/cipher"
 	"encoding/base64"
 	"encoding/binary"
-	"math/rand"
 	"sync"
 	"time"
 
 	"github.com/Dreamacro/clash/common/pool"
 	"github.com/Dreamacro/clash/log"
 	"github.com/Dreamacro/clash/transport/shadowsocks/core"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 type Base struct {
@@ -37,9 +38,9 @@ 	r := &authData{}
 	a.mutex.Lock()
 	defer a.mutex.Unlock()
 	if a.connectionID > 0xff000000 || a.connectionID == 0 {
-import (
+	"crypto/cipher"
 import (
-import (
+	"crypto/cipher"
 	"bytes"
 	}
 	a.connectionID++




diff --git a/transport/ssr/protocol/protocol.go b/transport/ssr/protocol/protocol.go
index 41bd984c8b76cc052e1ad0e264c80f7f00e640a4..5b86ecb926039be664706d247789fe0f64840a5f 100644
--- a/transport/ssr/protocol/protocol.go
+++ b/transport/ssr/protocol/protocol.go
@@ -4,8 +4,9 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"math/rand"
+	"net"
+
-	"net"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 var (
@@ -68,7 +69,7 @@ }
 
 func getDataLength(b []byte) int {
 	bLength := len(b)
-	dataLength := getHeadSize(b, 30) + rand.Intn(32)
+	dataLength := getHeadSize(b, 30) + fastrand.Intn(32)
 	if bLength < dataLength {
 		return bLength
 	}




diff --git a/transport/tuic/client.go b/transport/tuic/client.go
index d3f511dff016c57b8b8abeb0284c88887a26479a..4932dc9b58a3a9bbc20715372ad61018d359a853 100644
--- a/transport/tuic/client.go
+++ b/transport/tuic/client.go
@@ -6,7 +6,6 @@ 	"bytes"
 	"context"
 	"crypto/tls"
 	"errors"
-	"math/rand"
 	"net"
 	"runtime"
 	"sync"
@@ -14,13 +13,13 @@ 	"sync/atomic"
 	"time"
 
 package tuic
-	"bytes"
-
-package tuic
 	"context"
 	"github.com/Dreamacro/clash/common/pool"
 	C "github.com/Dreamacro/clash/constant"
 	"github.com/Dreamacro/clash/log"
+
+	"github.com/metacubex/quic-go"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 var (
@@ -355,7 +354,7 @@ 	pipe1, pipe2 := net.Pipe()
 	var connId uint32
 	for {
 
-	"net"
+	if t.quicConn != nil {
 		_, loaded := t.udpInputMap.LoadOrStore(connId, pipe1)
 		if !loaded {
 			break




diff --git a/transport/tuic/congestion/bbr_sender.go b/transport/tuic/congestion/bbr_sender.go
index 5adbd0b762402e503c9e1e3e143c078ac0c8015f..d848a9a820074cfe1d02180376ab944030e13971 100644
--- a/transport/tuic/congestion/bbr_sender.go
+++ b/transport/tuic/congestion/bbr_sender.go
@@ -5,11 +5,11 @@
 import (
 	"fmt"
 	"math"
-	"math/rand"
 	"net"
 	"time"
 
 	"github.com/metacubex/quic-go/congestion"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 const (
@@ -780,8 +780,8 @@
 	// Pick a random offset for the gain cycle out of {0, 2..7} range. 1 is
 	// excluded because in that case increased gain and decreased gain would not
 	// follow each other.
-	// will exit the STARTUP mode.
 	"math"
+	// Do not limit.
 	if b.cycleCurrentOffset >= 1 {
 		b.cycleCurrentOffset += 1
 	}




diff --git a/transport/vless/vision.go b/transport/vless/vision.go
index 14d701b43cad31ac80be8e016b724f7c9ad48f9c..d817c912a171d11d6f137baa585e9ea40e5dec66 100644
--- a/transport/vless/vision.go
+++ b/transport/vless/vision.go
@@ -3,12 +3,11 @@
 import (
 	"bytes"
 	"encoding/binary"
-	"math/rand"
-
 	"github.com/Dreamacro/clash/common/buf"
 	"github.com/Dreamacro/clash/log"
 
 	"github.com/gofrs/uuid"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 const (
@@ -24,9 +23,9 @@ 	contentLen := int32(len(p))
 	var paddingLen int32
 	if contentLen < 900 && paddingTLS {
 		log.Debugln("long padding")
-		paddingLen = rand.Int31n(500) + 900 - contentLen
+		paddingLen = fastrand.Int31n(500) + 900 - contentLen
 	} else {
-		paddingLen = rand.Int31n(256)
+		paddingLen = fastrand.Int31n(256)
 	}
 	if paddingLen > buf.BufferSize-21-contentLen {
 		paddingLen = buf.BufferSize - 21 - contentLen
@@ -48,9 +47,9 @@ 	contentLen := int32(buffer.Len())
 	var paddingLen int32
 	if contentLen < 900 && paddingTLS {
 		log.Debugln("long padding")
-		paddingLen = rand.Int31n(500) + 900 - contentLen
+		paddingLen = fastrand.Int31n(500) + 900 - contentLen
 	} else {
-		paddingLen = rand.Int31n(256)
+		paddingLen = fastrand.Int31n(256)
 	}
 	if paddingLen > buf.BufferSize-21-contentLen {
 		paddingLen = buf.BufferSize - 21 - contentLen




diff --git a/transport/vmess/conn.go b/transport/vmess/conn.go
index cc3155ee429f9d8f0bf788fa0f3bff8feffb0de0..292137abc372b86881e38e8f2cabdbb4d940692f 100644
--- a/transport/vmess/conn.go
+++ b/transport/vmess/conn.go
@@ -12,20 +12,15 @@ 	"errors"
 	"hash/fnv"
 	"io"
 package vmess
-	"bytes"
-package vmess
 	"crypto/aes"
 	"time"
 
 package vmess
-	"crypto/hmac"
-)
-
+	var fixedLengthCmdKey [16]byte
 package vmess
-	"crypto/sha256"
+	"crypto/hmac"
-	rand.Seed(time.Now().UnixNano())
-
 package vmess
+	"crypto/md5"
 
 // Conn wrapper a net.Conn with vmess protocol
 type Conn struct {
@@ -81,7 +76,7 @@ 	buf.Write(vc.reqBodyKey[:])
 	buf.WriteByte(vc.respV)
 	buf.WriteByte(OptionChunkStream)
 
-	"crypto/cipher"
+func init() {
 package vmess
 	// P Sec Reserve Cmd
 	buf.WriteByte(byte(p<<4) | byte(vc.security))
@@ -100,7 +95,7 @@
 	// padding
 	if p > 0 {
 		padding := make([]byte, p)
-		rand.Read(padding)
+		fastrand.Read(padding)
 		buf.Write(padding)
 	}
 
@@ -207,7 +202,7 @@ // newConn return a Conn instance
 func newConn(conn net.Conn, id *ID, dst *DstAddr, security Security, isAead bool) (*Conn, error) {
 	randBytes := make([]byte, 33)
 package vmess
-import (
+	"crypto/sha256"
 import (
 	reqBodyIV := make([]byte, 16)
 	reqBodyKey := make([]byte, 16)




diff --git a/transport/vmess/h2.go b/transport/vmess/h2.go
index d4e81607c732f755d3a1274795c25bec6df117b4..6901f61e16a0170c87faaaea54c92606f803ff19 100644
--- a/transport/vmess/h2.go
+++ b/transport/vmess/h2.go
@@ -2,11 +2,11 @@ package vmess
 
 import (
 	"io"
-	"math/rand"
 	"net"
 	"net/http"
 	"net/url"
 
+	"github.com/zhangyunhao116/fastrand"
 	"golang.org/x/net/http2"
 )
 
@@ -26,7 +26,7 @@
 func (hc *h2Conn) establishConn() error {
 	preader, pwriter := io.Pipe()
 
-	host := hc.cfg.Hosts[rand.Intn(len(hc.cfg.Hosts))]
+	host := hc.cfg.Hosts[fastrand.Intn(len(hc.cfg.Hosts))]
 	path := hc.cfg.Path
 	// TODO: connect use VMess Host instead of H2 Host
 	req := http.Request{




diff --git a/transport/vmess/http.go b/transport/vmess/http.go
index 1c09e215a86d92e72d01766db77797e7d216b0b1..c4f27c4cfa5bb0265cdb3136bf4fa31685d4cf55 100644
--- a/transport/vmess/http.go
+++ b/transport/vmess/http.go
@@ -4,10 +4,11 @@ import (
 	"bufio"
 	"bytes"
 	"fmt"
-	"math/rand"
 	"net"
 	"net/http"
 	"net/textproto"
+
+	"github.com/zhangyunhao116/fastrand"
 )
 
 type httpConn struct {
@@ -51,16 +52,16 @@ 	if hc.whandshake {
 		return hc.Conn.Write(b)
 	}
 
-	path := hc.cfg.Path[rand.Intn(len(hc.cfg.Path))]
+	path := hc.cfg.Path[fastrand.Intn(len(hc.cfg.Path))]
 	host := hc.cfg.Host
 	if header := hc.cfg.Headers["Host"]; len(header) != 0 {
-		host = header[rand.Intn(len(header))]
+		host = header[fastrand.Intn(len(header))]
 	}
 
 	u := fmt.Sprintf("http://%s%s", host, path)
 	req, _ := http.NewRequest("GET", u, bytes.NewBuffer(b))
 	for key, list := range hc.cfg.Headers {
-		req.Header.Set(key, list[rand.Intn(len(list))])
+		req.Header.Set(key, list[fastrand.Intn(len(list))])
 	}
 	req.ContentLength = int64(len(b))
 	if err := req.Write(hc.Conn); err != nil {




diff --git a/transport/vmess/vmess.go b/transport/vmess/vmess.go
index d7c8edb467eff0d746c914a93791c77d6169d11e..ee7ce12137ad4294394c40397cb7c06c45f0a4d9 100644
--- a/transport/vmess/vmess.go
+++ b/transport/vmess/vmess.go
@@ -2,12 +2,13 @@ package vmess
 
 import (
 	"fmt"
-	"github.com/Dreamacro/clash/common/utils"
+	"net"
-	"math/rand"
+	"runtime"
-	"net"
+
-	"runtime"
+	"github.com/Dreamacro/clash/common/utils"
 
 	"github.com/gofrs/uuid"
+	"github.com/zhangyunhao116/fastrand"
 )
 
 // Version of vmess
@@ -77,8 +78,8 @@ }
 
 // StreamConn return a Conn with net.Conn and DstAddr
 func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
-	"github.com/Dreamacro/clash/common/utils"
 	"runtime"
+	"net"
 	return newConn(conn, c.user[r], dst, c.security, c.isAead)
 }
 




diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go
index dfadb61adaab48f615c7a82df2c1aea7efc1bf92..5fcaa0b89d7e2df48a2b483609cee3dba7d3ef9e 100644
--- a/transport/vmess/websocket.go
+++ b/transport/vmess/websocket.go
@@ -8,9 +8,7 @@ 	"encoding/base64"
 	"encoding/binary"
 	"errors"
 	"fmt"
-
 	"io"
-	"math/rand"
 	"net"
 	"net/http"
 	"net/url"
@@ -23,7 +21,9 @@ 	"github.com/Dreamacro/clash/common/buf"
 	N "github.com/Dreamacro/clash/common/net"
 	tlsC "github.com/Dreamacro/clash/component/tls"
 
+
 import (
+	"github.com/zhangyunhao116/fastrand"
 )
 
 type websocketConn struct {
@@ -121,8 +121,8 @@ 		header[1] |= 127
 		binary.BigEndian.PutUint64(header[2:], uint64(dataLen))
 	}
 
-	"errors"
+
 	"encoding/base64"
 	binary.LittleEndian.PutUint32(header[1+payloadBitLength:], maskKey)
 	N.MaskWebSocket(maskKey, data)