connecting dots

This commit is contained in:
V2Ray committed 2015-09-11 00:24:18 +02:00
1 parent 1c618e93b1
commit 0a96b8fb1d
13 files changed
+501 -48

No files matched your search

+7 -6
View File
@@ -5,24 +5,25 @@ import (
"net"
"github.com/v2ray/v2ray-core"
v2net "github.com/v2ray/v2ray-core/net"
)
type VFreeConnection struct {
network string
address string
vPoint *core.VPoint
dest v2net.VAddress
}
func NewVFreeConnection(network string, address string) *VFreeConnection {
func NewVFreeConnection(vp *core.VPoint, dest v2net.VAddress) *VFreeConnection {
conn := new(VFreeConnection)
conn.network = network
conn.address = address
conn.vPoint = vp
conn.dest = dest
return conn
}
func (vconn *VFreeConnection) Start(vRay core.OutboundVRay) error {
input := vRay.OutboundInput()
output := vRay.OutboundOutput()
conn, err := net.Dial(vconn.network, vconn.address)
conn, err := net.Dial("tcp", vconn.dest.String())
if err != nil {
return err
}
+46 -1
View File
@@ -2,8 +2,10 @@ package socks
import (
"errors"
"io"
"net"
"github.com/v2ray/v2ray-core"
socksio "github.com/v2ray/v2ray-core/io/socks"
)
@@ -15,6 +17,13 @@ var (
// SocksServer is a SOCKS 5 proxy server
type SocksServer struct {
accepting bool
vPoint *core.VPoint
}
func NewSocksServer(vp *core.VPoint) *SocksServer {
server := new(SocksServer)
server.vPoint = vp
return server
}
func (server *SocksServer) Listen(port uint8) error {
@@ -65,7 +74,43 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
return ErrorCommandNotSupported
}
// TODO: establish connection with VNext
ray := server.vPoint.NewInboundConnectionAccepted(request.Destination())
input := ray.InboundInput()
output := ray.InboundOutput()
finish := make(chan bool, 2)
go server.dumpInput(connection, input, finish)
go server.dumpOutput(connection, output, finish)
server.waitForFinish(finish)
return nil
}
func (server *SocksServer) dumpInput(conn net.Conn, input chan<- []byte, finish chan<- bool) {
for {
buffer := make([]byte, 256)
nBytes, err := conn.Read(buffer)
if err == io.EOF {
finish <- true
break
}
input <- buffer[:nBytes]
}
}
func (server *SocksServer) dumpOutput(conn net.Conn, output <-chan []byte, finish chan<- bool) {
for {
buffer, open := <-output
if !open {
finish <- true
break
}
conn.Write(buffer)
}
}
func (server *SocksServer) waitForFinish(finish <-chan bool) {
for i := 0; i < 2; i++ {
<-finish
}
}
+12
View File
@@ -0,0 +1,12 @@
package socks
import (
"github.com/v2ray/v2ray-core"
)
type SocksServerFactory struct {
}
func (factory *SocksServerFactory) Create(vp *core.VPoint) *SocksServer {
return NewSocksServer(vp)
}
+60
View File
@@ -0,0 +1,60 @@
package core
import (
"net"
"strconv"
)
const (
AddrTypeIP = byte(0x01)
AddrTypeDomain = byte(0x03)
)
type VAddress struct {
Type byte
IP net.IP
Domain string
Port uint16
}
func IPAddress(ip []byte, port uint16) VAddress {
// TODO: check IP length
return VAddress{
AddrTypeIP,
net.IP(ip),
"",
port}
}
func DomainAddress(domain string, port uint16) VAddress {
return VAddress{
AddrTypeDomain,
nil,
domain,
port}
}
func (addr VAddress) IsIPv4() bool {
return addr.Type == AddrTypeIP && len(addr.IP) == net.IPv4len
}
func (addr VAddress) IsIPv6() bool {
return addr.Type == AddrTypeIP && len(addr.IP) == net.IPv6len
}
func (addr VAddress) IsDomain() bool {
return addr.Type == AddrTypeDomain
}
func (addr VAddress) String() string {
var host string
switch addr.Type {
case AddrTypeIP:
host = addr.IP.String()
case AddrTypeDomain:
host = addr.Domain
default:
panic("Unknown Address Type " + strconv.Itoa(int(addr.Type)))
}
return host + ":" + strconv.Itoa(int(addr.Port))
}
+3 -15
View File
@@ -1,17 +1,5 @@
package vemss
package vmess
import (
"net"
const (
BufferSize = 256
)
type VMessHandler struct {
}
func (*VMessHandler) Listen(port uint8) error {
_, err := net.Listen("tcp", ":"+string(port))
if err != nil {
return err
}
return nil
}
+119
View File
@@ -0,0 +1,119 @@
package vmess
import (
"crypto/md5"
"io"
"net"
"github.com/v2ray/v2ray-core"
v2io "github.com/v2ray/v2ray-core/io"
vmessio "github.com/v2ray/v2ray-core/io/vmess"
)
type VMessInboundHandler struct {
vPoint *core.VPoint
accepting bool
}
func NewVMessInboundHandler(vp *core.VPoint) *VMessInboundHandler {
handler := new(VMessInboundHandler)
handler.vPoint = vp
return handler
}
func (handler *VMessInboundHandler) Listen(port uint8) error {
listener, err := net.Listen("tcp", ":"+string(port))
if err != nil {
return err
}
handler.accepting = true
go handler.AcceptConnections(listener)
return nil
}
func (handler *VMessInboundHandler) AcceptConnections(listener net.Listener) error {
for handler.accepting {
connection, err := listener.Accept()
if err != nil {
return err
}
go handler.HandleConnection(connection)
}
return nil
}
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error {
defer connection.Close()
reader := vmessio.NewVMessRequestReader(handler.vPoint.UserSet)
request, err := reader.Read(connection)
if err != nil {
return err
}
response := vmessio.NewVMessResponse(request)
connection.Write(response[:])
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 err
}
responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
if err != nil {
return err
}
ray := handler.vPoint.NewInboundConnectionAccepted(request.Destination())
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
}
func (handler *VMessInboundHandler) dumpInput(reader io.Reader, input chan<- []byte, finish chan<- bool) {
for {
buffer := make([]byte, BufferSize)
nBytes, err := reader.Read(buffer)
if err == io.EOF {
finish <- true
break
}
input <- buffer[:nBytes]
}
}
func (handler *VMessInboundHandler) dumpOutput(writer io.Writer, output <-chan []byte, finish chan<- bool) {
for {
buffer, open := <-output
if !open {
finish <- true
break
}
writer.Write(buffer)
}
}
func (handler *VMessInboundHandler) waitForFinish(finish <-chan bool) {
for i := 0; i < 2; i++ {
<-finish
}
}
type VMessInboundHandlerFactory struct {
}
func (factory *VMessInboundHandlerFactory) Create(vp *core.VPoint) *VMessInboundHandler {
return NewVMessInboundHandler(vp)
}
+133
View File
@@ -0,0 +1,133 @@
package vmess
import (
"crypto/md5"
"crypto/rand"
"io"
mrand "math/rand"
"net"
"github.com/v2ray/v2ray-core"
v2io "github.com/v2ray/v2ray-core/io"
vmessio "github.com/v2ray/v2ray-core/io/vmess"
v2net "github.com/v2ray/v2ray-core/net"
)
type VMessOutboundHandler struct {
vPoint *core.VPoint
dest v2net.VAddress
}
func NewVMessOutboundHandler(vp *core.VPoint, dest v2net.VAddress) *VMessOutboundHandler {
handler := new(VMessOutboundHandler)
handler.vPoint = vp
handler.dest = dest
return handler
}
func (handler *VMessOutboundHandler) pickVNext() (v2net.VAddress, core.VUser) {
vNextLen := len(handler.vPoint.Config.VNextList)
if vNextLen == 0 {
panic("Zero vNext is configured.")
}
vNextIndex := mrand.Intn(vNextLen)
vNext := handler.vPoint.Config.VNextList[vNextIndex]
vNextUserLen := len(vNext.Users)
if vNextUserLen == 0 {
panic("Zero User account.")
}
vNextUserIndex := mrand.Intn(vNextUserLen)
vNextUser := vNext.Users[vNextUserIndex]
return vNext.Address, vNextUser
}
func (handler *VMessOutboundHandler) Start(ray core.OutboundVRay) error {
vNextAddress, vNextUser := handler.pickVNext()
request := new(vmessio.VMessRequest)
request.SetVersion(vmessio.Version)
copy(request.UserHash(), vNextUser.Id.Hash([]byte("ASK")))
rand.Read(request.RequestIV())
rand.Read(request.RequestKey())
rand.Read(request.ResponseHeader())
request.SetCommand(byte(0x01))
request.SetPort(handler.dest.Port)
address := handler.dest
switch {
case address.IsIPv4():
request.SetIPv4(address.IP)
case address.IsIPv6():
request.SetIPv6(address.IP)
case address.IsDomain():
request.SetDomain(address.Domain)
}
conn, err := net.Dial("tcp", vNextAddress.String())
if err != nil {
return err
}
defer conn.Close()
requestWriter := vmessio.NewVMessRequestWriter(handler.vPoint.UserSet)
requestWriter.Write(conn, request)
requestKey := request.RequestKey()
requestIV := request.RequestIV()
responseKey := md5.Sum(requestKey)
responseIV := md5.Sum(requestIV)
encryptRequestWriter, err := v2io.NewAesEncryptWriter(requestKey, requestIV, conn)
if err != nil {
return err
}
responseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
if err != nil {
return err
}
input := ray.OutboundInput()
output := ray.OutboundOutput()
finish := make(chan bool, 2)
go handler.dumpInput(encryptRequestWriter, input, finish)
go handler.dumpOutput(responseReader, output, finish)
handler.waitForFinish(finish)
return nil
}
func (handler *VMessOutboundHandler) dumpOutput(reader io.Reader, output chan<- []byte, finish chan<- bool) {
for {
buffer := make([]byte, BufferSize)
nBytes, err := reader.Read(buffer)
if err == io.EOF {
finish <- true
break
}
output <- buffer[:nBytes]
}
}
func (handler *VMessOutboundHandler) dumpInput(writer io.Writer, input <-chan []byte, finish chan<- bool) {
for {
buffer, open := <-input
if !open {
finish <- true
break
}
writer.Write(buffer)
}
}
func (handler *VMessOutboundHandler) waitForFinish(finish <-chan bool) {
for i := 0; i < 2; i++ {
<-finish
}
}
type VMessOutboundHandlerFactory struct {
}
func (factory *VMessOutboundHandlerFactory) Create(vp *core.VPoint, destination v2net.VAddress) *VMessOutboundHandler {
return NewVMessOutboundHandler(vp, destination)
}