mirror of
https://github.com/v2ray/v2ray-core.git
synced 2026-11-13 14:44:15 +00:00
connecting dots
This commit is contained in:
1 parent
1c618e93b1
commit
0a96b8fb1d
13 files changed
+501
-48
No files matched your search
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in new issue
Block a user