mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-30 05:56:54 -05:00
Version 1.0 alpha
This commit is contained in:
parent
f3a12e9f57
commit
cc3fdb6ef4
@ -12,8 +12,8 @@ func NewAesDecryptReader(key []byte, iv []byte, reader io.Reader) (io.Reader, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aesMode := cipher.NewCBCDecrypter(aesBlock, iv)
|
||||
return NewCryptionReader(aesMode, reader), nil
|
||||
aesStream := cipher.NewCFBDecrypter(aesBlock, iv)
|
||||
return NewCryptionReader(aesStream, reader), nil
|
||||
}
|
||||
|
||||
func NewAesEncryptWriter(key []byte, iv []byte, writer io.Writer) (io.Writer, error) {
|
||||
@ -22,6 +22,6 @@ func NewAesEncryptWriter(key []byte, iv []byte, writer io.Writer) (io.Writer, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aesMode := cipher.NewCBCEncrypter(aesBlock, iv)
|
||||
return NewCryptionWriter(aesMode, writer), nil
|
||||
aesStream := cipher.NewCFBEncrypter(aesBlock, iv)
|
||||
return NewCryptionWriter(aesStream, writer), nil
|
||||
}
|
||||
|
@ -3,18 +3,20 @@ package io
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"io"
|
||||
|
||||
"github.com/v2ray/v2ray-core/log"
|
||||
)
|
||||
|
||||
// CryptionReader is a general purpose reader that applies
|
||||
// block cipher on top of a regular reader.
|
||||
type CryptionReader struct {
|
||||
mode cipher.BlockMode
|
||||
stream cipher.Stream
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
func NewCryptionReader(mode cipher.BlockMode, reader io.Reader) *CryptionReader {
|
||||
func NewCryptionReader(stream cipher.Stream, reader io.Reader) *CryptionReader {
|
||||
this := new(CryptionReader)
|
||||
this.mode = mode
|
||||
this.stream = stream
|
||||
this.reader = reader
|
||||
return this
|
||||
}
|
||||
@ -23,32 +25,26 @@ func NewCryptionReader(mode cipher.BlockMode, reader io.Reader) *CryptionReader
|
||||
// a multiply of BlockSize()
|
||||
func (reader CryptionReader) Read(blocks []byte) (int, error) {
|
||||
nBytes, err := reader.reader.Read(blocks)
|
||||
if err != nil && err != io.EOF {
|
||||
return nBytes, err
|
||||
log.Debug("CryptionReader: Read %d bytes", nBytes)
|
||||
if nBytes > 0 {
|
||||
reader.stream.XORKeyStream(blocks[:nBytes], blocks[:nBytes])
|
||||
}
|
||||
if nBytes < len(blocks) {
|
||||
for i, _ := range blocks[nBytes:] {
|
||||
blocks[i] = 0
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Error reading blocks: %v", err)
|
||||
}
|
||||
reader.mode.CryptBlocks(blocks, blocks)
|
||||
return nBytes, err
|
||||
}
|
||||
|
||||
func (reader CryptionReader) BlockSize() int {
|
||||
return reader.mode.BlockSize()
|
||||
}
|
||||
|
||||
// Cryption writer is a general purpose of byte stream writer that applies
|
||||
// block cipher on top of a regular writer.
|
||||
type CryptionWriter struct {
|
||||
mode cipher.BlockMode
|
||||
stream cipher.Stream
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
func NewCryptionWriter(mode cipher.BlockMode, writer io.Writer) *CryptionWriter {
|
||||
func NewCryptionWriter(stream cipher.Stream, writer io.Writer) *CryptionWriter {
|
||||
this := new(CryptionWriter)
|
||||
this.mode = mode
|
||||
this.stream = stream
|
||||
this.writer = writer
|
||||
return this
|
||||
}
|
||||
@ -56,10 +52,7 @@ func NewCryptionWriter(mode cipher.BlockMode, writer io.Writer) *CryptionWriter
|
||||
// Write writes the give blocks to underlying writer. The length of the blocks
|
||||
// must be a multiply of BlockSize()
|
||||
func (writer CryptionWriter) Write(blocks []byte) (int, error) {
|
||||
writer.mode.CryptBlocks(blocks, blocks)
|
||||
log.Debug("CryptionWriter writing %d bytes", len(blocks))
|
||||
writer.stream.XORKeyStream(blocks, blocks)
|
||||
return writer.writer.Write(blocks)
|
||||
}
|
||||
|
||||
func (writer CryptionWriter) BlockSize() int {
|
||||
return writer.mode.BlockSize()
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ func NewDecryptionReader(reader io.Reader, key []byte, iv []byte) (*DecryptionRe
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aesBlockMode := cipher.NewCBCDecrypter(aesCipher, iv)
|
||||
decryptionReader.reader = v2io.NewCryptionReader(aesBlockMode, reader)
|
||||
aesStream := cipher.NewCFBDecrypter(aesCipher, iv)
|
||||
decryptionReader.reader = v2io.NewCryptionReader(aesStream, reader)
|
||||
decryptionReader.buffer = bytes.NewBuffer(make([]byte, 0, 2*blockSize))
|
||||
return decryptionReader, nil
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ func TestNormalReading(t *testing.T) {
|
||||
aesBlock, err := aes.NewCipher(key)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
aesMode := cipher.NewCBCEncrypter(aesBlock, iv)
|
||||
aesStream := cipher.NewCFBEncrypter(aesBlock, iv)
|
||||
|
||||
ciphertext := make([]byte, testSize)
|
||||
aesMode.CryptBlocks(ciphertext, plaintext)
|
||||
aesStream.XORKeyStream(ciphertext, plaintext)
|
||||
|
||||
ciphertextcopy := make([]byte, testSize)
|
||||
copy(ciphertextcopy, ciphertext)
|
||||
|
@ -224,8 +224,8 @@ func (w *VMessRequestWriter) Write(writer io.Writer, request *VMessRequest) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
aesMode := cipher.NewCBCEncrypter(aesCipher, make([]byte, blockSize))
|
||||
cWriter := v2io.NewCryptionWriter(aesMode, writer)
|
||||
aesStream := cipher.NewCFBEncrypter(aesCipher, make([]byte, blockSize))
|
||||
cWriter := v2io.NewCryptionWriter(aesStream, writer)
|
||||
|
||||
_, err = writer.Write(buffer[0:encryptionBegin])
|
||||
if err != nil {
|
||||
|
25
log/log.go
25
log/log.go
@ -21,30 +21,33 @@ func SetLogLevel(level LogLevel) {
|
||||
logLevel = level
|
||||
}
|
||||
|
||||
func writeLog(data string, level LogLevel) {
|
||||
func writeLog(level LogLevel, prefix, format string, v ...interface{}) string {
|
||||
if level < logLevel {
|
||||
return
|
||||
return ""
|
||||
}
|
||||
log.Print(data)
|
||||
var data string
|
||||
if v == nil || len(v) == 0 {
|
||||
data = format
|
||||
} else {
|
||||
data = fmt.Sprintf(format, v...)
|
||||
}
|
||||
log.Print(prefix + data)
|
||||
return data
|
||||
}
|
||||
|
||||
func Debug(format string, v ...interface{}) {
|
||||
data := fmt.Sprintf(format, v)
|
||||
writeLog("[Debug]"+data, DebugLevel)
|
||||
writeLog(DebugLevel, "[Debug]", format, v...)
|
||||
}
|
||||
|
||||
func Info(format string, v ...interface{}) {
|
||||
data := fmt.Sprintf(format, v)
|
||||
writeLog("[Info]"+data, InfoLevel)
|
||||
writeLog(InfoLevel, "[Info]", format, v...)
|
||||
}
|
||||
|
||||
func Warning(format string, v ...interface{}) {
|
||||
data := fmt.Sprintf(format, v)
|
||||
writeLog("[Warning]"+data, WarningLevel)
|
||||
writeLog(WarningLevel, "[Warning]", format, v...)
|
||||
}
|
||||
|
||||
func Error(format string, v ...interface{}) error {
|
||||
data := fmt.Sprintf(format, v)
|
||||
writeLog("[Error]"+data, ErrorLevel)
|
||||
data := writeLog(ErrorLevel, "[Error]", format, v...)
|
||||
return errors.New(data)
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ package freedom
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/v2ray/v2ray-core"
|
||||
"github.com/v2ray/v2ray-core/log"
|
||||
v2net "github.com/v2ray/v2ray-core/net"
|
||||
)
|
||||
|
||||
@ -24,10 +24,9 @@ func (vconn *VFreeConnection) Start(vRay core.OutboundVRay) error {
|
||||
output := vRay.OutboundOutput()
|
||||
conn, err := net.Dial("tcp", vconn.dest.String())
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
return log.Error("Failed to open tcp: %s", vconn.dest.String())
|
||||
}
|
||||
log.Print("Working on tcp:" + vconn.dest.String())
|
||||
log.Debug("Sending outbound tcp: %s", vconn.dest.String())
|
||||
|
||||
finish := make(chan bool, 2)
|
||||
go vconn.DumpInput(conn, input, finish)
|
||||
@ -41,22 +40,25 @@ func (vconn *VFreeConnection) DumpInput(conn net.Conn, input <-chan []byte, fini
|
||||
data, open := <-input
|
||||
if !open {
|
||||
finish <- true
|
||||
log.Debug("Freedom finishing input.")
|
||||
break
|
||||
}
|
||||
conn.Write(data)
|
||||
nBytes, err := conn.Write(data)
|
||||
log.Debug("Freedom wrote %d bytes with error %v", nBytes, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (vconn *VFreeConnection) DumpOutput(conn net.Conn, output chan<- []byte, finish chan<- bool) {
|
||||
for {
|
||||
buffer := make([]byte, 128)
|
||||
buffer := make([]byte, 512)
|
||||
nBytes, err := conn.Read(buffer)
|
||||
log.Debug("Freedom reading %d bytes with error %v", nBytes, err)
|
||||
if err == io.EOF {
|
||||
close(output)
|
||||
finish <- true
|
||||
log.Debug("Freedom finishing output.")
|
||||
break
|
||||
}
|
||||
log.Print(buffer[:nBytes])
|
||||
output <- buffer[:nBytes]
|
||||
}
|
||||
}
|
||||
|
@ -11,3 +11,7 @@ type FreedomFactory struct {
|
||||
func (factory FreedomFactory) Create(vp *core.VPoint, config []byte, dest v2net.VAddress) (core.OutboundConnectionHandler, error) {
|
||||
return NewVFreeConnection(dest), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
core.RegisterOutboundConnectionHandlerFactory("freedom", FreedomFactory{})
|
||||
}
|
||||
|
@ -37,8 +37,10 @@ func NewSocksServer(vp *core.VPoint, rawConfig []byte) *SocksServer {
|
||||
func (server *SocksServer) Listen(port uint16) error {
|
||||
listener, err := net.Listen("tcp", ":"+strconv.Itoa(int(port)))
|
||||
if err != nil {
|
||||
return log.Error("Error on listening port %d: %v", port, err)
|
||||
log.Error("Error on listening port %d: %v", port, err)
|
||||
return err
|
||||
}
|
||||
log.Debug("Working on tcp:%d", port)
|
||||
server.accepting = true
|
||||
go server.AcceptConnections(listener)
|
||||
return nil
|
||||
@ -48,7 +50,8 @@ func (server *SocksServer) AcceptConnections(listener net.Listener) error {
|
||||
for server.accepting {
|
||||
connection, err := listener.Accept()
|
||||
if err != nil {
|
||||
return log.Error("Error on accepting socks connection: %v", err)
|
||||
log.Error("Error on accepting socks connection: %v", err)
|
||||
return err
|
||||
}
|
||||
go server.HandleConnection(connection)
|
||||
}
|
||||
@ -60,7 +63,8 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
|
||||
|
||||
auth, err := socksio.ReadAuthentication(connection)
|
||||
if err != nil {
|
||||
return log.Error("Error on reading authentication: %v", err)
|
||||
log.Error("Error on reading authentication: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
expectedAuthMethod := socksio.AuthNotRequired
|
||||
@ -76,12 +80,14 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
|
||||
return ErrorAuthenticationFailed
|
||||
}
|
||||
|
||||
log.Debug("Auth accepted, responding auth.")
|
||||
authResponse := socksio.NewAuthenticationResponse(socksio.AuthNotRequired)
|
||||
socksio.WriteAuthentication(connection, authResponse)
|
||||
|
||||
request, err := socksio.ReadRequest(connection)
|
||||
if err != nil {
|
||||
return log.Error("Error on reading socks request: %v", err)
|
||||
log.Error("Error on reading socks request: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
response := socksio.NewSocks5Response()
|
||||
@ -105,6 +111,7 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
|
||||
case socksio.AddrTypeDomain:
|
||||
response.Domain = request.Domain
|
||||
}
|
||||
log.Debug("Socks response port = %d", response.Port)
|
||||
socksio.WriteResponse(connection, response)
|
||||
|
||||
ray := server.vPoint.NewInboundConnectionAccepted(request.Destination())
|
||||
@ -121,12 +128,13 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
|
||||
|
||||
func (server *SocksServer) dumpInput(conn net.Conn, input chan<- []byte, finish chan<- bool) {
|
||||
for {
|
||||
buffer := make([]byte, 256)
|
||||
buffer := make([]byte, 512)
|
||||
nBytes, err := conn.Read(buffer)
|
||||
log.Debug("Reading %d bytes, with error %v", nBytes, err)
|
||||
if err == io.EOF {
|
||||
close(input)
|
||||
finish <- true
|
||||
log.Debug("Socks finishing input.")
|
||||
break
|
||||
}
|
||||
input <- buffer[:nBytes]
|
||||
@ -138,10 +146,11 @@ func (server *SocksServer) dumpOutput(conn net.Conn, output <-chan []byte, finis
|
||||
buffer, open := <-output
|
||||
if !open {
|
||||
finish <- true
|
||||
log.Debug("Socks finishing output")
|
||||
break
|
||||
}
|
||||
nBytes, _ := conn.Write(buffer)
|
||||
log.Debug("Writing %d bytes", nBytes)
|
||||
nBytes, err := conn.Write(buffer)
|
||||
log.Debug("Writing %d bytes with error %v", nBytes, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,29 +11,29 @@ import (
|
||||
|
||||
func TestSocksTcpConnect(t *testing.T) {
|
||||
t.Skip("Not ready yet.")
|
||||
/*
|
||||
assert := unit.Assert(t)
|
||||
/*
|
||||
assert := unit.Assert(t)
|
||||
|
||||
port := uint16(12384)
|
||||
port := uint16(12384)
|
||||
|
||||
uuid := "2418d087-648d-4990-86e8-19dca1d006d3"
|
||||
vid, err := core.UUIDToVID(uuid)
|
||||
assert.Error(err).IsNil()
|
||||
uuid := "2418d087-648d-4990-86e8-19dca1d006d3"
|
||||
vid, err := core.UUIDToVID(uuid)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
config := core.VConfig{
|
||||
port,
|
||||
[]core.VUser{core.VUser{vid}},
|
||||
"",
|
||||
[]core.VNext{}}
|
||||
config := core.VConfig{
|
||||
port,
|
||||
[]core.VUser{core.VUser{vid}},
|
||||
"",
|
||||
[]core.VNext{}}
|
||||
|
||||
och := new(mocks.FakeOutboundConnectionHandler)
|
||||
och.Data2Send = bytes.NewBuffer(make([]byte, 1024))
|
||||
och.Data2Return = []byte("The data to be returned to socks server.")
|
||||
och := new(mocks.FakeOutboundConnectionHandler)
|
||||
och.Data2Send = bytes.NewBuffer(make([]byte, 1024))
|
||||
och.Data2Return = []byte("The data to be returned to socks server.")
|
||||
|
||||
vpoint, err := core.NewVPoint(&config, SocksServerFactory{}, och)
|
||||
assert.Error(err).IsNil()
|
||||
vpoint, err := core.NewVPoint(&config, SocksServerFactory{}, och)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
err = vpoint.Start()
|
||||
assert.Error(err).IsNil()
|
||||
*/
|
||||
err = vpoint.Start()
|
||||
assert.Error(err).IsNil()
|
||||
*/
|
||||
}
|
||||
|
@ -10,3 +10,7 @@ type SocksServerFactory struct {
|
||||
func (factory SocksServerFactory) Create(vp *core.VPoint, config []byte) (core.InboundConnectionHandler, error) {
|
||||
return NewSocksServer(vp, config), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
core.RegisterInboundConnectionHandlerFactory("socks", SocksServerFactory{})
|
||||
}
|
||||
|
@ -4,11 +4,22 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/v2ray/v2ray-core"
|
||||
"github.com/v2ray/v2ray-core/log"
|
||||
v2net "github.com/v2ray/v2ray-core/net"
|
||||
)
|
||||
|
||||
type VMessUser struct {
|
||||
Id string `json:"id"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
func (u *VMessUser) ToVUser() (core.VUser, error) {
|
||||
id, err := core.UUIDToVID(u.Id)
|
||||
return core.VUser{id}, err
|
||||
}
|
||||
|
||||
type VMessInboundConfig struct {
|
||||
AllowedClients []core.VUser `json:"clients"`
|
||||
AllowedClients []VMessUser `json:"clients"`
|
||||
}
|
||||
|
||||
func loadInboundConfig(rawConfig []byte) (VMessInboundConfig, error) {
|
||||
@ -18,19 +29,27 @@ func loadInboundConfig(rawConfig []byte) (VMessInboundConfig, error) {
|
||||
}
|
||||
|
||||
type VNextConfig struct {
|
||||
Address string `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
Users []core.VUser `json:"users"`
|
||||
Address string `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
Users []VMessUser `json:"users"`
|
||||
}
|
||||
|
||||
func (config VNextConfig) ToVNextServer() VNextServer {
|
||||
users := make([]core.VUser, 0, len(config.Users))
|
||||
for _, user := range config.Users {
|
||||
vuser, err := user.ToVUser()
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to convert %v to VUser.", user))
|
||||
}
|
||||
users = append(users, vuser)
|
||||
}
|
||||
return VNextServer{
|
||||
v2net.DomainAddress(config.Address, config.Port),
|
||||
config.Users}
|
||||
users}
|
||||
}
|
||||
|
||||
type VMessOutboundConfig struct {
|
||||
VNextList []VNextConfig
|
||||
VNextList []VNextConfig `json:"vnext"`
|
||||
}
|
||||
|
||||
func loadOutboundConfig(rawConfig []byte) (VMessOutboundConfig, error) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
package vmess
|
||||
|
||||
const (
|
||||
BufferSize = 256
|
||||
BufferSize = 512
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"crypto/md5"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/v2ray/v2ray-core"
|
||||
v2io "github.com/v2ray/v2ray-core/io"
|
||||
@ -24,10 +25,10 @@ func NewVMessInboundHandler(vp *core.VPoint, clients *core.VUserSet) *VMessInbou
|
||||
return handler
|
||||
}
|
||||
|
||||
func (handler *VMessInboundHandler) Listen(port uint8) error {
|
||||
listener, err := net.Listen("tcp", ":"+string(port))
|
||||
func (handler *VMessInboundHandler) Listen(port uint16) error {
|
||||
listener, err := net.Listen("tcp", ":"+strconv.Itoa(int(port)))
|
||||
if err != nil {
|
||||
return err
|
||||
return log.Error("Unable to listen tcp:%d", port)
|
||||
}
|
||||
handler.accepting = true
|
||||
go handler.AcceptConnections(listener)
|
||||
@ -39,7 +40,7 @@ func (handler *VMessInboundHandler) AcceptConnections(listener net.Listener) err
|
||||
for handler.accepting {
|
||||
connection, err := listener.Accept()
|
||||
if err != nil {
|
||||
return err
|
||||
return log.Error("Failed to accpet connection: %s", err.Error())
|
||||
}
|
||||
go handler.HandleConnection(connection)
|
||||
}
|
||||
@ -54,9 +55,14 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debug("Received request for %s", request.Address.String())
|
||||
|
||||
response := vmessio.NewVMessResponse(request)
|
||||
connection.Write(response[:])
|
||||
nBytes, err := connection.Write(response[:])
|
||||
log.Debug("Writing VMess response %v", response)
|
||||
if err != nil {
|
||||
return log.Error("Failed to write VMess response (%d bytes): %v", nBytes, err)
|
||||
}
|
||||
|
||||
requestKey := request.RequestKey[:]
|
||||
requestIV := request.RequestIV[:]
|
||||
@ -65,12 +71,12 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error
|
||||
|
||||
requestReader, err := v2io.NewAesDecryptReader(requestKey, requestIV, connection)
|
||||
if err != nil {
|
||||
return err
|
||||
return log.Error("Failed to create decrypt reader: %v", err)
|
||||
}
|
||||
|
||||
responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
|
||||
if err != nil {
|
||||
return err
|
||||
return log.Error("Failed to create encrypt writer: %v", err)
|
||||
}
|
||||
|
||||
ray := handler.vPoint.NewInboundConnectionAccepted(request.Address)
|
||||
@ -89,8 +95,10 @@ func (handler *VMessInboundHandler) dumpInput(reader io.Reader, input chan<- []b
|
||||
for {
|
||||
buffer := make([]byte, BufferSize)
|
||||
nBytes, err := reader.Read(buffer)
|
||||
log.Debug("VMessInbound: Reading %d bytes with error %v", nBytes, err)
|
||||
if err == io.EOF {
|
||||
close(input)
|
||||
log.Debug("VMessInbound finishing input.")
|
||||
finish <- true
|
||||
break
|
||||
}
|
||||
@ -103,9 +111,11 @@ func (handler *VMessInboundHandler) dumpOutput(writer io.Writer, output <-chan [
|
||||
buffer, open := <-output
|
||||
if !open {
|
||||
finish <- true
|
||||
log.Debug("VMessInbound finishing output.")
|
||||
break
|
||||
}
|
||||
writer.Write(buffer)
|
||||
nBytes, err := writer.Write(buffer)
|
||||
log.Debug("VmessInbound: Wrote %d bytes with error %v", nBytes, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,14 +128,22 @@ func (handler *VMessInboundHandler) waitForFinish(finish <-chan bool) {
|
||||
type VMessInboundHandlerFactory struct {
|
||||
}
|
||||
|
||||
func (factory *VMessInboundHandlerFactory) Create(vp *core.VPoint, rawConfig []byte) *VMessInboundHandler {
|
||||
func (factory *VMessInboundHandlerFactory) Create(vp *core.VPoint, rawConfig []byte) (core.InboundConnectionHandler, error) {
|
||||
config, err := loadInboundConfig(rawConfig)
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to load VMess inbound config: %v", err))
|
||||
}
|
||||
allowedClients := core.NewVUserSet()
|
||||
for _, user := range config.AllowedClients {
|
||||
for _, client := range config.AllowedClients {
|
||||
user, err := client.ToVUser()
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to parse user id %s: %v", client.Id, err))
|
||||
}
|
||||
allowedClients.AddUser(user)
|
||||
}
|
||||
return NewVMessInboundHandler(vp, allowedClients)
|
||||
return NewVMessInboundHandler(vp, allowedClients), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
core.RegisterInboundConnectionHandlerFactory("vmess", &VMessInboundHandlerFactory{})
|
||||
}
|
||||
|
@ -62,26 +62,48 @@ func (handler *VMessOutboundHandler) Start(ray core.OutboundVRay) error {
|
||||
request.Command = byte(0x01)
|
||||
request.Address = handler.dest
|
||||
|
||||
conn, err := net.Dial("tcp", vNextAddress.String())
|
||||
go handler.startCommunicate(request, vNextAddress, ray)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (handler *VMessOutboundHandler) startCommunicate(request *vmessio.VMessRequest, dest v2net.VAddress, ray core.OutboundVRay) error {
|
||||
conn, err := net.Dial("tcp", dest.String())
|
||||
log.Debug("VMessOutbound dialing tcp: %s", dest.String())
|
||||
if err != nil {
|
||||
log.Error("Failed to open tcp (%s): %v", dest.String(), err)
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
requestWriter := vmessio.NewVMessRequestWriter()
|
||||
requestWriter.Write(conn, request)
|
||||
err = requestWriter.Write(conn, request)
|
||||
if err != nil {
|
||||
log.Error("Failed to write VMess request: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
requestKey := request.RequestKey[:]
|
||||
requestIV := request.RequestIV[:]
|
||||
responseKey := md5.Sum(requestKey)
|
||||
responseIV := md5.Sum(requestIV)
|
||||
|
||||
encryptRequestWriter, err := v2io.NewAesEncryptWriter(requestKey, requestIV, conn)
|
||||
response := vmessio.VMessResponse{}
|
||||
nBytes, err := conn.Read(response[:])
|
||||
if err != nil {
|
||||
log.Error("Failed to read VMess response (%d bytes): %v", nBytes, err)
|
||||
return err
|
||||
}
|
||||
responseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
|
||||
log.Debug("Got response %v", response)
|
||||
// TODO: check response
|
||||
|
||||
encryptRequestWriter, err := v2io.NewAesEncryptWriter(requestKey, requestIV, conn)
|
||||
if err != nil {
|
||||
log.Error("Failed to create encrypt writer: %v", err)
|
||||
return err
|
||||
}
|
||||
decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
|
||||
if err != nil {
|
||||
log.Error("Failed to create decrypt reader: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -90,7 +112,7 @@ func (handler *VMessOutboundHandler) Start(ray core.OutboundVRay) error {
|
||||
finish := make(chan bool, 2)
|
||||
|
||||
go handler.dumpInput(encryptRequestWriter, input, finish)
|
||||
go handler.dumpOutput(responseReader, output, finish)
|
||||
go handler.dumpOutput(decryptResponseReader, output, finish)
|
||||
handler.waitForFinish(finish)
|
||||
return nil
|
||||
}
|
||||
@ -99,9 +121,11 @@ func (handler *VMessOutboundHandler) dumpOutput(reader io.Reader, output chan<-
|
||||
for {
|
||||
buffer := make([]byte, BufferSize)
|
||||
nBytes, err := reader.Read(buffer)
|
||||
log.Debug("VMessOutbound: Reading %d bytes, with error %v", nBytes, err)
|
||||
if err == io.EOF {
|
||||
close(output)
|
||||
finish <- true
|
||||
log.Debug("VMessOutbound finishing output.")
|
||||
break
|
||||
}
|
||||
output <- buffer[:nBytes]
|
||||
@ -113,9 +137,11 @@ func (handler *VMessOutboundHandler) dumpInput(writer io.Writer, input <-chan []
|
||||
buffer, open := <-input
|
||||
if !open {
|
||||
finish <- true
|
||||
log.Debug("VMessOutbound finishing input.")
|
||||
break
|
||||
}
|
||||
writer.Write(buffer)
|
||||
nBytes, err := writer.Write(buffer)
|
||||
log.Debug("VMessOutbound: Wrote %d bytes with error %v", nBytes, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,12 +149,13 @@ func (handler *VMessOutboundHandler) waitForFinish(finish <-chan bool) {
|
||||
for i := 0; i < 2; i++ {
|
||||
<-finish
|
||||
}
|
||||
log.Debug("Finishing waiting for VMessOutbound ending.")
|
||||
}
|
||||
|
||||
type VMessOutboundHandlerFactory struct {
|
||||
}
|
||||
|
||||
func (factory *VMessOutboundHandlerFactory) Create(vp *core.VPoint, rawConfig []byte, destination v2net.VAddress) *VMessOutboundHandler {
|
||||
func (factory *VMessOutboundHandlerFactory) Create(vp *core.VPoint, rawConfig []byte, destination v2net.VAddress) (core.OutboundConnectionHandler, error) {
|
||||
config, err := loadOutboundConfig(rawConfig)
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to load VMess outbound config: %v", err))
|
||||
@ -137,5 +164,9 @@ func (factory *VMessOutboundHandlerFactory) Create(vp *core.VPoint, rawConfig []
|
||||
for _, server := range config.VNextList {
|
||||
servers = append(servers, server.ToVNextServer())
|
||||
}
|
||||
return NewVMessOutboundHandler(vp, servers, destination)
|
||||
return NewVMessOutboundHandler(vp, servers, destination), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
core.RegisterOutboundConnectionHandlerFactory("vmess", &VMessOutboundHandlerFactory{})
|
||||
}
|
||||
|
3
release/config/in_socks.json
Normal file
3
release/config/in_socks.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"auth": "noauth"
|
||||
}
|
5
release/config/in_vmess.json
Normal file
5
release/config/in_vmess.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"clients": [
|
||||
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}
|
||||
]
|
||||
}
|
11
release/config/out_vmess.json
Normal file
11
release/config/out_vmess.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"vnext": [
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"port": 27183,
|
||||
"users": [
|
||||
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
11
release/config/vpoint_socks_vmess.json
Normal file
11
release/config/vpoint_socks_vmess.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"port": 1080,
|
||||
"inbound": {
|
||||
"protocol": "socks",
|
||||
"file": "in_socks.json"
|
||||
},
|
||||
"outbound": {
|
||||
"protocol": "vmess",
|
||||
"file": "out_vmess.json"
|
||||
}
|
||||
}
|
11
release/config/vpoint_vmess_freedom.json
Normal file
11
release/config/vpoint_vmess_freedom.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"port": 27183,
|
||||
"inbound": {
|
||||
"protocol": "vmess",
|
||||
"file": "in_vmess.json"
|
||||
},
|
||||
"outbound": {
|
||||
"protocol": "freedom",
|
||||
"file": ""
|
||||
}
|
||||
}
|
@ -1,5 +1,57 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
import (
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"github.com/v2ray/v2ray-core"
|
||||
"github.com/v2ray/v2ray-core/log"
|
||||
|
||||
_ "github.com/v2ray/v2ray-core/net/freedom"
|
||||
_ "github.com/v2ray/v2ray-core/net/socks"
|
||||
_ "github.com/v2ray/v2ray-core/net/vmess"
|
||||
)
|
||||
|
||||
var (
|
||||
configFile = flag.String("config", "", "Config file for this VPoint server.")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
log.SetLogLevel(log.DebugLevel)
|
||||
|
||||
if configFile == nil || len(*configFile) == 0 {
|
||||
panic(log.Error("Config file is not set."))
|
||||
}
|
||||
rawVConfig, err := ioutil.ReadFile(*configFile)
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to read config file (%s): %v", *configFile, err))
|
||||
}
|
||||
vconfig, err := core.LoadVConfig(rawVConfig)
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to parse VConfig: %v", err))
|
||||
}
|
||||
|
||||
if !path.IsAbs(vconfig.InboundConfig.File) && len(vconfig.InboundConfig.File) > 0 {
|
||||
vconfig.InboundConfig.File = path.Join(path.Dir(*configFile), vconfig.InboundConfig.File)
|
||||
}
|
||||
|
||||
if !path.IsAbs(vconfig.OutboundConfig.File) && len(vconfig.OutboundConfig.File) > 0 {
|
||||
vconfig.OutboundConfig.File = path.Join(path.Dir(*configFile), vconfig.OutboundConfig.File)
|
||||
}
|
||||
|
||||
vPoint, err := core.NewVPoint(vconfig)
|
||||
if err != nil {
|
||||
panic(log.Error("Failed to create VPoint server: %v", err))
|
||||
}
|
||||
|
||||
err = vPoint.Start()
|
||||
if err != nil {
|
||||
log.Error("Error starting VPoint server.")
|
||||
}
|
||||
|
||||
finish := make(chan bool)
|
||||
<-finish
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user