mirror of https://github.com/v2ray/v2ray-core
				
				
				
			re-enable vmess test
							parent
							
								
									8f93612dec
								
							
						
					
					
						commit
						228e1eeabe
					
				| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
package hash
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CounterHash interface {
 | 
			
		||||
	Hash(key []byte, counter int64) []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StringHash interface {
 | 
			
		||||
	Hash(key []byte, data []byte) []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TimeHash struct {
 | 
			
		||||
	baseHash StringHash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewTimeHash(baseHash StringHash) CounterHash {
 | 
			
		||||
	return TimeHash{
 | 
			
		||||
		baseHash: baseHash,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h TimeHash) Hash(key []byte, counter int64) []byte {
 | 
			
		||||
	counterBytes := int64ToBytes(counter)
 | 
			
		||||
	return h.baseHash.Hash(key, counterBytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HMACHash struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h HMACHash) Hash(key []byte, data []byte) []byte {
 | 
			
		||||
	hash := hmac.New(md5.New, key)
 | 
			
		||||
	hash.Write(data)
 | 
			
		||||
	return hash.Sum(nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func int64ToBytes(value int64) []byte {
 | 
			
		||||
	return []byte{
 | 
			
		||||
		byte(value >> 56),
 | 
			
		||||
		byte(value >> 48),
 | 
			
		||||
		byte(value >> 40),
 | 
			
		||||
		byte(value >> 32),
 | 
			
		||||
		byte(value >> 24),
 | 
			
		||||
		byte(value >> 16),
 | 
			
		||||
		byte(value >> 8),
 | 
			
		||||
		byte(value),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
package hash
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Int64Hash(value int64) []byte {
 | 
			
		||||
	md5hash := md5.New()
 | 
			
		||||
	buffer := int64ToBytes(value)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	return md5hash.Sum(nil)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								id.go
								
								
								
								
							
							
						
						
									
										56
									
								
								id.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,11 +1,8 @@
 | 
			
		|||
package core
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	mrand "math/rand"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/v2ray/v2ray-core/log"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -32,60 +29,17 @@ func NewID(id string) (ID, error) {
 | 
			
		|||
	md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21"))
 | 
			
		||||
	cmdKey := md5.Sum(nil)
 | 
			
		||||
 | 
			
		||||
	return ID{id, idBytes, cmdKey[:]}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v ID) TimeRangeHash(rangeSec int) ([]byte, int64) {
 | 
			
		||||
	nowSec := time.Now().UTC().Unix()
 | 
			
		||||
	delta := mrand.Intn(rangeSec*2) - rangeSec
 | 
			
		||||
 | 
			
		||||
	targetSec := nowSec + int64(delta)
 | 
			
		||||
	return v.TimeHash(targetSec), targetSec
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v ID) TimeHash(timeSec int64) []byte {
 | 
			
		||||
	buffer := []byte{
 | 
			
		||||
		byte(timeSec >> 56),
 | 
			
		||||
		byte(timeSec >> 48),
 | 
			
		||||
		byte(timeSec >> 40),
 | 
			
		||||
		byte(timeSec >> 32),
 | 
			
		||||
		byte(timeSec >> 24),
 | 
			
		||||
		byte(timeSec >> 16),
 | 
			
		||||
		byte(timeSec >> 8),
 | 
			
		||||
		byte(timeSec),
 | 
			
		||||
	}
 | 
			
		||||
	return v.Hash(buffer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v ID) Hash(data []byte) []byte {
 | 
			
		||||
	hasher := hmac.New(md5.New, v.Bytes)
 | 
			
		||||
	hasher.Write(data)
 | 
			
		||||
	return hasher.Sum(nil)
 | 
			
		||||
	return ID{
 | 
			
		||||
		String: id,
 | 
			
		||||
		Bytes:  idBytes,
 | 
			
		||||
		cmdKey: cmdKey[:],
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v ID) CmdKey() []byte {
 | 
			
		||||
	return v.cmdKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TimestampHash(timeSec int64) []byte {
 | 
			
		||||
	md5hash := md5.New()
 | 
			
		||||
	buffer := []byte{
 | 
			
		||||
		byte(timeSec >> 56),
 | 
			
		||||
		byte(timeSec >> 48),
 | 
			
		||||
		byte(timeSec >> 40),
 | 
			
		||||
		byte(timeSec >> 32),
 | 
			
		||||
		byte(timeSec >> 24),
 | 
			
		||||
		byte(timeSec >> 16),
 | 
			
		||||
		byte(timeSec >> 8),
 | 
			
		||||
		byte(timeSec),
 | 
			
		||||
	}
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	md5hash.Write(buffer)
 | 
			
		||||
	return md5hash.Sum(nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var byteGroups = []int{8, 4, 4, 4, 12}
 | 
			
		||||
 | 
			
		||||
// TODO: leverage a full functional UUID library
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ func TestAuthenticationResponseWrite(t *testing.T) {
 | 
			
		|||
	response := NewAuthenticationResponse(byte(0x05))
 | 
			
		||||
 | 
			
		||||
	buffer := bytes.NewBuffer(make([]byte, 0, 10))
 | 
			
		||||
	WriteAuthentication(buffer, &response)
 | 
			
		||||
	WriteAuthentication(buffer, response)
 | 
			
		||||
	assert.Bytes(buffer.Bytes()).Equals([]byte{socksVersion, byte(0x05)})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
package socks
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Socks5UDPRequest struct {
 | 
			
		||||
	fragment byte
 | 
			
		||||
	address  v2net.Address
 | 
			
		||||
	data     []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReadUDPRequest(reader io.Reader) (request Socks5UDPRequest, err error) {
 | 
			
		||||
	//buf := make([]byte, 4 * 1024) // Regular UDP packet size is 1500 bytes.
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,10 +10,13 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	mrand "math/rand"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/v2ray/v2ray-core"
 | 
			
		||||
	v2hash "github.com/v2ray/v2ray-core/hash"
 | 
			
		||||
	v2io "github.com/v2ray/v2ray-core/io"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/log"
 | 
			
		||||
	v2math "github.com/v2ray/v2ray-core/math"
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +60,6 @@ func NewVMessRequestReader(vUserSet core.UserSet) *VMessRequestReader {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
 | 
			
		||||
 | 
			
		||||
	buffer := make([]byte, 256)
 | 
			
		||||
 | 
			
		||||
	nBytes, err := reader.Read(buffer[:core.IDBytesLen])
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +78,7 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	aesStream := cipher.NewCFBDecrypter(aesCipher, core.TimestampHash(timeSec))
 | 
			
		||||
	aesStream := cipher.NewCFBDecrypter(aesCipher, v2hash.Int64Hash(timeSec))
 | 
			
		||||
	decryptor := v2io.NewCryptionReader(aesStream, reader)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -180,18 +182,25 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
type VMessRequestWriter struct {
 | 
			
		||||
	idHash           v2hash.CounterHash
 | 
			
		||||
	randomRangeInt64 v2math.RandomInt64InRange
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewVMessRequestWriter() *VMessRequestWriter {
 | 
			
		||||
	return &VMessRequestWriter{}
 | 
			
		||||
func NewVMessRequestWriter(idHash v2hash.CounterHash, randomRangeInt64 v2math.RandomInt64InRange) *VMessRequestWriter {
 | 
			
		||||
	return &VMessRequestWriter{
 | 
			
		||||
		idHash:           idHash,
 | 
			
		||||
		randomRangeInt64: randomRangeInt64,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *VMessRequestWriter) Write(writer io.Writer, request *VMessRequest) error {
 | 
			
		||||
	buffer := make([]byte, 0, 300)
 | 
			
		||||
	userHash, timeSec := request.UserId.TimeRangeHash(30)
 | 
			
		||||
 | 
			
		||||
	log.Debug("Writing userhash: %v", userHash)
 | 
			
		||||
	buffer = append(buffer, userHash...)
 | 
			
		||||
	counter := w.randomRangeInt64(time.Now().UTC().Unix(), 30)
 | 
			
		||||
	idHash := w.idHash.Hash(request.UserId.Bytes, counter)
 | 
			
		||||
 | 
			
		||||
	log.Debug("Writing userhash: %v", idHash)
 | 
			
		||||
	buffer = append(buffer, idHash...)
 | 
			
		||||
 | 
			
		||||
	encryptionBegin := len(buffer)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -241,7 +250,7 @@ func (w *VMessRequestWriter) Write(writer io.Writer, request *VMessRequest) erro
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	aesStream := cipher.NewCFBEncrypter(aesCipher, core.TimestampHash(timeSec))
 | 
			
		||||
	aesStream := cipher.NewCFBEncrypter(aesCipher, v2hash.Int64Hash(counter))
 | 
			
		||||
	cWriter := v2io.NewCryptionWriter(aesStream, writer)
 | 
			
		||||
 | 
			
		||||
	_, err = writer.Write(buffer[0:encryptionBegin])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,13 +7,14 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/v2ray/v2ray-core"
 | 
			
		||||
	v2hash "github.com/v2ray/v2ray-core/hash"
 | 
			
		||||
	v2math "github.com/v2ray/v2ray-core/math"
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/net"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/testing/mocks"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/testing/unit"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestVMessSerialization(t *testing.T) {
 | 
			
		||||
	t.Skip()
 | 
			
		||||
	assert := unit.Assert(t)
 | 
			
		||||
 | 
			
		||||
	userId, err := core.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51")
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +22,7 @@ func TestVMessSerialization(t *testing.T) {
 | 
			
		|||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int)}
 | 
			
		||||
	userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int), make(map[string]int64)}
 | 
			
		||||
	userSet.AddUser(core.User{userId})
 | 
			
		||||
 | 
			
		||||
	request := new(VMessRequest)
 | 
			
		||||
| 
						 | 
				
			
			@ -47,13 +48,15 @@ func TestVMessSerialization(t *testing.T) {
 | 
			
		|||
	request.Address = v2net.DomainAddress("v2ray.com", 80)
 | 
			
		||||
 | 
			
		||||
	buffer := bytes.NewBuffer(make([]byte, 0, 300))
 | 
			
		||||
	requestWriter := NewVMessRequestWriter()
 | 
			
		||||
	mockTime := int64(1823730)
 | 
			
		||||
	requestWriter := NewVMessRequestWriter(v2hash.NewTimeHash(v2hash.HMACHash{}), func(base int64, delta int) int64 { return mockTime })
 | 
			
		||||
	err = requestWriter.Write(buffer, request)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userSet.UserHashes[string(buffer.Bytes()[:16])] = 0
 | 
			
		||||
	userSet.Timestamps[string(buffer.Bytes()[:16])] = mockTime
 | 
			
		||||
 | 
			
		||||
	requestReader := NewVMessRequestReader(&userSet)
 | 
			
		||||
	actualRequest, err := requestReader.Read(buffer)
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +75,7 @@ func TestVMessSerialization(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
func BenchmarkVMessRequestWriting(b *testing.B) {
 | 
			
		||||
	userId, _ := core.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51")
 | 
			
		||||
	userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int)}
 | 
			
		||||
	userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int), make(map[string]int64)}
 | 
			
		||||
	userSet.AddUser(core.User{userId})
 | 
			
		||||
 | 
			
		||||
	request := new(VMessRequest)
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +89,7 @@ func BenchmarkVMessRequestWriting(b *testing.B) {
 | 
			
		|||
	request.Command = byte(0x01)
 | 
			
		||||
	request.Address = v2net.DomainAddress("v2ray.com", 80)
 | 
			
		||||
 | 
			
		||||
	requestWriter := NewVMessRequestWriter()
 | 
			
		||||
	requestWriter := NewVMessRequestWriter(v2hash.NewTimeHash(v2hash.HMACHash{}), v2math.GenerateRandomInt64InRange)
 | 
			
		||||
	for i := 0; i < b.N; i++ {
 | 
			
		||||
		requestWriter.Write(ioutil.Discard, request)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
package math
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math/rand"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type RandomInt64InRange func(base int64, delta int) int64
 | 
			
		||||
 | 
			
		||||
func GenerateRandomInt64InRange(base int64, delta int) int64 {
 | 
			
		||||
	rangeInDelta := rand.Intn(delta*2) - delta
 | 
			
		||||
	return base + int64(rangeInDelta)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,9 +7,11 @@ import (
 | 
			
		|||
	"net"
 | 
			
		||||
 | 
			
		||||
	"github.com/v2ray/v2ray-core"
 | 
			
		||||
	v2hash "github.com/v2ray/v2ray-core/hash"
 | 
			
		||||
	v2io "github.com/v2ray/v2ray-core/io"
 | 
			
		||||
	vmessio "github.com/v2ray/v2ray-core/io/vmess"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/log"
 | 
			
		||||
	v2math "github.com/v2ray/v2ray-core/math"
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +96,7 @@ func startCommunicate(request *vmessio.VMessRequest, dest v2net.Address, ray cor
 | 
			
		|||
 | 
			
		||||
func handleRequest(conn *net.TCPConn, request *vmessio.VMessRequest, input <-chan []byte, finish chan<- bool) error {
 | 
			
		||||
	defer close(finish)
 | 
			
		||||
	requestWriter := vmessio.NewVMessRequestWriter()
 | 
			
		||||
	requestWriter := vmessio.NewVMessRequestWriter(v2hash.NewTimeHash(v2hash.HMACHash{}), v2math.GenerateRandomInt64InRange)
 | 
			
		||||
	err := requestWriter.Write(conn, request)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("Failed to write VMess request: %v", err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
type MockUserSet struct {
 | 
			
		||||
	UserIds    []core.ID
 | 
			
		||||
	UserHashes map[string]int
 | 
			
		||||
	Timestamps map[string]int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (us *MockUserSet) AddUser(user core.User) error {
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +18,7 @@ func (us *MockUserSet) AddUser(user core.User) error {
 | 
			
		|||
func (us *MockUserSet) GetUser(userhash []byte) (*core.ID, int64, bool) {
 | 
			
		||||
	idx, found := us.UserHashes[string(userhash)]
 | 
			
		||||
	if found {
 | 
			
		||||
		return &us.UserIds[idx], 1234, true
 | 
			
		||||
		return &us.UserIds[idx], us.Timestamps[string(userhash)], true
 | 
			
		||||
	}
 | 
			
		||||
	return nil, 0, false
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@ package core
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	v2hash "github.com/v2ray/v2ray-core/hash"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +46,7 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
 | 
			
		|||
 | 
			
		||||
	hash2Remove := make(chan hashEntry, cacheDurationSec*3*len(us.validUserIds))
 | 
			
		||||
	lastSec2Remove := now.Unix()
 | 
			
		||||
	idHash := v2hash.NewTimeHash(v2hash.HMACHash{})
 | 
			
		||||
	for {
 | 
			
		||||
		now := <-tick
 | 
			
		||||
		nowSec := now.UTC().Unix()
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +62,7 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
 | 
			
		|||
 | 
			
		||||
		for lastSec < nowSec+cacheDurationSec {
 | 
			
		||||
			for idx, id := range us.validUserIds {
 | 
			
		||||
				idHash := id.TimeHash(lastSec)
 | 
			
		||||
				idHash := idHash.Hash(id.Bytes, lastSec)
 | 
			
		||||
				hash2Remove <- hashEntry{string(idHash), lastSec}
 | 
			
		||||
				us.userHashes[string(idHash)] = indexTimePair{idx, lastSec}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue