Ejemplo n.º 1
0
func (handler *VMessOutboundHandler) startCommunicate(request *vmessio.VMessRequest, dest v2net.Address, ray core.OutboundRay) error {
	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{dest.IP, int(dest.Port), ""})
	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()

	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	requestWriter := vmessio.NewVMessRequestWriter()
	err = requestWriter.Write(conn, request)
	if err != nil {
		log.Error("Failed to write VMess request: %v", err)
		close(output)
		return err
	}

	requestKey := request.RequestKey[:]
	requestIV := request.RequestIV[:]
	responseKey := md5.Sum(requestKey)
	responseIV := md5.Sum(requestIV)

	response := vmessio.VMessResponse{}
	nBytes, err := conn.Read(response[:])
	if err != nil {
		close(output)
		log.Error("Failed to read VMess response (%d bytes): %v", nBytes, err)
		return err
	}
	log.Debug("Got response %v", response)
	// TODO: check response

	encryptRequestWriter, err := v2io.NewAesEncryptWriter(requestKey, requestIV, conn)
	if err != nil {
		close(output)
		log.Error("Failed to create encrypt writer: %v", err)
		return err
	}
	decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
	if err != nil {
		close(output)
		log.Error("Failed to create decrypt reader: %v", err)
		return err
	}

	readFinish := make(chan bool)
	writeFinish := make(chan bool)

	go handler.dumpInput(encryptRequestWriter, input, readFinish)
	go handler.dumpOutput(decryptResponseReader, output, writeFinish)

	<-readFinish
	conn.CloseWrite()
	log.Debug("VMessOut closing write")
	<-writeFinish
	return nil
}
Ejemplo n.º 2
0
func handleRequest(conn *net.TCPConn, request *vmessio.VMessRequest, input <-chan []byte, finish chan<- bool) error {
	defer close(finish)
	encryptRequestWriter, err := v2io.NewAesEncryptWriter(request.RequestKey[:], request.RequestIV[:], conn)
	if err != nil {
		log.Error("Failed to create encrypt writer: %v", err)
		return err
	}

	buffer, err := request.ToBytes(v2hash.NewTimeHash(v2hash.HMACHash{}), v2math.GenerateRandomInt64InRange)
	if err != nil {
		log.Error("VMessOut: Failed to serialize VMess request: %v", err)
	}
	//conn.Write(buffer)
	data, open := <-input
	if open {
		encryptRequestWriter.Crypt(data)
		buffer = append(buffer, data...)
	}

	_, err = conn.Write(buffer)
	if err != nil {
		log.Error("VMessOut: Failed to write VMess request: %v", err)
	}

	if !open {
		return nil
	}

	v2net.ChanToWriter(encryptRequestWriter, input)
	return nil
}
Ejemplo n.º 3
0
// NewPoint returns a new Point server based on given configuration.
// The server is not started at this point.
func NewPoint(config Config) (*Point, error) {
	var vpoint = new(Point)
	vpoint.port = config.Port

	ichFactory, ok := inboundFactories[config.InboundConfig.Protocol]
	if !ok {
		panic(log.Error("Unknown inbound connection handler factory %s", config.InboundConfig.Protocol))
	}
	vpoint.ichFactory = ichFactory
	if len(config.InboundConfig.File) > 0 {
		ichConfig, err := ioutil.ReadFile(config.InboundConfig.File)
		if err != nil {
			panic(log.Error("Unable to read config file %v", err))
		}
		vpoint.ichConfig = ichConfig
	}

	ochFactory, ok := outboundFactories[config.OutboundConfig.Protocol]
	if !ok {
		panic(log.Error("Unknown outbound connection handler factory %s", config.OutboundConfig.Protocol))
	}

	vpoint.ochFactory = ochFactory
	if len(config.OutboundConfig.File) > 0 {
		ochConfig, err := ioutil.ReadFile(config.OutboundConfig.File)
		if err != nil {
			panic(log.Error("Unable to read config file %v", err))
		}
		vpoint.ochConfig = ochConfig
	}

	return vpoint, nil
}
Ejemplo n.º 4
0
func handleRequest(conn *net.TCPConn, request *vmessio.VMessRequest, input <-chan []byte, finish chan<- bool) {
	defer close(finish)
	encryptRequestWriter, err := v2io.NewAesEncryptWriter(request.RequestKey[:], request.RequestIV[:], conn)
	if err != nil {
		log.Error("VMessOut: Failed to create encrypt writer: %v", err)
		return
	}

	buffer, err := request.ToBytes(v2hash.NewTimeHash(v2hash.HMACHash{}), v2math.GenerateRandomInt64InRange)
	if err != nil {
		log.Error("VMessOut: Failed to serialize VMess request: %v", err)
		return
	}

	// Send first packet of payload together with request, in favor of small requests.
	payload, open := <-input
	if open {
		encryptRequestWriter.Crypt(payload)
		buffer = append(buffer, payload...)

		_, err = conn.Write(buffer)
		if err != nil {
			log.Error("VMessOut: Failed to write VMess request: %v", err)
			return
		}

		v2net.ChanToWriter(encryptRequestWriter, input)
	}
	return
}
Ejemplo n.º 5
0
func handleResponse(conn *net.TCPConn, request *vmessio.VMessRequest, output chan<- []byte, finish chan<- bool) {
	defer close(finish)
	defer close(output)
	responseKey := md5.Sum(request.RequestKey[:])
	responseIV := md5.Sum(request.RequestIV[:])

	decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
	if err != nil {
		log.Error("VMessOut: Failed to create decrypt reader: %v", err)
		return
	}

	response := vmessio.VMessResponse{}
	nBytes, err := decryptResponseReader.Read(response[:])
	if err != nil {
		log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", nBytes, err)
		return
	}
	if !bytes.Equal(response[:], request.ResponseHeader[:]) {
		log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.")
		return
	}

	v2net.ReaderToChan(output, decryptResponseReader)
	return
}
Ejemplo n.º 6
0
func main() {
	flag.Parse()

	if *version {
		fmt.Printf("V2Ray version %s (%s): %s", core.Version, core.Codename, core.Intro)
		fmt.Println()
		return
	}

	switch *logLevel {
	case "debug":
		log.SetLogLevel(log.DebugLevel)
	case "info":
		log.SetLogLevel(log.InfoLevel)
	case "warning":
		log.SetLogLevel(log.WarningLevel)
	case "error":
		log.SetLogLevel(log.ErrorLevel)
	}

	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.LoadConfig(rawVConfig)
	if err != nil {
		panic(log.Error("Failed to parse Config: %v", err))
	}

	if !filepath.IsAbs(vconfig.InboundConfig.File) && len(vconfig.InboundConfig.File) > 0 {
		vconfig.InboundConfig.File = filepath.Join(filepath.Dir(*configFile), vconfig.InboundConfig.File)
	}

	if !filepath.IsAbs(vconfig.OutboundConfig.File) && len(vconfig.OutboundConfig.File) > 0 {
		vconfig.OutboundConfig.File = filepath.Join(filepath.Dir(*configFile), vconfig.OutboundConfig.File)
	}

	vPoint, err := core.NewPoint(vconfig)
	if err != nil {
		panic(log.Error("Failed to create Point server: %v", err))
	}

	err = vPoint.Start()
	if err != nil {
		log.Error("Error starting Point server: %v", err)
	}

	finish := make(chan bool)
	<-finish
}
Ejemplo n.º 7
0
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error {
	defer connection.Close()

	reader := vmessio.NewVMessRequestReader(handler.clients)

	request, err := reader.Read(connection)
	if err != nil {
		log.Debug("Failed to parse VMess request: %v", err)
		return err
	}
	log.Debug("Received request for %s", request.Address.String())

	response := vmessio.NewVMessResponse(request)
	nBytes, err := connection.Write(response[:])
	if err != nil {
		return log.Error("Failed to write VMess response (%d bytes): %v", nBytes, err)
	}

	requestKey := request.RequestKey[:]
	requestIV := request.RequestIV[:]
	responseKey := md5.Sum(requestKey)
	responseIV := md5.Sum(requestIV)

	requestReader, err := v2io.NewAesDecryptReader(requestKey, requestIV, connection)
	if err != nil {
		return log.Error("Failed to create decrypt reader: %v", err)
	}

	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
	if err != nil {
		return log.Error("Failed to create encrypt writer: %v", err)
	}

	ray := handler.vPoint.NewInboundConnectionAccepted(request.Address)
	input := ray.InboundInput()
	output := ray.InboundOutput()

	readFinish := make(chan bool)
	writeFinish := make(chan bool)

	go handler.dumpInput(requestReader, input, readFinish)
	go handler.dumpOutput(responseWriter, output, writeFinish)

	<-writeFinish
	if tcpConn, ok := connection.(*net.TCPConn); ok {
		log.Debug("VMessIn closing write")
		tcpConn.CloseWrite()
	}
	<-readFinish

	return nil
}
Ejemplo n.º 8
0
func (factory *VMessInboundHandlerFactory) Create(vp *core.Point, 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.NewTimedUserSet()
	for _, client := range config.AllowedClients {
		user, err := client.ToUser()
		if err != nil {
			panic(log.Error("Failed to parse user id %s: %v", client.Id, err))
		}
		allowedClients.AddUser(user)
	}
	return NewVMessInboundHandler(vp, allowedClients), nil
}
Ejemplo n.º 9
0
func startCommunicate(request *vmessio.VMessRequest, dest v2net.Address, ray core.OutboundRay) error {
	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{dest.IP, int(dest.Port), ""})
	log.Debug("VMessOutbound dialing tcp: %s", dest.String())
	if err != nil {
		log.Error("Failed to open tcp (%s): %v", dest.String(), err)
		close(output)
		return err
	}
	defer conn.Close()
	defer close(output)

	requestFinish := make(chan bool)
	responseFinish := make(chan bool)

	go handleRequest(conn, request, input, requestFinish)
	go handleResponse(conn, request, output, responseFinish)

	<-requestFinish
	conn.CloseWrite()
	<-responseFinish
	return nil
}
Ejemplo n.º 10
0
// TODO: leverage a full functional UUID library
func UUIDToID(uuid string) (v ID, err error) {
	text := []byte(uuid)
	if len(text) < 32 {
		err = log.Error("uuid: invalid UUID string: %s", text)
		return
	}

	b := v[:]

	for _, byteGroup := range byteGroups {
		if text[0] == '-' {
			text = text[1:]
		}

		_, err = hex.Decode(b[:byteGroup/2], text[:byteGroup])

		if err != nil {
			return
		}

		text = text[byteGroup:]
		b = b[byteGroup/2:]
	}

	return
}
Ejemplo n.º 11
0
func NewID(id string) (ID, error) {
	idBytes, err := UUIDToID(id)
	if err != nil {
		return ID{}, log.Error("Failed to parse id %s", id)
	}
	hasher := hmac.New(md5.New, idBytes)
	return ID{id, idBytes, hasher}, nil
}
Ejemplo n.º 12
0
func (config VNextConfig) ToVNextServer() VNextServer {
	users := make([]core.User, 0, len(config.Users))
	for _, user := range config.Users {
		vuser, err := user.ToUser()
		if err != nil {
			panic(log.Error("Failed to convert %v to User.", user))
		}
		users = append(users, vuser)
	}
	ip := net.ParseIP(config.Address)
	if ip == nil {
		panic(log.Error("Unable to parse VNext IP: %s", config.Address))
	}
	return VNextServer{
		v2net.IPAddress(ip, config.Port),
		users}
}
Ejemplo n.º 13
0
func handleRequest(conn *net.TCPConn, request *vmessio.VMessRequest, input <-chan []byte, finish chan<- bool) error {
	defer close(finish)
	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)
		return err
	}

	encryptRequestWriter, err := v2io.NewAesEncryptWriter(request.RequestKey[:], request.RequestIV[:], conn)
	if err != nil {
		log.Error("Failed to create encrypt writer: %v", err)
		return err
	}

	v2net.ChanToWriter(encryptRequestWriter, input)
	return nil
}
Ejemplo n.º 14
0
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)
	}
	server.accepting = true
	go server.AcceptConnections(listener)
	return nil
}
Ejemplo n.º 15
0
func (server *SocksServer) AcceptConnections(listener net.Listener) {
	for server.accepting {
		connection, err := listener.Accept()
		if err != nil {
			log.Error("Error on accepting socks connection: %v", err)
		}
		go server.HandleConnection(connection)
	}
}
Ejemplo n.º 16
0
// Read reads blocks from underlying reader, the length of blocks must be
// a multiply of BlockSize()
func (reader CryptionReader) Read(blocks []byte) (int, error) {
	nBytes, err := reader.reader.Read(blocks)
	if nBytes > 0 {
		reader.stream.XORKeyStream(blocks[:nBytes], blocks[:nBytes])
	}
	if err != nil && err != io.EOF {
		log.Error("Error reading blocks: %v", err)
	}
	return nBytes, err
}
Ejemplo n.º 17
0
func NewSocksServer(vp *core.Point, rawConfig []byte) *SocksServer {
	server := new(SocksServer)
	server.vPoint = vp
	config, err := loadConfig(rawConfig)
	if err != nil {
		panic(log.Error("Unable to load socks config: %v", err))
	}
	server.config = config
	return server
}
Ejemplo n.º 18
0
func NewSocksServer(vp *core.Point, rawConfig []byte) *SocksServer {
	config, err := loadConfig(rawConfig)
	if err != nil {
		panic(log.Error("Unable to load socks config: %v", err))
	}
	return &SocksServer{
		vPoint: vp,
		config: config,
	}
}
Ejemplo n.º 19
0
func (handler *VMessInboundHandler) AcceptConnections(listener net.Listener) error {
	for handler.accepting {
		connection, err := listener.Accept()
		if err != nil {
			return log.Error("Failed to accpet connection: %s", err.Error())
		}
		go handler.HandleConnection(connection)
	}
	return nil
}
Ejemplo n.º 20
0
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error {
	defer connection.Close()
	reader := vmessio.NewVMessRequestReader(handler.clients)

	request, err := reader.Read(connection)
	if err != nil {
		return err
	}
	log.Debug("Received request for %s", request.Address.String())

	response := vmessio.NewVMessResponse(request)
	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[:]
	responseKey := md5.Sum(requestKey)
	responseIV := md5.Sum(requestIV)

	requestReader, err := v2io.NewAesDecryptReader(requestKey, requestIV, connection)
	if err != nil {
		return log.Error("Failed to create decrypt reader: %v", err)
	}

	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
	if err != nil {
		return log.Error("Failed to create encrypt writer: %v", err)
	}

	ray := handler.vPoint.NewInboundConnectionAccepted(request.Address)
	input := ray.InboundInput()
	output := ray.InboundOutput()
	finish := make(chan bool, 2)

	go handler.dumpInput(requestReader, input, finish)
	go handler.dumpOutput(responseWriter, output, finish)
	handler.waitForFinish(finish)

	return nil
}
Ejemplo n.º 21
0
func (handler *VMessInboundHandler) Listen(port uint16) error {
	listener, err := net.Listen("tcp", ":"+strconv.Itoa(int(port)))
	if err != nil {
		return log.Error("Unable to listen tcp:%d", port)
	}
	handler.accepting = true
	go handler.AcceptConnections(listener)

	return nil
}
Ejemplo n.º 22
0
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error {
	defer connection.Close()

	reader := vmessio.NewVMessRequestReader(handler.clients)

	request, err := reader.Read(connection)
	if err != nil {
		log.Debug("Failed to parse VMess request: %v", err)
		return err
	}
	log.Debug("Received request for %s", request.Address.String())

	ray := handler.vPoint.NewInboundConnectionAccepted(request.Address)
	input := ray.InboundInput()
	output := ray.InboundOutput()

	readFinish := make(chan bool)
	writeFinish := make(chan bool)

	go handleInput(request, connection, input, readFinish)

	responseKey := md5.Sum(request.RequestKey[:])
	responseIV := md5.Sum(request.RequestIV[:])

	response := vmessio.NewVMessResponse(request)
	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
	if err != nil {
		return log.Error("Failed to create encrypt writer: %v", err)
	}
	//responseWriter.Write(response[:])

	// Optimize for small response packet
	buffer := make([]byte, 0, 1024)
	buffer = append(buffer, response[:]...)
	data, open := <-output
	if open {
		buffer = append(buffer, data...)
	}
	responseWriter.Write(buffer)

	if open {
		go handleOutput(request, responseWriter, output, writeFinish)
	} else {
		close(writeFinish)
	}

	<-writeFinish
	if tcpConn, ok := connection.(*net.TCPConn); ok {
		log.Debug("VMessIn closing write")
		tcpConn.CloseWrite()
	}
	<-readFinish

	return nil
}
Ejemplo n.º 23
0
// Read reads blocks from underlying reader, the length of blocks must be
// a multiply of BlockSize()
func (reader CryptionReader) Read(blocks []byte) (int, error) {
	nBytes, err := reader.reader.Read(blocks)
	log.Debug("CryptionReader: Read %d bytes", nBytes)
	if nBytes > 0 {
		reader.stream.XORKeyStream(blocks[:nBytes], blocks[:nBytes])
	}
	if err != nil {
		log.Error("Error reading blocks: %v", err)
	}
	return nBytes, err
}
Ejemplo n.º 24
0
// Start starts the Point server, and return any error during the process.
// In the case of any errors, the state of the server is unpredicatable.
func (vp *Point) Start() error {
	if vp.port <= 0 {
		return log.Error("Invalid port %d", vp.port)
	}
	inboundConnectionHandler, err := vp.ichFactory.Create(vp, vp.ichConfig)
	if err != nil {
		return err
	}
	err = inboundConnectionHandler.Listen(vp.port)
	return nil
}
Ejemplo n.º 25
0
func (factory *VMessOutboundHandlerFactory) Create(vp *core.Point, rawConfig []byte, destination v2net.Address) (core.OutboundConnectionHandler, error) {
	config, err := loadOutboundConfig(rawConfig)
	if err != nil {
		panic(log.Error("Failed to load VMess outbound config: %v", err))
	}
	servers := make([]VNextServer, 0, len(config.VNextList))
	for _, server := range config.VNextList {
		servers = append(servers, server.ToVNextServer())
	}
	return NewVMessOutboundHandler(vp, servers, destination), nil
}
Ejemplo n.º 26
0
func (factory *VMessInboundHandlerFactory) Create(vp *core.VPoint, rawConfig []byte) *VMessInboundHandler {
	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 {
		allowedClients.AddUser(user)
	}
	return NewVMessInboundHandler(vp, allowedClients)
}
Ejemplo n.º 27
0
func handleInput(request *vmessio.VMessRequest, reader io.Reader, input chan<- []byte, finish chan<- bool) {
	defer close(input)
	defer close(finish)

	requestReader, err := v2io.NewAesDecryptReader(request.RequestKey[:], request.RequestIV[:], reader)
	if err != nil {
		log.Error("Failed to create decrypt reader: %v", err)
		return
	}

	v2net.ReaderToChan(input, requestReader)
}
Ejemplo n.º 28
0
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),
		users}
}
Ejemplo n.º 29
0
func NewID(id string) (ID, error) {
	idBytes, err := UUIDToID(id)
	if err != nil {
		return ID{}, log.Error("Failed to parse id %s", id)
	}

	md5hash := md5.New()
	md5hash.Write(idBytes)
	md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21"))
	cmdKey := md5.Sum(nil)

	return ID{id, idBytes, cmdKey[:]}, nil
}
Ejemplo n.º 30
0
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.LoadConfig(rawVConfig)
	if err != nil {
		panic(log.Error("Failed to parse Config: %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.NewPoint(vconfig)
	if err != nil {
		panic(log.Error("Failed to create Point server: %v", err))
	}

	err = vPoint.Start()
	if err != nil {
		log.Error("Error starting Point server: %v", err)
	}

	finish := make(chan bool)
	<-finish
}