1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-10 01:40:44 +00:00

Version 1.0 alpha

This commit is contained in:
V2Ray 2015-09-12 20:36:21 +02:00
parent f3a12e9f57
commit cc3fdb6ef4
21 changed files with 279 additions and 103 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()
*/
}

View File

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

View File

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

View File

@ -1,5 +1,5 @@
package vmess
const (
BufferSize = 256
BufferSize = 512
)

View File

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

View File

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

View File

@ -0,0 +1,3 @@
{
"auth": "noauth"
}

View File

@ -0,0 +1,5 @@
{
"clients": [
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}
]
}

View File

@ -0,0 +1,11 @@
{
"vnext": [
{
"address": "127.0.0.1",
"port": 27183,
"users": [
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}
]
}
]
}

View File

@ -0,0 +1,11 @@
{
"port": 1080,
"inbound": {
"protocol": "socks",
"file": "in_socks.json"
},
"outbound": {
"protocol": "vmess",
"file": "out_vmess.json"
}
}

View File

@ -0,0 +1,11 @@
{
"port": 27183,
"inbound": {
"protocol": "vmess",
"file": "in_vmess.json"
},
"outbound": {
"protocol": "freedom",
"file": ""
}
}

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