mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-06 17:27:05 +08:00
修订代码,注释,文档
This commit is contained in:
1
Makefile
1
Makefile
@@ -7,6 +7,7 @@
|
||||
#
|
||||
# for embedding geoip file:
|
||||
# make tags="embed_geoip" macm1
|
||||
#
|
||||
# 目前发布版直接使用go1.18编译,你如果想编译出相同文件,也要使用go1.18才行
|
||||
|
||||
BUILD_VERSION := v1.0.7
|
||||
|
32
main.go
32
main.go
@@ -31,6 +31,7 @@ const (
|
||||
standardMode
|
||||
v2rayCompatibleMode
|
||||
)
|
||||
const tlslazy_willuseSystemCall = runtime.GOOS == "linux" || runtime.GOOS == "darwin"
|
||||
|
||||
var (
|
||||
configFileName string
|
||||
@@ -216,12 +217,12 @@ func main() {
|
||||
|
||||
func listenSer(listener net.Listener, inServer proxy.Server) {
|
||||
|
||||
theFunc := func(conn net.Conn) {
|
||||
handleFunc := func(conn net.Conn) {
|
||||
handleNewIncomeConnection(inServer, conn)
|
||||
}
|
||||
|
||||
network := inServer.Network()
|
||||
err := netLayer.ListenAndAccept(network, inServer.AddrStr(), theFunc)
|
||||
err := netLayer.ListenAndAccept(network, inServer.AddrStr(), handleFunc)
|
||||
|
||||
if err == nil {
|
||||
if utils.CanLogInfo() {
|
||||
@@ -700,16 +701,8 @@ afterLocalServerHandshake:
|
||||
}
|
||||
|
||||
if utils.CanLogDebug() {
|
||||
/*
|
||||
go func() {
|
||||
n, e := io.Copy(wrc, wlc)
|
||||
log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e)
|
||||
}()
|
||||
n, e := io.Copy(wlc, wrc)
|
||||
|
||||
log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e)
|
||||
*/
|
||||
|
||||
if netLayer.UseReadv {
|
||||
go func() {
|
||||
n, e := netLayer.TryCopy(wrc, wlc)
|
||||
log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e)
|
||||
@@ -719,16 +712,23 @@ afterLocalServerHandshake:
|
||||
log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e)
|
||||
|
||||
} else {
|
||||
//如果两个都是 *net.TCPConn或uds, 则Copy会自动进行splice/sendfile,无需额外处理
|
||||
//go io.Copy(wrc, wlc)
|
||||
//io.Copy(wlc, wrc)
|
||||
|
||||
go func() {
|
||||
n, e := io.Copy(wrc, wlc)
|
||||
log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e)
|
||||
}()
|
||||
n, e := io.Copy(wlc, wrc)
|
||||
|
||||
log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e)
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
netLayer.Relay(wlc, wrc)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var tlslazy_willuseSystemCall = runtime.GOOS == "linux" || runtime.GOOS == "darwin"
|
||||
|
||||
// tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn,也就是裸奔转发
|
||||
// 如果在linux上,则和 xtls的splice 含义相同. 在其他系统时,与xtls-direct含义相同。
|
||||
// 我们内部先 使用 DetectConn进行过滤分析,然后再判断进化为splice 或者退化为普通拷贝
|
||||
|
@@ -28,22 +28,26 @@ type Addr struct {
|
||||
Network string
|
||||
}
|
||||
|
||||
func RandPortStr() string {
|
||||
return strconv.Itoa(rand.Intn(60000) + 4096)
|
||||
}
|
||||
|
||||
func GetRandLocalAddr() string {
|
||||
return "0.0.0.0:" + strconv.Itoa(rand.Intn(60000)+4096)
|
||||
return "0.0.0.0:" + RandPortStr()
|
||||
}
|
||||
|
||||
func NewAddrFromUDPAddr(addr *net.UDPAddr) *Addr {
|
||||
return &Addr{
|
||||
IP: addr.IP,
|
||||
Port: addr.Port,
|
||||
//IsUDP: true,
|
||||
Network: "udp",
|
||||
}
|
||||
}
|
||||
|
||||
//addrStr格式一般为 host:port 的格式;如果不含冒号,将直接认为该字符串是域名或文件名
|
||||
func NewAddr(addrStr string) (*Addr, error) {
|
||||
if !strings.Contains(addrStr, ":") {
|
||||
//如果 是unix domain socket
|
||||
//unix domain socket, 或者域名默认端口的情况
|
||||
return &Addr{Name: addrStr}, nil
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ func GetRawConn(reader io.Reader) syscall.RawConn {
|
||||
}
|
||||
|
||||
// 用于读端实现了 readv但是写端的情况,比如 从socks5读取 数据, 等裸协议的情况
|
||||
// 小贴士:将该 net.Buffers 写入io.Writer的话,只需使用 其WriteTo方法。
|
||||
// 小贴士:将该 net.Buffers 写入io.Writer的话,只需使用 其WriteTo方法, 即可自动适配writev。
|
||||
/*
|
||||
使用方式
|
||||
|
||||
|
@@ -21,7 +21,7 @@ func init() {
|
||||
|
||||
}
|
||||
|
||||
//这里认为能 splice 或 sendfile的 都算
|
||||
//这里认为能 splice 或 sendfile的 都算,具体可参考go标准代码的实现, 总之就是tcp和uds可以
|
||||
func CanSplice(r interface{}) bool {
|
||||
|
||||
if _, ok := r.(*net.TCPConn); ok {
|
||||
@@ -90,7 +90,7 @@ copy:
|
||||
return io.Copy(writeConn, readConn)
|
||||
}
|
||||
|
||||
// 类似TryCopy,但是只会读写一次
|
||||
// 类似TryCopy,但是只会读写一次; 因为只读写一次,所以没办法splice
|
||||
func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err error) {
|
||||
var mr utils.MultiReader
|
||||
var buffers net.Buffers
|
||||
@@ -100,12 +100,6 @@ func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err err
|
||||
log.Println("TryCopy", reflect.TypeOf(readConn), "->", reflect.TypeOf(writeConn))
|
||||
}
|
||||
|
||||
if SystemCanSplice && CanSplice(readConn) && CanSplice(writeConn) {
|
||||
if utils.CanLogDebug() {
|
||||
log.Println("copying with splice")
|
||||
}
|
||||
goto copy
|
||||
}
|
||||
// 不全 支持splice的话,我们就考虑 read端 可 readv 的情况
|
||||
// 连readv都不让 那就直接 经典拷贝
|
||||
if !UseReadv {
|
||||
@@ -136,16 +130,22 @@ classic:
|
||||
if utils.CanLogDebug() {
|
||||
log.Println("copying with classic method")
|
||||
}
|
||||
copy:
|
||||
|
||||
//Copy内部实现 会自动进行splice, 若无splice实现则直接使用原始方法 “循环读取 并 写入”
|
||||
return io.Copy(writeConn, readConn)
|
||||
bs := utils.GetPacket()
|
||||
n, e := readConn.Read(bs)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
n, e = writeConn.Write(bs[:n])
|
||||
utils.PutPacket(bs)
|
||||
return int64(n), e
|
||||
}
|
||||
|
||||
// 从conn1读取 写入到 conn2,并同时从 conn2读取写入conn1
|
||||
// 阻塞
|
||||
// 返回从 conn1读取 写入到 conn2的数据
|
||||
// UseReadv==true 时 内部使用 TryCopy 进行拷贝
|
||||
// 会自动优选 splice,readv,不行则使用经典拷贝
|
||||
func Relay(conn1, conn2 io.ReadWriter) (int64, error) {
|
||||
|
||||
if UseReadv {
|
||||
@@ -157,31 +157,3 @@ func Relay(conn1, conn2 io.ReadWriter) (int64, error) {
|
||||
return io.Copy(conn2, conn1)
|
||||
}
|
||||
}
|
||||
|
||||
// 阻塞.
|
||||
func RelayUDP(putter UDP_Putter, extractor UDP_Extractor) {
|
||||
|
||||
go func() {
|
||||
for {
|
||||
raddr, bs, err := extractor.GetNewUDPRequest()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = putter.WriteUDPRequest(raddr, bs)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
raddr, bs, err := putter.GetNewUDPResponse()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = extractor.WriteUDPResponse(raddr, bs)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,35 @@ const (
|
||||
)
|
||||
|
||||
//本文件内含 一些 转发 udp 数据的 接口与方法
|
||||
|
||||
// 阻塞.
|
||||
func RelayUDP(putter UDP_Putter, extractor UDP_Extractor) {
|
||||
|
||||
go func() {
|
||||
for {
|
||||
raddr, bs, err := extractor.GetNewUDPRequest()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = putter.WriteUDPRequest(raddr, bs)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
raddr, bs, err := putter.GetNewUDPResponse()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = extractor.WriteUDPResponse(raddr, bs)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////// 接口 ////////////////////
|
||||
|
||||
type UDPRequestReader interface {
|
||||
|
@@ -37,7 +37,7 @@ type UserConn struct {
|
||||
remainFirstBufLen int //记录读取握手包头时读到的buf的长度. 如果我们读超过了这个部分的话,实际上我们就可以不再使用 optionalReader 读取, 而是直接从Conn读取
|
||||
|
||||
uuid [16]byte
|
||||
convertedStr string
|
||||
convertedUUIDStr string
|
||||
version int
|
||||
isUDP bool
|
||||
isServerEnd bool //for v0
|
||||
@@ -55,11 +55,11 @@ func (uc *UserConn) GetProtocolVersion() int {
|
||||
return uc.version
|
||||
}
|
||||
func (uc *UserConn) GetIdentityStr() string {
|
||||
if uc.convertedStr == "" {
|
||||
uc.convertedStr = proxy.UUIDToStr(uc.uuid)
|
||||
if uc.convertedUUIDStr == "" {
|
||||
uc.convertedUUIDStr = proxy.UUIDToStr(uc.uuid)
|
||||
}
|
||||
|
||||
return uc.convertedStr
|
||||
return uc.convertedUUIDStr
|
||||
}
|
||||
|
||||
//如果是udp,则是多线程不安全的,如果是tcp,则安不安全看底层的链接。
|
||||
|
@@ -15,11 +15,11 @@ import (
|
||||
)
|
||||
|
||||
func TestVLess0(t *testing.T) {
|
||||
testVLess(0, "9527", t)
|
||||
testVLess(0, netLayer.RandPortStr(), t)
|
||||
}
|
||||
|
||||
func TestVLess1(t *testing.T) {
|
||||
testVLess(1, "9538", t)
|
||||
testVLess(1, netLayer.RandPortStr(), t)
|
||||
}
|
||||
|
||||
func testVLess(version int, port string, t *testing.T) {
|
||||
@@ -115,7 +115,7 @@ func testVLess(version int, port string, t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVLess0_udp(t *testing.T) {
|
||||
testVLessUDP(0, "9638", t)
|
||||
testVLessUDP(0, netLayer.RandPortStr(), t)
|
||||
}
|
||||
|
||||
//func TestVLess1_udp(t *testing.T) {
|
||||
|
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func TestVlesss(t *testing.T) {
|
||||
testTls("vlesss", "9507", t)
|
||||
testTls("vlesss", netLayer.RandPortStr(), t)
|
||||
}
|
||||
|
||||
func testTls(protocol string, port string, t *testing.T) {
|
||||
|
@@ -46,10 +46,12 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
//从Pool中获取一个 *bytes.Buffer
|
||||
func GetBuf() *bytes.Buffer {
|
||||
return bufPool.Get().(*bytes.Buffer)
|
||||
}
|
||||
|
||||
//将 buf 放回 Pool
|
||||
func PutBuf(buf *bytes.Buffer) {
|
||||
buf.Reset()
|
||||
bufPool.Put(buf)
|
||||
@@ -73,12 +75,12 @@ func PutPacket(bs []byte) {
|
||||
standardPacketPool.Put(bs[:c])
|
||||
}
|
||||
|
||||
// 从Pool中获取一个 StandardBytesLength 长度的 []byte
|
||||
func GetMTU() []byte {
|
||||
return standardBytesPool.Get().([]byte)[:StandardBytesLength]
|
||||
}
|
||||
|
||||
// 从pool中获取 []byte, 在 size <= StandardBytesLength 时有最佳性能
|
||||
// 否则会直接调用 GetPacket
|
||||
// 从pool中获取 []byte, 根据给出长度不同,来源于的Pool会不同.
|
||||
func GetBytes(size int) []byte {
|
||||
if size <= StandardBytesLength {
|
||||
bs := standardBytesPool.Get().([]byte)
|
||||
@@ -89,7 +91,7 @@ func GetBytes(size int) []byte {
|
||||
|
||||
}
|
||||
|
||||
// 根据bs长度 选择放入各种pool中, 只有cap>=1500 才会被处理
|
||||
// 根据bs长度 选择放入各种pool中, 只有 cap(bs)>=1500 才会被处理
|
||||
func PutBytes(bs []byte) {
|
||||
c := cap(bs)
|
||||
if c < StandardBytesLength {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Package utils provides utils that needed by all packages of verysimle
|
||||
// Package utils provides utils that needed by all sub-packages in verysimle
|
||||
package utils
|
||||
|
||||
//具体实现见 readv_*.go
|
||||
//具体实现见 readv_*.go; 用 GetReadVReader() 函数来获取本平台的对应实现。
|
||||
type MultiReader interface {
|
||||
Init([][]byte)
|
||||
Read(fd uintptr) int32
|
||||
|
@@ -1,5 +1,8 @@
|
||||
# vless v1
|
||||
|
||||
目前v1仍然处于研发当中。建议先用v0,等v1完全出炉了再说,本文只是理论探索,实际代码暂未完整实现所有的设计.
|
||||
## 握手协议格式
|
||||
|
||||
具体我的探讨还可以查看 https://github.com/v2fly/v2ray-core/discussions/1655
|
||||
|
||||
总的来说 vless v1 简化了一些流程, 约定永远使用tls(与trojan相同),并重点考虑 非多路复用的 udp over tcp的 fullcone实现。
|
||||
|
@@ -54,7 +54,7 @@ func (c *Conn) Read(p []byte) (int, error) {
|
||||
return n, e
|
||||
}
|
||||
c.remainLenForLastFrame -= int64(n)
|
||||
// 这里之所以可以放心 减去 n,不怕减成负的,是因为 r的代码里 在读取一帧的数据时,用到了 io.LimitedReader, 一帧的读取长度的上限已被限定,直到 该帧完全被读完为止
|
||||
// 这里之所以可以放心 减去 n,不怕减成负的,是因为 wsutil.Reader 的代码里 在读取一帧的数据时,用到了 io.LimitedReader, 一帧的读取长度的上限已被限定,直到 该帧完全被读完为止
|
||||
return n, nil
|
||||
}
|
||||
|
||||
|
@@ -1,16 +1,19 @@
|
||||
package ws
|
||||
package ws_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
"github.com/hahahrfool/v2ray_simple/ws"
|
||||
)
|
||||
|
||||
// ws基本读写功能测试.
|
||||
// 分别测试写入短数据和长数据
|
||||
func TestWs(t *testing.T) {
|
||||
listenAddr := "127.0.0.1:7777"
|
||||
listenAddr := netLayer.GetRandLocalAddr()
|
||||
listener, err := net.Listen("tcp", listenAddr)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
@@ -35,7 +38,7 @@ func TestWs(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
s := NewServer(wsPath)
|
||||
s := ws.NewServer(wsPath)
|
||||
|
||||
wsConn, err := s.Handshake(conn)
|
||||
if err != nil {
|
||||
@@ -64,7 +67,7 @@ func TestWs(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
cli, err := NewClient(listenAddr, wsPath)
|
||||
cli, err := ws.NewClient(listenAddr, wsPath)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
t.FailNow()
|
||||
|
Reference in New Issue
Block a user