mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-30 05:56:54 -05:00
init
This commit is contained in:
commit
4c03bf0d45
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 V2 Ray
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Project V2Ray
|
||||
|
||||
V2Ray 是一个翻墙工具包,用于简化和复用其它翻墙工具,加速二次开发。
|
||||
|
||||
“V2”来源于 [V2 火箭](https://zh.wikipedia.org/wiki/V-2%E7%81%AB%E7%AE%AD),Ray 即射线,意指新一代的翻墙工具。
|
||||
|
||||
## 主要特点
|
||||
* 多对多服务器支持,负载均衡
|
||||
* 支持多用户
|
||||
* 开放协议支持,兼容 ShadowSocks 和 GoAgent
|
||||
|
||||
## 概要设计
|
||||
[链接](https://github.com/V2Ray/v2ray-core/blob/master/spec/design.md)
|
||||
|
||||
## 开发日程
|
||||
|
||||
2015.11 **1.0** 完成,单服务器模式,可独立运行
|
||||
2016.01 **1.5** 完成,兼容 ShadowSocks 协议
|
||||
2016.04 **2.0** 完成,多服务器模式
|
||||
|
||||
## 关于
|
||||
我是只是一名普通的开发人员,已肉翻,本已不依赖这些翻墙工具,但 ShadowSock 和 GoAgent 被迫删除代码的事件实在太恶心,不得不做点什么了。
|
38
io/jsonvconfigmarshaller.go
Normal file
38
io/jsonvconfigmarshaller.go
Normal file
@ -0,0 +1,38 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
_ "fmt"
|
||||
"github.com/v2ray/v2ray-core"
|
||||
)
|
||||
|
||||
type JsonVUser struct {
|
||||
id string `json:"id"`
|
||||
email string `json:"email"`
|
||||
}
|
||||
|
||||
type JsonVConfig struct {
|
||||
RunAs string `json:"runas"`
|
||||
Port uint8 `json:"port"`
|
||||
Clients []JsonVUser `json:"users"`
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
type JsonVConfigUnmarshaller struct {
|
||||
|
||||
}
|
||||
|
||||
func StringToVUser(id string) (u core.VUser, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (*JsonVConfigUnmarshaller) Unmarshall(data []byte) (*core.VConfig, error) {
|
||||
var jsonConfig JsonVConfig
|
||||
err := json.Unmarshal(data, &jsonConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var vconfig = new(core.VConfig)
|
||||
vconfig.RunAs = core.VUser{}
|
||||
return vconfig, nil
|
||||
}
|
32
io/vmessreader.go
Normal file
32
io/vmessreader.go
Normal file
@ -0,0 +1,32 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
type VMessInput struct {
|
||||
version byte
|
||||
userHash [16]byte
|
||||
randHash [256]byte
|
||||
respKey [32]byte
|
||||
iv [16]byte
|
||||
command byte
|
||||
port uint16
|
||||
target [256]byte
|
||||
data []byte
|
||||
}
|
||||
|
||||
type VMessReader struct {
|
||||
conn *net.Conn
|
||||
}
|
||||
|
||||
func NewVMessReader(conn *net.Conn) (VMessReader, error) {
|
||||
var reader VMessReader
|
||||
reader.conn = conn
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
func (*VMessReader) Read() (VMessInput, error) {
|
||||
var input VMessInput
|
||||
return input, nil
|
||||
}
|
9
net/vmesshandler.go
Normal file
9
net/vmesshandler.go
Normal file
@ -0,0 +1,9 @@
|
||||
package net
|
||||
|
||||
type VMessHandler struct {
|
||||
|
||||
}
|
||||
|
||||
func (*VMessHandler) Listen(port uint8) error {
|
||||
return nil
|
||||
}
|
88
spec/design.md
Normal file
88
spec/design.md
Normal file
@ -0,0 +1,88 @@
|
||||
# V2Ray 设计概要
|
||||
|
||||
## 目标
|
||||
* V2Ray 自身提供基础的翻墙功能,单独使用可满足日常需求;
|
||||
* V2Ray 可被用于二次开发,可为用户提供个性化的翻墙体验,从而也达到难以统一屏蔽之效果;
|
||||
* V2Ray 为模块化设计,模块之间互相独立。每个模块可单独使用,也可和其它模块搭配使用。
|
||||
|
||||
## 架构
|
||||
|
||||
### 术语
|
||||
* VPoint:一个 V2Ray 服务器称为 VPoint
|
||||
* VSet:本机上的一组 VPoint
|
||||
* VSuperSet:多机环境中的多个 VSet
|
||||
* VSource:用户所使用的需要翻墙的软件,比如浏览器
|
||||
* VEnd:用户需要访问的网站
|
||||
* VUser:一个受到 VPoint 认证的帐号
|
||||
* VID:全局唯一的 ID,类似于 UUID
|
||||
|
||||
|
||||
### 工作流程
|
||||
VPoint 可提收来自 VSource 或其它 VPoint 的请求,并将请求转发至配置中的下一个 VPoint(或 VSet 或 VSuperSet) 或目标网站,然后将所得到的应答回复给请求来源。
|
||||
VPoint 采用白名单机制,只接受已认证帐号的请求。
|
||||
|
||||
### 通信协议
|
||||
* VPoint 之间默认使用自有 VMess 协议,或第三方自定义协议。
|
||||
* VPoint 和客户端之间可使用以下协议:
|
||||
* HTTP Proxy
|
||||
* SOCKS 5 Proxy
|
||||
* PPTP / L2TP / SSTP 等 VPN 隧道
|
||||
* 其它自定义协议
|
||||
* VPoint 和目标网站之间使用以下协议:
|
||||
* HTTP / HTTPS
|
||||
* UDP (DNS)
|
||||
|
||||
#### VMess
|
||||
VMess 为 V2Ray 的原生协议,设计用于两个 VPoint 之间的通信。[详细设计](https://github.com/V2Ray/v2ray-core/blob/master/spec/vmess.md)
|
||||
|
||||
### VUser
|
||||
* 每个 VUser 有一个 VID
|
||||
|
||||
### VPoint
|
||||
* 每个 VPoint 有一个 VID,运行时生成
|
||||
* 每个 VPoint 可使用独立的配置文件,或从 VSet 继承
|
||||
* 一个 VPoint 监听主机上的一个特定端口(可配置),用于接收和发送数据
|
||||
* 一个 VPoint 运行于一个独立的进程,可设定其使用的系统帐户
|
||||
|
||||
### VSet
|
||||
TODO
|
||||
|
||||
### VSuperSet
|
||||
TODO
|
||||
|
||||
## VPoint 详细设计
|
||||
一个 VPoint 包含五个部分:
|
||||
* 配置文件处理:读取和解析配置文件
|
||||
* 输入:负责与客户端建立连接(如 TCP),接收客户端的消息
|
||||
* 控制中心:负责处理事件
|
||||
* 加密解密
|
||||
* VPoint 负载均衡
|
||||
* VPoint 进程间通信
|
||||
* 输出:负责向客户端发送消息
|
||||
|
||||
### 配置文件
|
||||
配置文件使用 JSON / ProtoBuf 兼容格式,定义 TODO
|
||||
|
||||
### 加密
|
||||
TODO
|
||||
|
||||
### 任务处理
|
||||
TODO
|
||||
|
||||
### 控制中心
|
||||
控制中心响应以下事件:
|
||||
|
||||
**INIT**
|
||||
* 输入:用户 VID
|
||||
* 输出:如果用户 VID 有效:"OK",否则关闭连接
|
||||
|
||||
**MSG**
|
||||
* 输入:VMess 消息
|
||||
* 输出:对应的响应消息
|
||||
|
||||
**END**
|
||||
* 输入:用户 VID
|
||||
* 输出:如果用户 VID 有效:关闭连接
|
||||
|
||||
## 编程语言
|
||||
暂定为 golang。
|
42
spec/vmess.md
Normal file
42
spec/vmess.md
Normal file
@ -0,0 +1,42 @@
|
||||
# VMess 设计
|
||||
## 摘要
|
||||
* 版本:1
|
||||
|
||||
## 数据请求
|
||||
* 1 字节:版本号,目前为 0x1
|
||||
* 16 字节:md5(用户 VID + 'ASK')
|
||||
* 1 字节:余下字节数 L
|
||||
* 1 字节:随机填充长度 M (M <= 32)
|
||||
* M 字节:随机填充内容
|
||||
* 32 字节:应答所使用的 AES Key AK
|
||||
* 1 字节:保留
|
||||
* X 字节:实际请求内容
|
||||
* 16 字节:IV
|
||||
* 1 字节:指令
|
||||
* 0x0:保留
|
||||
* 0x1:TCP 请求
|
||||
* 0x2:UDP 请求
|
||||
* 2 字节:目标端口
|
||||
* 1 字节:目标类型
|
||||
* 0x01:IPv4
|
||||
* 0x02:域名
|
||||
* 0x03:IPv6
|
||||
* 目标地址:
|
||||
* 4 字节:IPv4
|
||||
* 2 字节长度 + 域名
|
||||
* 16 字节:IPv6
|
||||
* 4 字节:请求长度 N
|
||||
* N 字节:请求数据
|
||||
|
||||
其中第 18 字节开始所有内容经过 AES-256 加密,Key 为 left(用户 VID, 32)。
|
||||
|
||||
## 数据应答
|
||||
* 1 字节:版本号,目前为 0x1
|
||||
* 16 字节:md5(用户 VID + 'ANS')
|
||||
* 1 字节:余下字节数 L
|
||||
* L 字节
|
||||
* 16 字节:IV
|
||||
* 1 字节:数据长度
|
||||
* N 字节:应答数据
|
||||
|
||||
其中第 18 字节开始所有内容经过 AES-256 加密,Key 为 AK。
|
20
vconfig.go
Normal file
20
vconfig.go
Normal file
@ -0,0 +1,20 @@
|
||||
package core
|
||||
|
||||
type VUser struct {
|
||||
id VID
|
||||
}
|
||||
|
||||
type VConfig struct {
|
||||
RunAs VUser
|
||||
Port uint16
|
||||
AllowedClients []VUser
|
||||
AllowedProtocol string
|
||||
}
|
||||
|
||||
type VConfigMarshaller interface {
|
||||
Marshal(config VConfig) ([]byte, error)
|
||||
}
|
||||
|
||||
type VConfigUnmarshaller interface {
|
||||
Unmarshal(data []byte) (VConfig, error)
|
||||
}
|
38
vid.go
Normal file
38
vid.go
Normal file
@ -0,0 +1,38 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type VID [16]byte
|
||||
|
||||
var byteGroups = []int{8, 4, 4, 4, 12}
|
||||
|
||||
// TODO: leverage a full functional UUID library
|
||||
func UUIDToVID(uuid string) (v VID, err error) {
|
||||
text := []byte(uuid)
|
||||
if len(text) < 32 {
|
||||
err = fmt.Errorf("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
|
||||
}
|
27
vpoint.go
Normal file
27
vpoint.go
Normal file
@ -0,0 +1,27 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type VPoint struct {
|
||||
config VConfig
|
||||
connHandler ConnectionHandler
|
||||
}
|
||||
|
||||
func NewVPoint(config *VConfig) (*VPoint, error) {
|
||||
var vpoint *VPoint
|
||||
return vpoint, nil
|
||||
}
|
||||
|
||||
type ConnectionHandler interface {
|
||||
Listen(port uint16) error
|
||||
}
|
||||
|
||||
func (vp *VPoint) Start() error {
|
||||
if vp.config.Port <= 0 {
|
||||
return fmt.Errorf("Invalid port %d", vp.config.Port)
|
||||
}
|
||||
vp.connHandler.Listen(vp.config.Port)
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user