1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-30 05:56:54 -05:00

re-enable vmess test

This commit is contained in:
V2Ray 2015-09-16 21:13:13 +02:00
parent 8f93612dec
commit 228e1eeabe
11 changed files with 137 additions and 68 deletions

51
hash/id.go Normal file
View File

@ -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),
}
}

15
hash/int.go Normal file
View File

@ -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
View File

@ -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

View File

@ -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)})
}

19
io/socks/udp.go Normal file
View File

@ -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
}

View File

@ -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])

View File

@ -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)
}

12
math/rand.go Normal file
View File

@ -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)
}

View File

@ -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)

View File

@ -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
}

View File

@ -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}
}