令vmess可用,已经过验证,添加vmess.client.toml配置文件

This commit is contained in:
e1732a364fed
2000-01-01 00:00:00 +00:00
parent 3dcefdd4f8
commit a534b46efb
6 changed files with 248 additions and 51 deletions

View File

@@ -0,0 +1,12 @@
[[listen]]
protocol = "socks5"
host = "127.0.0.1"
port = 10800
[[dial]]
protocol = "vmess"
uuid = "a684455c-b14f-11ea-bf0d-42010aaa0003"
host = "127.0.0.1"
port = 4434
extra = { vmess_security = "aes-128-gcm" }

View File

@@ -29,6 +29,7 @@ import (
_ "github.com/e1732a364fed/v2ray_simple/proxy/socks5http"
_ "github.com/e1732a364fed/v2ray_simple/proxy/trojan"
_ "github.com/e1732a364fed/v2ray_simple/proxy/vless"
_ "github.com/e1732a364fed/v2ray_simple/proxy/vmess"
)
//statistics

View File

@@ -3,8 +3,8 @@ package vmess
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/md5"
"crypto/sha256"
"encoding/binary"
"errors"
"hash/fnv"
@@ -67,6 +67,7 @@ func (ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) {
if err = c.specifySecurityByStr(str); err != nil {
return nil, err
}
}
}
}
@@ -121,20 +122,28 @@ func (c *Client) commonHandshake(underlay net.Conn, firstPayload []byte, target
conn.addr, conn.atyp = target.AddressBytes()
conn.port = uint16(target.Port)
randBytes := utils.GetBytes(32)
randBytes := utils.GetBytes(33)
rand.Read(randBytes)
copy(conn.reqBodyIV[:], randBytes[:16])
copy(conn.reqBodyKey[:], randBytes[16:32])
utils.PutBytes(randBytes)
conn.reqRespV = byte(rand.Intn(1 << 8))
conn.respBodyIV = md5.Sum(conn.reqBodyIV[:])
conn.respBodyKey = md5.Sum(conn.reqBodyKey[:])
conn.reqRespV = randBytes[32]
//non-aead
//conn.respBodyIV = md5.Sum(conn.reqBodyIV[:])
//conn.respBodyKey = md5.Sum(conn.reqBodyKey[:])
bodyKey := sha256.Sum256(conn.reqBodyKey[:])
bodyIV := sha256.Sum256(conn.reqBodyIV[:])
copy(conn.respBodyKey[:], bodyKey[:16])
copy(conn.respBodyIV[:], bodyIV[:16])
// Auth
err := conn.auth()
if err != nil {
return nil, err
}
//err := conn.non_aead_auth()
//if err != nil {
// return nil, err
//}
var err error
// Request
if target.IsUDP() {
@@ -145,11 +154,15 @@ func (c *Client) commonHandshake(underlay net.Conn, firstPayload []byte, target
err = conn.handshake(CmdTCP)
}
if err != nil {
return nil, err
}
if len(firstPayload) > 0 {
_, err = conn.Write(firstPayload)
}
return conn, nil
return conn, err
}
// ClientConn is a connection to vmess server
@@ -188,7 +201,7 @@ func (c *ClientConn) Fullcone() bool {
func (c *ClientConn) ReadMsgFrom() (bs []byte, target netLayer.Addr, err error) {
bs = utils.GetPacket()
var n int
n, err = c.Conn.Read(bs)
n, err = c.Read(bs)
if err != nil {
utils.PutPacket(bs)
bs = nil
@@ -204,20 +217,6 @@ func (c *ClientConn) WriteMsgTo(b []byte, _ netLayer.Addr) error {
return e
}
// send auth info: HMAC("md5", UUID, UTC)
func (c *ClientConn) auth() error {
ts := utils.GetBytes(8)
defer utils.PutBytes(ts)
binary.BigEndian.PutUint64(ts, uint64(time.Now().UTC().Unix()))
h := hmac.New(md5.New, c.user.IdentityBytes())
h.Write(ts)
_, err := c.Conn.Write(h.Sum(nil))
return err
}
// handshake sends request to server.
func (c *ClientConn) handshake(cmd byte) error {
buf := utils.GetBuf()
@@ -264,45 +263,68 @@ func (c *ClientConn) handshake(cmd byte) error {
buf.Write(fnv1a.Sum(nil))
// log.Printf("Request Send %v", buf.Bytes())
/*
//non-aead procedure
block, err := aes.NewCipher(GetKey(c.user))
if err != nil {
return err
}
block, err := aes.NewCipher(GetKey(c.user))
if err != nil {
return err
}
stream := cipher.NewCFBEncrypter(block, TimestampHash(time.Now().UTC().Unix()))
stream.XORKeyStream(buf.Bytes(), buf.Bytes())
_, err = c.Conn.Write(buf.Bytes())
stream := cipher.NewCFBEncrypter(block, TimestampHash(time.Now().UTC().Unix()))
stream.XORKeyStream(buf.Bytes(), buf.Bytes())
*/
var fixedLengthCmdKey [16]byte
copy(fixedLengthCmdKey[:], GetKey(c.user))
vmessout := sealVMessAEADHeader(fixedLengthCmdKey, buf.Bytes(), time.Now())
_, err = c.Conn.Write(vmessout)
return err
}
// DecodeRespHeader decodes response header.
func (c *ClientConn) DecodeRespHeader() error {
block, err := aes.NewCipher(c.respBodyKey[:])
func (vc *ClientConn) aead_decodeRespHeader() error {
var buf []byte
aeadResponseHeaderLengthEncryptionKey := kdf(vc.respBodyKey[:], kdfSaltConstAEADRespHeaderLenKey)[:16]
aeadResponseHeaderLengthEncryptionIV := kdf(vc.respBodyIV[:], kdfSaltConstAEADRespHeaderLenIV)[:12]
aeadResponseHeaderLengthEncryptionKeyAESBlock, _ := aes.NewCipher(aeadResponseHeaderLengthEncryptionKey)
aeadResponseHeaderLengthEncryptionAEAD, _ := cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock)
aeadEncryptedResponseHeaderLength := make([]byte, 18)
if _, err := io.ReadFull(vc.Conn, aeadEncryptedResponseHeaderLength); err != nil {
return err
}
decryptedResponseHeaderLengthBinaryBuffer, err := aeadResponseHeaderLengthEncryptionAEAD.Open(nil, aeadResponseHeaderLengthEncryptionIV, aeadEncryptedResponseHeaderLength[:], nil)
if err != nil {
return err
}
decryptedResponseHeaderLength := binary.BigEndian.Uint16(decryptedResponseHeaderLengthBinaryBuffer)
aeadResponseHeaderPayloadEncryptionKey := kdf(vc.respBodyKey[:], kdfSaltConstAEADRespHeaderPayloadKey)[:16]
aeadResponseHeaderPayloadEncryptionIV := kdf(vc.respBodyIV[:], kdfSaltConstAEADRespHeaderPayloadIV)[:12]
aeadResponseHeaderPayloadEncryptionKeyAESBlock, _ := aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey)
aeadResponseHeaderPayloadEncryptionAEAD, _ := cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock)
encryptedResponseHeaderBuffer := make([]byte, decryptedResponseHeaderLength+16)
if _, err := io.ReadFull(vc.Conn, encryptedResponseHeaderBuffer); err != nil {
return err
}
buf, err = aeadResponseHeaderPayloadEncryptionAEAD.Open(nil, aeadResponseHeaderPayloadEncryptionIV, encryptedResponseHeaderBuffer, nil)
if err != nil {
return err
}
stream := cipher.NewCFBDecrypter(block, c.respBodyIV[:])
b := utils.GetBytes(4)
defer utils.PutBytes(b)
_, err = io.ReadFull(c.Conn, b)
if err != nil {
return err
if len(buf) < 4 {
return errors.New("unexpected buffer length")
}
stream.XORKeyStream(b, b)
if b[0] != c.reqRespV {
if buf[0] != vc.reqRespV {
return errors.New("unexpected response header")
}
if b[2] != 0 {
// dataLen := int32(buf[3])
if buf[2] != 0 {
return errors.New("dynamic port is not supported now")
}
@@ -345,7 +367,8 @@ func (c *ClientConn) Read(b []byte) (n int, err error) {
return c.dataReader.Read(b)
}
err = c.DecodeRespHeader()
err = c.aead_decodeRespHeader()
if err != nil {
return 0, err
}

58
proxy/vmess/deprecated.go Normal file
View File

@@ -0,0 +1,58 @@
package vmess
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/md5"
"encoding/binary"
"errors"
"io"
"time"
"github.com/e1732a364fed/v2ray_simple/utils"
)
//Deprecated: send non_aead_auth info: HMAC("md5", UUID, UTC)
func (c *ClientConn) non_aead_auth() error {
ts := utils.GetBytes(8)
defer utils.PutBytes(ts)
binary.BigEndian.PutUint64(ts, uint64(time.Now().UTC().Unix()))
h := hmac.New(md5.New, c.user.IdentityBytes())
h.Write(ts)
_, err := c.Conn.Write(h.Sum(nil))
return err
}
//Deprecated: non_aead is depreated
func (c *ClientConn) non_aead_decodeRespHeader() error {
block, err := aes.NewCipher(c.respBodyKey[:])
if err != nil {
return err
}
stream := cipher.NewCFBDecrypter(block, c.respBodyIV[:])
b := utils.GetBytes(4)
defer utils.PutBytes(b)
_, err = io.ReadFull(c.Conn, b)
if err != nil {
return err
}
stream.XORKeyStream(b, b)
if b[0] != c.reqRespV {
return errors.New("unexpected response header")
}
if b[2] != 0 {
return errors.New("dynamic port is not supported now")
}
return nil
}

103
proxy/vmess/header.go Normal file
View File

@@ -0,0 +1,103 @@
package vmess
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"hash"
"hash/crc32"
"time"
)
const (
kdfSaltConstAuthIDEncryptionKey = "AES Auth ID Encryption"
kdfSaltConstAEADRespHeaderLenKey = "AEAD Resp Header Len Key"
kdfSaltConstAEADRespHeaderLenIV = "AEAD Resp Header Len IV"
kdfSaltConstAEADRespHeaderPayloadKey = "AEAD Resp Header Key"
kdfSaltConstAEADRespHeaderPayloadIV = "AEAD Resp Header IV"
kdfSaltConstVMessAEADKDF = "VMess AEAD KDF"
kdfSaltConstVMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
kdfSaltConstVMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
kdfSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
kdfSaltConstVMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"
)
func kdf(key []byte, path ...string) []byte {
hmacCreator := &hMacCreator{value: []byte(kdfSaltConstVMessAEADKDF)}
for _, v := range path {
hmacCreator = &hMacCreator{value: []byte(v), parent: hmacCreator}
}
hmacf := hmacCreator.Create()
hmacf.Write(key)
return hmacf.Sum(nil)
}
type hMacCreator struct {
parent *hMacCreator
value []byte
}
func (h *hMacCreator) Create() hash.Hash {
if h.parent == nil {
return hmac.New(sha256.New, h.value)
}
return hmac.New(h.parent.Create, h.value)
}
func createAuthID(cmdKey []byte, time int64) [16]byte {
buf := &bytes.Buffer{}
binary.Write(buf, binary.BigEndian, time)
random := make([]byte, 4)
rand.Read(random)
buf.Write(random)
zero := crc32.ChecksumIEEE(buf.Bytes())
binary.Write(buf, binary.BigEndian, zero)
aesBlock, _ := aes.NewCipher(kdf(cmdKey[:], kdfSaltConstAuthIDEncryptionKey)[:16])
var result [16]byte
aesBlock.Encrypt(result[:], buf.Bytes())
return result
}
func sealVMessAEADHeader(key [16]byte, data []byte, t time.Time) []byte {
generatedAuthID := createAuthID(key[:], t.Unix())
connectionNonce := make([]byte, 8)
rand.Read(connectionNonce)
aeadPayloadLengthSerializedByte := make([]byte, 2)
binary.BigEndian.PutUint16(aeadPayloadLengthSerializedByte, uint16(len(data)))
var payloadHeaderLengthAEADEncrypted []byte
{
payloadHeaderLengthAEADKey := kdf(key[:], kdfSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))[:16]
payloadHeaderLengthAEADNonce := kdf(key[:], kdfSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
payloadHeaderLengthAEADAESBlock, _ := aes.NewCipher(payloadHeaderLengthAEADKey)
payloadHeaderAEAD, _ := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
}
var payloadHeaderAEADEncrypted []byte
{
payloadHeaderAEADKey := kdf(key[:], kdfSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))[:16]
payloadHeaderAEADNonce := kdf(key[:], kdfSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
payloadHeaderAEADAESBlock, _ := aes.NewCipher(payloadHeaderAEADKey)
payloadHeaderAEAD, _ := cipher.NewGCM(payloadHeaderAEADAESBlock)
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
}
outputBuffer := &bytes.Buffer{}
outputBuffer.Write(generatedAuthID[:])
outputBuffer.Write(payloadHeaderLengthAEADEncrypted)
outputBuffer.Write(connectionNonce)
outputBuffer.Write(payloadHeaderAEADEncrypted)
return outputBuffer.Bytes()
}

View File

@@ -1,5 +1,5 @@
/*
Package tlsLayer provides facilities for tls, including sniffing.
Package tlsLayer provides facilities for tls, including uTls, sniffing and random certificate.
*/
package tlsLayer