This commit is contained in:
V2Ray 2015-09-05 17:48:38 +02:00
commit 4c03bf0d45
10 changed files with 338 additions and 0 deletions

22
LICENSE Normal file
View 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
View 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 被迫删除代码的事件实在太恶心,不得不做点什么了。

View 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
View 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
View File

@ -0,0 +1,9 @@
package net
type VMessHandler struct {
}
func (*VMessHandler) Listen(port uint8) error {
return nil
}

88
spec/design.md Normal file
View 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
View 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保留
* 0x1TCP 请求
* 0x2UDP 请求
* 2 字节:目标端口
* 1 字节:目标类型
* 0x01IPv4
* 0x02域名
* 0x03IPv6
* 目标地址:
* 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
View 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
View 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
View 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
}