commit 4c03bf0d45ba68dc2768bd75b1eb2e2efd23b58d Author: V2Ray Date: Sat Sep 5 17:48:38 2015 +0200 init diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..b04578f14 --- /dev/null +++ b/LICENSE @@ -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. + diff --git a/README.md b/README.md new file mode 100644 index 000000000..74b36339c --- /dev/null +++ b/README.md @@ -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 被迫删除代码的事件实在太恶心,不得不做点什么了。 \ No newline at end of file diff --git a/io/jsonvconfigmarshaller.go b/io/jsonvconfigmarshaller.go new file mode 100644 index 000000000..aaa994d1a --- /dev/null +++ b/io/jsonvconfigmarshaller.go @@ -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 +} \ No newline at end of file diff --git a/io/vmessreader.go b/io/vmessreader.go new file mode 100644 index 000000000..501ca0e27 --- /dev/null +++ b/io/vmessreader.go @@ -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 +} \ No newline at end of file diff --git a/net/vmesshandler.go b/net/vmesshandler.go new file mode 100644 index 000000000..6da129390 --- /dev/null +++ b/net/vmesshandler.go @@ -0,0 +1,9 @@ +package net + +type VMessHandler struct { + +} + +func (*VMessHandler) Listen(port uint8) error { + return nil +} diff --git a/spec/design.md b/spec/design.md new file mode 100644 index 000000000..382121863 --- /dev/null +++ b/spec/design.md @@ -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。 diff --git a/spec/vmess.md b/spec/vmess.md new file mode 100644 index 000000000..791d95cee --- /dev/null +++ b/spec/vmess.md @@ -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。 \ No newline at end of file diff --git a/vconfig.go b/vconfig.go new file mode 100644 index 000000000..45c671ae3 --- /dev/null +++ b/vconfig.go @@ -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) +} diff --git a/vid.go b/vid.go new file mode 100644 index 000000000..0aeed0b3b --- /dev/null +++ b/vid.go @@ -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 +} diff --git a/vpoint.go b/vpoint.go new file mode 100644 index 000000000..ffb120606 --- /dev/null +++ b/vpoint.go @@ -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 +} \ No newline at end of file