Files
v2ray_simple/proxy/direct/client.go
hahahrfool e664b9740e feat:添加回落和分流功能.
创建新子包netLayer, 将 proxy.Addr改为 netLayer.Addr
修订文档

RoutePolicy等分流机制也放到 netLayer

引入github.com/oschwald/maxminddb-golang 依赖,支持使用 GeoLite2-Country.mmdb 来进行ip分流

另外注意它默认的版本对于 golang.org/x/sys 包的依赖太老了,会导致go1.18中编译不通过,我在
go.mod 文件中新增了下面代码,就能通过编译了

```
require (
	golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect
)
```

verysimple的可执行文件的相同目录下,必须有该mmdb文件才能够开启ip分流功能

新配置方式:配置文件新加一行 "route":{ "mycountry":"CN" }

mycountry指定的国家的ip会被直连发送,其他地址ip会被发送到代理.

新配置方式,回落,直接在 local 项的 url 的 query部分添加 fallback=:80, 或者 fallback=127.0.0.1:80
即可 回落到指定端口.

将tls_test重新挪动到tlsLayer包中

在main.go中添加了 logLevel变量,并且把关于配置文件的部分挪动到 config.go

出了上面的分流和回落以外,还新增支持了 #xxx 的尾缀,用于配置该url的tag. tag在未来会被用于精准分流

Makefile中新增了 PACK 参数用于编译出 打包版的发行包;可选 tag=embed_geoip 参数用于将mmdb.tgz文件内置到可执行程序里

同时,我开始直接使用go1.18编译本项目,期待性能提升,因为这是新发布的版本,看了介绍据说对 mac m1有20%的提升.
2022-03-16 19:28:26 +08:00

129 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package direct provies direct proxy support for proxy.Client
package direct
import (
"io"
"net"
"net/url"
"sync"
"github.com/hahahrfool/v2ray_simple/netLayer"
"github.com/hahahrfool/v2ray_simple/proxy"
)
const name = "direct"
func init() {
proxy.RegisterClient(name, NewDirectClient)
}
type Direct struct {
proxy.ProxyCommonStruct
*proxy.UDP_Pipe
targetAddr *netLayer.Addr
addrStr string
}
func NewDirectClient(url *url.URL) (proxy.Client, error) {
d := &Direct{
UDP_Pipe: proxy.NewUDP_Pipe(),
}
go RelayUDP_to_Direct(d.UDP_Pipe)
return d, nil
}
func (d *Direct) Name() string { return name }
func (d *Direct) Handshake(underlay net.Conn, target *netLayer.Addr) (io.ReadWriter, error) {
if underlay == nil {
d.targetAddr = target
d.SetAddrStr(d.targetAddr.String())
return target.Dial()
}
return underlay, nil
}
// RelayUDP_to_Direct 用于 从一个未知协议读取 udp请求然后通过 直接的udp连接 发送到 远程udp 地址。
// 该函数是阻塞的。而且实现了fullcone; 本函数会直接处理 对外新udp 的dial
//
// RelayUDP_to_Direct 与 RelayTCP 函数 的区别是已经建立的udpConn是可以向其它目的地址发送信息的
// 服务端可以向 客户端发送 非客户端发送过数据 的地址 发来的信息
// 原理是,客户端请求第一次后,就会在服务端开放一个端口,然后其它远程主机就会发现这个端口并试图向客户端发送数据
// 而由于fullcone所以如果客户端要请求一个 不同的udp地址的话如果这个udp地址是之前发送来过信息那么就要用之前建立过的udp连接这样才能保证端口一致
//
func RelayUDP_to_Direct(extractor proxy.UDP_Extractor) {
//具体实现: 每当有对新远程udp地址的请求发生时就会同时 监听 “用于发送该请求到远程udp主机的本地udp端口”接受一切发往 该端口的数据
var dialedUDPConnMap map[string]*net.UDPConn = make(map[string]*net.UDPConn)
var mutex sync.RWMutex
for {
addr, requestData, err := extractor.GetNewUDPRequest()
if err != nil {
break
}
addrStr := addr.String()
mutex.RLock()
oldConn := dialedUDPConnMap[addrStr]
mutex.RUnlock()
if oldConn != nil {
oldConn.Write(requestData)
} else {
newConn, err := net.DialUDP("udp", nil, addr)
if err != nil {
break
}
_, err = newConn.Write(requestData)
if err != nil {
break
}
mutex.Lock()
dialedUDPConnMap[addrStr] = newConn
mutex.Unlock()
//监听所有发往 newConn的 远程任意主机 发来的消息。
go func(thisconn *net.UDPConn, supposedRemoteAddr *net.UDPAddr) {
bs := make([]byte, proxy.MaxUDP_packetLen)
for {
n, raddr, err := thisconn.ReadFromUDP(bs)
if err != nil {
break
}
// 这个远程 地址 无论是新的还是旧的, 都是要 和 newConn关联的下一次向 这个远程地址发消息时,也要用 newConn来发而不是新dial一个。
// 因为判断本身也要占一个语句,所以就不管新旧了,直接赋值即可。
// 所以也就不需要 比对 supposedRemoteAddr 和 raddr了
mutex.Lock()
dialedUDPConnMap[raddr.String()] = thisconn
mutex.RUnlock()
err = extractor.WriteUDPResponse(raddr, bs[:n])
if err != nil {
break
}
}
}(newConn, addr)
}
}
}