Jelajahi Sumber

Fix IPv6 random IP logic error (#3232)

* Update handler.go

fix CIDR6

* Update handler.go
Aubrey Yang 1 tahun lalu
induk
melakukan
8374d59ce6
1 mengubah file dengan 19 tambahan dan 14 penghapusan
  1. 19 14
      app/proxyman/outbound/handler.go

+ 19 - 14
app/proxyman/outbound/handler.go

@@ -2,12 +2,8 @@ package outbound
 
 import (
 	"context"
+	"crypto/rand"
 	"errors"
-	"io"
-	"math/rand"
-	gonet "net"
-	"os"
-
 	"github.com/xtls/xray-core/app/proxyman"
 	"github.com/xtls/xray-core/common"
 	"github.com/xtls/xray-core/common/buf"
@@ -25,6 +21,10 @@ import (
 	"github.com/xtls/xray-core/transport/internet/stat"
 	"github.com/xtls/xray-core/transport/internet/tls"
 	"github.com/xtls/xray-core/transport/pipe"
+	"io"
+	"math/big"
+	gonet "net"
+	"os"
 )
 
 func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
@@ -319,16 +319,21 @@ func (h *Handler) Close() error {
 	return nil
 }
 
-// Return random IPv6 in a CIDR block
+
 func ParseRandomIPv6(address net.Address, prefix string) net.Address {
-	addr := address.IP().String()
-	_, network, _ := gonet.ParseCIDR(addr + "/" + prefix)
+	_, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix)
 
-	ipv6 := network.IP.To16()
-	prefixLen, _ := network.Mask.Size()
-	for i := prefixLen / 8; i < 16; i++ {
-		ipv6[i] = byte(rand.Intn(256))
-	}
+	maskSize, totalBits := network.Mask.Size()
+	subnetSize := big.NewInt(1).Lsh(big.NewInt(1), uint(totalBits-maskSize))
+
+	// random
+	randomBigInt, _ := rand.Int(rand.Reader, subnetSize)
+
+	startIPBigInt := big.NewInt(0).SetBytes(network.IP.To16())
+	randomIPBigInt := big.NewInt(0).Add(startIPBigInt, randomBigInt)
+
+	randomIPBytes := randomIPBigInt.Bytes()
+	randomIPBytes = append(make([]byte, 16-len(randomIPBytes)), randomIPBytes...)
 
-	return net.ParseAddress(gonet.IP(ipv6).String())
+	return net.ParseAddress(gonet.IP(randomIPBytes).String())
 }