Beispiel #1
0
func (this *DnsCache) Add(context app.Context, domain string, ip net.IP) {
	callerTag := context.CallerTag()
	if !this.config.IsTrustedSource(serial.StringLiteral(callerTag)) {
		return
	}

	this.cache.Set(serial.StringLiteral(domain), newEntry(domain, ip))
}
Beispiel #2
0
func (this *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(16, connection)
	requestReader := protocol.NewVMessRequestReader(this.clients)

	request, err := requestReader.Read(connReader)
	if err != nil {
		log.Access(connection.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err)
		return err
	}
	log.Access(connection.RemoteAddr(), request.Address, log.AccessAccepted, serial.StringLiteral(""))
	log.Debug("VMessIn: Received request for ", request.Address)

	ray := this.space.PacketDispatcher().DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true))
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	userSettings := vmess.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	go handleInput(request, connReader, input, &readFinish)

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

	aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:])
	if err != nil {
		log.Error("VMessIn: Failed to create AES decryption stream: ", err)
		close(input)
		return err
	}

	responseWriter := v2crypto.NewCryptionWriter(aesStream, connection)

	// Optimize for small response packet
	buffer := alloc.NewLargeBuffer().Clear()
	defer buffer.Release()
	buffer.AppendBytes(request.ResponseHeader[0] ^ request.ResponseHeader[1])
	buffer.AppendBytes(request.ResponseHeader[2] ^ request.ResponseHeader[3])
	buffer.AppendBytes(byte(0), byte(0))

	if data, open := <-output; open {
		buffer.Append(data.Value)
		data.Release()
		responseWriter.Write(buffer.Value)
		go handleOutput(request, responseWriter, output, &writeFinish)
		writeFinish.Lock()
	}

	connection.CloseWrite()
	readFinish.Lock()

	return nil
}
Beispiel #3
0
func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
	if !dest.Address().IsDomain() {
		return false
	}
	domain := serial.StringLiteral(dest.Address().Domain())
	return this.pattern.MatchString(domain.ToLower().String())
}
Beispiel #4
0
func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool {
	if !dest.Address().IsDomain() {
		return false
	}
	domain := serial.StringLiteral(dest.Address().Domain())
	return domain.Contains(this.pattern)
}
Beispiel #5
0
func TestAccessLog(t *testing.T) {
	v2testing.Current(t)

	filename := "/tmp/test_access_log.log"
	InitAccessLogger(filename)
	_, err := os.Stat(filename)
	assert.Error(err).IsNil()

	Access("test_from", "test_to", AccessAccepted, "test_reason")
	<-time.After(2 * time.Second)

	accessLoggerInstance.(*fileLogWriter).close()
	accessLoggerInstance = &noOpLogWriter{}

	content, err := ioutil.ReadFile(filename)
	assert.Error(err).IsNil()

	contentStr := serial.StringLiteral(content)
	assert.String(contentStr).Contains(serial.StringLiteral("test_from"))
	assert.String(contentStr).Contains(serial.StringLiteral("test_to"))
	assert.String(contentStr).Contains(serial.StringLiteral("test_reason"))
	assert.String(contentStr).Contains(serial.StringLiteral("accepted"))
}
Beispiel #6
0
func TestStreamLogger(t *testing.T) {
	v2testing.Current(t)

	buffer := bytes.NewBuffer(make([]byte, 0, 1024))
	infoLogger = &stdOutLogWriter{
		logger: log.New(buffer, "", 0),
	}
	Info("Test ", "Stream Logger", " Format")
	assert.StringLiteral(string(buffer.Bytes())).Equals("[Info]Test Stream Logger Format" + platform.LineSeparator())

	buffer.Reset()
	errorLogger = infoLogger
	Error("Test ", serial.StringLiteral("literal"), " Format")
	assert.StringLiteral(string(buffer.Bytes())).Equals("[Error]Test literal Format" + platform.LineSeparator())
}
Beispiel #7
0
func TestDnsAdd(t *testing.T) {
	v2testing.Current(t)

	domain := "v2ray.com"
	cache := dns.NewCache(&dns.CacheConfig{
		TrustedTags: map[serial.StringLiteral]bool{
			serial.StringLiteral("testtag"): true,
		},
	})
	ip := cache.Get(&apptesting.Context{}, domain)
	netassert.IP(ip).IsNil()

	cache.Add(&apptesting.Context{CallerTagValue: "notvalidtag"}, domain, []byte{1, 2, 3, 4})
	ip = cache.Get(&apptesting.Context{}, domain)
	netassert.IP(ip).IsNil()

	cache.Add(&apptesting.Context{CallerTagValue: "testtag"}, domain, []byte{1, 2, 3, 4})
	ip = cache.Get(&apptesting.Context{}, domain)
	netassert.IP(ip).Equals(net.IP([]byte{1, 2, 3, 4}))
}
Beispiel #8
0
func (subject *StringSubject) NotEquals(expectation string) {
	if subject.value.String() == expectation {
		subject.Fail(subject.DisplayString(), "is not equal to ", serial.StringLiteral(expectation))
	}
}
Beispiel #9
0
func (subject *PortSubject) IsValid() {
	if subject.value == 0 {
		subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("a valid port"))
	}
}
Beispiel #10
0
func (this *DnsCache) Get(context app.Context, domain string) net.IP {
	if value := this.cache.Get(serial.StringLiteral(domain)); value != nil {
		return value.(*entry).ip
	}
	return nil
}
Beispiel #11
0
func (this *Shadowsocks) handleConnection(conn *hub.TCPConn) {
	defer conn.Close()

	buffer := alloc.NewSmallBuffer()
	defer buffer.Release()

	_, err := io.ReadFull(conn, buffer.Value[:this.config.Cipher.IVSize()])
	if err != nil {
		log.Access(conn.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Error("Shadowsocks: Failed to read IV: ", err)
		return
	}

	iv := buffer.Value[:this.config.Cipher.IVSize()]
	key := this.config.Key

	reader, err := this.config.Cipher.NewDecodingStream(key, iv, conn)
	if err != nil {
		log.Error("Shadowsocks: Failed to create decoding stream: ", err)
		return
	}

	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(iv, key)), false)
	if err != nil {
		log.Access(conn.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("Shadowsocks: Invalid request from ", conn.RemoteAddr(), ": ", err)
		return
	}

	dest := v2net.TCPDestination(request.Address, request.Port)
	log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, serial.StringLiteral(""))
	log.Info("Shadowsocks: Tunnelling request to ", dest)

	packet := v2net.NewPacket(dest, nil, true)
	ray := this.packetDispatcher.DispatchToOutbound(packet)

	var writeFinish sync.Mutex
	writeFinish.Lock()
	go func() {
		if payload, ok := <-ray.InboundOutput(); ok {
			payload.SliceBack(16)
			rand.Read(payload.Value[:16])

			writer, err := this.config.Cipher.NewEncodingStream(key, payload.Value[:16], conn)
			if err != nil {
				log.Error("Shadowsocks: Failed to create encoding stream: ", err)
				return
			}

			writer.Write(payload.Value)
			payload.Release()
			v2io.ChanToRawWriter(writer, ray.InboundOutput())
		}
		writeFinish.Unlock()
	}()

	var payloadReader v2io.Reader
	if request.OTA {
		payloadAuth := NewAuthenticator(ChunkKeyGenerator(iv))
		payloadReader = NewChunkReader(reader, payloadAuth)
	} else {
		payloadReader = v2io.NewAdaptiveReader(reader)
	}

	v2io.ReaderToChan(ray.InboundInput(), payloadReader)
	close(ray.InboundInput())

	writeFinish.Lock()
}
Beispiel #12
0
func (this *Shadowsocks) handlerUDPPayload(payload *alloc.Buffer, source v2net.Destination) {
	defer payload.Release()

	iv := payload.Value[:this.config.Cipher.IVSize()]
	key := this.config.Key
	payload.SliceFrom(this.config.Cipher.IVSize())

	reader, err := this.config.Cipher.NewDecodingStream(key, iv, payload)
	if err != nil {
		log.Error("Shadowsocks: Failed to create decoding stream: ", err)
		return
	}

	request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)), true)
	if err != nil {
		log.Access(source, serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("Shadowsocks: Invalid request from ", source, ": ", err)
		return
	}

	dest := v2net.UDPDestination(request.Address, request.Port)
	log.Access(source, dest, log.AccessAccepted, serial.StringLiteral(""))
	log.Info("Shadowsocks: Tunnelling request to ", dest)

	packet := v2net.NewPacket(dest, request.UDPPayload, false)
	this.udpServer.Dispatch(source, packet, func(packet v2net.Packet) {
		defer packet.Chunk().Release()

		response := alloc.NewBuffer().Slice(0, this.config.Cipher.IVSize())
		defer response.Release()

		rand.Read(response.Value)
		respIv := response.Value

		writer, err := this.config.Cipher.NewEncodingStream(key, respIv, response)
		if err != nil {
			log.Error("Shadowsocks: Failed to create encoding stream: ", err)
			return
		}

		switch {
		case request.Address.IsIPv4():
			writer.Write([]byte{AddrTypeIPv4})
			writer.Write(request.Address.IP())
		case request.Address.IsIPv6():
			writer.Write([]byte{AddrTypeIPv6})
			writer.Write(request.Address.IP())
		case request.Address.IsDomain():
			writer.Write([]byte{AddrTypeDomain, byte(len(request.Address.Domain()))})
			writer.Write([]byte(request.Address.Domain()))
		}

		writer.Write(request.Port.Bytes())
		writer.Write(packet.Chunk().Value)

		if request.OTA {
			respAuth := NewAuthenticator(HeaderKeyGenerator(key, respIv))
			respAuth.Authenticate(response.Value, response.Value[this.config.Cipher.IVSize():])
		}

		this.udpHub.WriteTo(response.Value, source)
	})
}
Beispiel #13
0
func (subject *AddressSubject) IsNotIPv6() {
	if subject.value.IsIPv6() {
		subject.Fail(subject.DisplayString(), "is not", serial.StringLiteral("an IPv6 address"))
	}
}
Beispiel #14
0
func (subject *AddressSubject) IsNotDomain() {
	if subject.value.IsDomain() {
		subject.Fail(subject.DisplayString(), "is not", serial.StringLiteral("a domain address"))
	}
}
Beispiel #15
0
func (this *DestinationSubject) IsTCP() {
	if !this.value.IsTCP() {
		this.Fail(this.DisplayString(), "is", serial.StringLiteral("a TCP destination"))
	}
}
Beispiel #16
0
func (subject *AddressSubject) IsIPv4() {
	if !subject.value.IsIPv4() {
		subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("an IPv4 address"))
	}
}
Beispiel #17
0
func StringLiteral(value string) *StringSubject {
	return String(serial.StringLiteral((value)))
}
Beispiel #18
0
func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
	return &PlainDomainMatcher{
		pattern: serial.StringLiteral(pattern),
	}
}
Beispiel #19
0
func (subject *IPSubject) IsNil() {
	if subject.value != nil {
		subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("nil"))
	}
}
Beispiel #20
0
func (this *VMessInboundHandler) HandleConnection(connection *hub.TCPConn) {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(16, connection)

	reader := v2io.NewBufferedReader(connReader)
	session := raw.NewServerSession(this.clients)

	request, err := session.DecodeRequestHeader(reader)
	if err != nil {
		log.Access(connection.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err)
		return
	}
	log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, serial.StringLiteral(""))
	log.Debug("VMessIn: Received request for ", request.Destination())

	ray := this.packetDispatcher.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true))
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	userSettings := proto.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	reader.SetCached(false)
	go func() {
		defer close(input)
		defer readFinish.Unlock()
		bodyReader := session.DecodeRequestBody(reader)
		var requestReader v2io.Reader
		if request.Option.IsChunkStream() {
			requestReader = vmessio.NewAuthChunkReader(bodyReader)
		} else {
			requestReader = v2io.NewAdaptiveReader(bodyReader)
		}
		v2io.ReaderToChan(input, requestReader)
	}()

	writer := v2io.NewBufferedWriter(connection)

	response := &proto.ResponseHeader{
		Command: this.generateCommand(request),
	}

	session.EncodeResponseHeader(response, writer)

	bodyWriter := session.EncodeResponseBody(writer)

	// Optimize for small response packet
	if data, open := <-output; open {
		if request.Option.IsChunkStream() {
			vmessio.Authenticate(data)
		}
		bodyWriter.Write(data.Value)
		data.Release()

		writer.SetCached(false)
		go func(finish *sync.Mutex) {
			var writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
			if request.Option.IsChunkStream() {
				writer = vmessio.NewAuthChunkWriter(writer)
			}
			v2io.ChanToWriter(writer, output)
			finish.Unlock()
		}(&writeFinish)
		writeFinish.Lock()
	}

	connection.CloseWrite()
	readFinish.Lock()
}
Beispiel #21
0
func (this *DestinationSubject) IsNotUDP() {
	if this.value.IsUDP() {
		this.Fail(this.DisplayString(), "is not", serial.StringLiteral("a UDP destination"))
	}
}