mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2026-04-23 01:07:04 +08:00
修订代码;修复loglevel为debug时失效问题;dns请求加锁,已经可用
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
api草案:
|
||||
|
||||
使用restful api + basic auth
|
||||
|
||||
功能列表
|
||||
1. 生成toml配置文件功能
|
||||
2. 查看本次程序开始运行起所使用的流量(双向)
|
||||
3. 查看自某一天开始所用掉的总流量
|
||||
4. 动态插入一个 新 inServer / outClient;
|
||||
5. 动态修改 某个 inServer/outClient 的 uuid
|
||||
6. 动态调节 hy手动挡阻控模式 的发送速率
|
||||
7. 动态删除一个 inServer /outClient
|
||||
8. 动态控制每一个 inServer / outClient 的网速
|
||||
|
||||
坚决抵制添加其它花哨的专门供机场主使用的功能。你们机场主有不给我们开发者钱,凭啥给你干活。
|
||||
|
||||
@@ -9,6 +9,9 @@ default_uuid = "a684455c-b14f-11ea-bf0d-42010aaa0003"
|
||||
|
||||
|
||||
[dns]
|
||||
|
||||
# dns解析仅仅是为了能够精准分流, 如果你不需要分流, 没有自定义dns需求,则不需要dns模块
|
||||
|
||||
servers = [
|
||||
"udp://114.114.114.114:53" # 如果把该url指向我们dokodemo监听的端口,就可以达到通过节点请求dns的目的.
|
||||
]
|
||||
|
||||
@@ -43,7 +43,30 @@ require (
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
||||
replace github.com/lucas-clemente/quic-go => github.com/tobyxdd/quic-go v0.25.1-0.20220224051149-310bd1bfaf1f
|
||||
|
||||
retract v1.1.1
|
||||
|
||||
retract v1.1.0
|
||||
|
||||
retract v1.0.9
|
||||
|
||||
retract v1.0.8
|
||||
|
||||
retract v1.0.7
|
||||
|
||||
retract v1.0.6
|
||||
|
||||
retract v1.0.5
|
||||
|
||||
retract v1.0.4
|
||||
|
||||
retract v1.0.3
|
||||
|
||||
retract v1.0.2
|
||||
|
||||
retract v1.0.1
|
||||
|
||||
retract v1.0.0
|
||||
|
||||
@@ -12,6 +12,7 @@ github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU
|
||||
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
@@ -142,6 +143,7 @@ github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je4
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
||||
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM=
|
||||
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||
@@ -202,6 +204,7 @@ go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
/*
|
||||
Package grpc implements methods for grpc
|
||||
/*Package grpc implements methods for grpc
|
||||
|
||||
从stream.proto 生成 stream.pb.go 和 stream_grpc.pb.go:
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Package httpLayer 提供http层的一些方法和定义.
|
||||
Package httpLayer provides methods and definitions for http layer
|
||||
|
||||
比如fallback一般由httpLayer处理
|
||||
*/
|
||||
|
||||
@@ -321,7 +321,6 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) {
|
||||
|
||||
ce.Write(
|
||||
zap.String("protocol", proxy.GetFullName(inServer)),
|
||||
zap.String("network", inServer.Network()),
|
||||
zap.String("addr", inServer.AddrStr()),
|
||||
)
|
||||
//log.Printf("%s is listening %s on %s\n", , , )
|
||||
@@ -342,7 +341,6 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) {
|
||||
|
||||
ce.Write(
|
||||
zap.String("protocol", proxy.GetFullName(inServer)),
|
||||
zap.String("network", inServer.Network()),
|
||||
zap.String("addr", inServer.AddrStr()),
|
||||
)
|
||||
//log.Printf("%s is listening %s on %s\n", proxy.GetFullName(inServer), network, inServer.AddrStr())
|
||||
@@ -744,20 +742,33 @@ afterLocalServerHandshake:
|
||||
|
||||
////////////////////////////// DNS解析阶段 /////////////////////////////////////
|
||||
|
||||
//dns解析会试图解析域名并将ip放入 targetAddr中
|
||||
// 因为在direct时,netLayer.Addr 拨号时,会优先选用ip拨号,而且我们下面的分流阶段 如果使用ip的话,
|
||||
// 可以利用geoip文件, 可以做到国别分流.
|
||||
|
||||
if dnsMachine != nil && (targetAddr.Name != "" && len(targetAddr.IP) == 0) && targetAddr.Network != "unix" {
|
||||
//log.Println("will query", targetAddr.Name)
|
||||
|
||||
if ce := utils.CanLogDebug("querying"); ce != nil {
|
||||
ce.Write(zap.String("domain", targetAddr.Name))
|
||||
}
|
||||
|
||||
ip := dnsMachine.Query(targetAddr.Name, dns.TypeA)
|
||||
if ip == nil {
|
||||
ip = dnsMachine.Query(targetAddr.Name, dns.TypeAAAA)
|
||||
}
|
||||
if ip != nil {
|
||||
targetAddr.IP = ip
|
||||
|
||||
if ce2 := utils.CanLogDebug("dns query result"); ce2 != nil {
|
||||
ce2.Write(zap.String("domain", targetAddr.Name), zap.String("ip", ip.String()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////// 分流阶段 /////////////////////////////////////
|
||||
|
||||
var client proxy.Client = iics.defaultClient
|
||||
routed := false
|
||||
|
||||
//尝试分流, 获取到真正要发向 的 outClient
|
||||
if routePolicy != nil && !inServer.CantRoute() {
|
||||
@@ -768,8 +779,7 @@ afterLocalServerHandshake:
|
||||
}
|
||||
|
||||
if ce := utils.CanLogDebug("try routing"); ce != nil {
|
||||
//log.Printf("try routing %v\n", desc)
|
||||
ce.Write(zap.Any("desc", desc))
|
||||
ce.Write(zap.Any("source", desc))
|
||||
}
|
||||
|
||||
outtag := routePolicy.GetOutTag(desc)
|
||||
@@ -777,9 +787,9 @@ afterLocalServerHandshake:
|
||||
if outtag == "direct" {
|
||||
client = directClient
|
||||
iics.routedToDirect = true
|
||||
routed = true
|
||||
|
||||
if ce := utils.CanLogInfo("routed to direct"); ce != nil {
|
||||
//log.Printf("routed to direct %s\n", targetAddr.UrlString())
|
||||
ce.Write(
|
||||
zap.String("target", targetAddr.UrlString()),
|
||||
)
|
||||
@@ -789,17 +799,29 @@ afterLocalServerHandshake:
|
||||
|
||||
if tagC, ok := clientsTagMap[outtag]; ok {
|
||||
client = tagC
|
||||
if ce := utils.CanLogInfo("routed to"); ce != nil {
|
||||
//log.Printf("routed to %s %s\n", outtag, proxy.GetFullName(client))
|
||||
routed = true
|
||||
if ce := utils.CanLogInfo("routed"); ce != nil {
|
||||
ce.Write(
|
||||
zap.String("outtag", outtag),
|
||||
zap.String("client", proxy.GetFullName(client)),
|
||||
zap.Any("source", desc),
|
||||
zap.String("to outtag", outtag),
|
||||
zap.String("P", proxy.GetFullName(client)),
|
||||
zap.String("addr", client.AddrStr()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !routed {
|
||||
if ce := utils.CanLogDebug("not routed, using default"); ce != nil {
|
||||
ce.Write(
|
||||
zap.Any("source", targetAddr.String()),
|
||||
zap.String("client", proxy.GetFullName(client)),
|
||||
zap.String("addr", client.AddrStr()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////// 特殊处理阶段 /////////////////////////////////////
|
||||
|
||||
// 下面几段用于处理 tls lazy
|
||||
@@ -999,13 +1021,14 @@ func dialClient(iics incomingInserverConnState, targetAddr netLayer.Addr, client
|
||||
if ce := utils.CanLogDebug("request isn't the appointed domain"); ce != nil {
|
||||
|
||||
if uniqueTestDomain != "" && uniqueTestDomain != targetAddr.Name {
|
||||
|
||||
ce.Write(
|
||||
zap.String("request", targetAddr.String()),
|
||||
zap.String("uniqueTestDomain", uniqueTestDomain),
|
||||
)
|
||||
return nil, utils.NumErr{N: 1, Prefix: "dialClient err, "}
|
||||
|
||||
}
|
||||
return nil, utils.NumErr{N: 1, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
if ce := utils.CanLogInfo("Request"); ce != nil {
|
||||
@@ -1100,7 +1123,10 @@ func dialClient(iics incomingInserverConnState, targetAddr netLayer.Addr, client
|
||||
|
||||
tlsConn, err := client.GetTLS_Client().Handshake(clientConn)
|
||||
if err != nil {
|
||||
log.Printf("failed in handshake outClient tls %s, Reason: %s\n", targetAddr.String(), err)
|
||||
if ce := utils.CanLogErr("failed in handshake outClient tls"); ce != nil {
|
||||
ce.Write(zap.String("target", targetAddr.String()), zap.Error(err))
|
||||
}
|
||||
|
||||
return nil, utils.NumErr{N: 4, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
@@ -1118,7 +1144,6 @@ advLayerStep:
|
||||
clientConn, err = client.DialSubConnFunc()(dailedCommonConn)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("DialSubConnFunc failed"); ce != nil {
|
||||
//log.Printf("DialSubConnFunc failed, %s\n", err)
|
||||
ce.Write(
|
||||
zap.Error(err),
|
||||
)
|
||||
@@ -1130,7 +1155,6 @@ advLayerStep:
|
||||
grpcClientConn, err = grpc.ClientHandshake(clientConn, &realTargetAddr)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("grpc.ClientHandshake failed"); ce != nil {
|
||||
//log.Printf("grpc.ClientHandshake failed, %s\n", err)
|
||||
ce.Write(zap.Error(err))
|
||||
|
||||
}
|
||||
@@ -1146,7 +1170,6 @@ advLayerStep:
|
||||
clientConn, err = grpc.DialNewSubConn(client.Path(), grpcClientConn, &realTargetAddr)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("grpc.DialNewSubConn failed"); ce != nil {
|
||||
//log.Printf("grpc.DialNewSubConn failed,%s\n", err)
|
||||
|
||||
ce.Write(zap.Error(err))
|
||||
|
||||
@@ -1171,8 +1194,7 @@ advLayerStep:
|
||||
edBuf = edBuf[:ws.MaxEarlyDataLen]
|
||||
n, e := wlc.Read(edBuf)
|
||||
if e != nil {
|
||||
if ce := utils.CanLogErr("reading ws early data"); ce != nil {
|
||||
//log.Printf("err when reading ws early data %s\n", e)
|
||||
if ce := utils.CanLogErr("failed to read ws early data"); ce != nil {
|
||||
ce.Write(zap.Error(e))
|
||||
}
|
||||
return nil, utils.NumErr{N: 7, Prefix: "dialClient err, "}
|
||||
@@ -1195,11 +1217,9 @@ advLayerStep:
|
||||
wc, err = wsClient.Handshake(clientConn)
|
||||
|
||||
}
|
||||
//wc, err := wsClient.Handshake(clientConn, ed)
|
||||
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("failed in handshake ws"); ce != nil {
|
||||
//log.Printf("failed in handshake ws to %s , Reason: %s\n", targetAddr.String(), err)
|
||||
|
||||
ce.Write(
|
||||
zap.String("target", targetAddr.String()),
|
||||
zap.Error(err),
|
||||
@@ -1217,8 +1237,6 @@ advLayerStep:
|
||||
wrc, err := client.Handshake(clientConn, targetAddr)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("failed in handshake"); ce != nil {
|
||||
//log.Printf("failed in handshake to %s , Reason: %s\n", targetAddr.String(), err)
|
||||
|
||||
ce.Write(
|
||||
zap.String("target", targetAddr.String()),
|
||||
zap.Error(err),
|
||||
|
||||
+65
-26
@@ -3,6 +3,7 @@ package netLayer
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/utils"
|
||||
@@ -10,12 +11,28 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func DNSQuery(domain string, dns_type uint16, conn *dns.Conn, recursionCount int) net.IP {
|
||||
var globalDnsQueryMutex sync.Mutex
|
||||
|
||||
//domain必须是 dns.Fqdn 函数 包过的, 本函数不检查是否包过。如果不包过就传入,会报错。
|
||||
// dns_type 为 miekg/dns 包中定义的类型, 如 TypeA, TypeAAAA, TypeCNAME.
|
||||
// conn是一个建立好的 dns.Conn, 必须非空, 本函数不检查.
|
||||
// theMux是与 conn相匹配的mutex, 这是为了防止同时有多个请求导致无法对口;内部若判断为nil,会主动使用一个全局mux.
|
||||
// recursionCount 使用者统一填0 即可,用于内部 遇到cname时进一步查询时防止无限递归.
|
||||
func DNSQuery(domain string, dns_type uint16, conn *dns.Conn, theMux *sync.Mutex, recursionCount int) net.IP {
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion((domain), dns_type) //为了更快,不使用 dns.Fqdn, 请调用之前先确保ok
|
||||
c := new(dns.Client)
|
||||
|
||||
if theMux == nil {
|
||||
theMux = &globalDnsQueryMutex
|
||||
}
|
||||
|
||||
theMux.Lock()
|
||||
|
||||
r, _, err := c.ExchangeWithConn(m, conn)
|
||||
|
||||
theMux.Unlock()
|
||||
|
||||
if r == nil {
|
||||
if ce := utils.CanLogErr("dns query read err"); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
@@ -56,44 +73,52 @@ func DNSQuery(domain string, dns_type uint16, conn *dns.Conn, recursionCount int
|
||||
|
||||
if recursionCount > 2 {
|
||||
//不准循环递归,否则就是bug;因为有可能两个域名cname相互指向对方,好坏
|
||||
if ce := utils.CanLogDebug("dns query got cname bug recursionCount>2"); ce != nil {
|
||||
ce.Write(zap.String("query", domain), zap.String("target", aa.Target))
|
||||
if ce := utils.CanLogDebug("dns query got cname but recursionCount>2"); ce != nil {
|
||||
ce.Write(zap.String("query", domain), zap.String("cname", aa.Target))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return DNSQuery(aa.Target, dns_type, conn, recursionCount+1)
|
||||
return DNSQuery(dns.Fqdn(aa.Target), dns_type, conn, theMux, recursionCount+1)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 给 miekg/dns.Conn 加一个互斥锁, 可保证同一时间仅有一个请求发生
|
||||
// 这样就不会造成并发时的混乱
|
||||
type DnsConn struct {
|
||||
*dns.Conn
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
//dns machine维持与多个dns服务器的连接(最好是udp这种无状态的),并可以发起dns请求
|
||||
// 会缓存dns记录
|
||||
type DNSMachine struct {
|
||||
DefaultConn *dns.Conn
|
||||
conns map[string]*dns.Conn
|
||||
DefaultConn DnsConn
|
||||
conns map[string]*DnsConn
|
||||
cache map[string]net.IP
|
||||
|
||||
SpecialIPPollicy map[string][]netip.Addr
|
||||
|
||||
SpecialServerPollicy map[string]string //domain -> dns server name 的map
|
||||
|
||||
mux sync.RWMutex
|
||||
mutex sync.RWMutex //读写 conns, cache, SpecialIPPollicy, SpecialServerPollicy 时所使用的 mutex
|
||||
|
||||
}
|
||||
|
||||
//并不初始化所有内部成员
|
||||
func NewDnsMachine(defaultAddr *Addr) *DNSMachine {
|
||||
//并不初始化所有内部成员, 只是创建并拨个号,若为nil则号也不拨
|
||||
func NewDnsMachine(defaultDnsServerAddr *Addr) *DNSMachine {
|
||||
var dm DNSMachine
|
||||
if defaultAddr != nil {
|
||||
if defaultDnsServerAddr != nil {
|
||||
|
||||
var conn net.Conn
|
||||
var err error
|
||||
|
||||
if defaultAddr.IsUDP() {
|
||||
conn, err = net.DialUDP("udp", nil, defaultAddr.ToUDPAddr())
|
||||
if defaultDnsServerAddr.IsUDP() {
|
||||
conn, err = net.DialUDP("udp", nil, defaultDnsServerAddr.ToUDPAddr())
|
||||
} else {
|
||||
conn, err = defaultAddr.Dial()
|
||||
conn, err = defaultDnsServerAddr.Dial()
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
@@ -104,15 +129,15 @@ func NewDnsMachine(defaultAddr *Addr) *DNSMachine {
|
||||
|
||||
dc := new(dns.Conn)
|
||||
dc.Conn = conn
|
||||
dm.DefaultConn = dc
|
||||
dm.DefaultConn.Conn = dc
|
||||
}
|
||||
|
||||
return &dm
|
||||
}
|
||||
|
||||
func (dm *DNSMachine) SetDefaultConn(c net.Conn) {
|
||||
dm.DefaultConn = new(dns.Conn)
|
||||
dm.DefaultConn.Conn = c
|
||||
dm.DefaultConn.Conn = new(dns.Conn)
|
||||
dm.DefaultConn.Conn.Conn = c
|
||||
}
|
||||
|
||||
//name为该dns服务器的名称
|
||||
@@ -120,28 +145,38 @@ func (dm *DNSMachine) AddConnForServer(name string, c net.Conn) {
|
||||
dc := new(dns.Conn)
|
||||
dc.Conn = c
|
||||
if dm.conns == nil {
|
||||
dm.conns = make(map[string]*dns.Conn)
|
||||
dm.conns = map[string]*DnsConn{}
|
||||
}
|
||||
dm.conns[name] = dc
|
||||
dcc := &DnsConn{Conn: dc}
|
||||
dm.conns[name] = dcc
|
||||
}
|
||||
|
||||
//传入的domain必须是不带尾缀点号的domain, 即没有包过 Fqdn
|
||||
func (dm *DNSMachine) Query(domain string, dns_type uint16) (ip net.IP) {
|
||||
var cacheHit bool
|
||||
defer func() {
|
||||
if len(ip) > 0 {
|
||||
//log.Println("will add to cache", domain, ip)
|
||||
if cacheHit {
|
||||
return
|
||||
}
|
||||
|
||||
dm.mux.Lock()
|
||||
if len(ip) > 0 {
|
||||
if ce := utils.CanLogDebug("will add to dns cache"); ce != nil {
|
||||
ce.Write(zap.String("domain", domain))
|
||||
}
|
||||
|
||||
dm.mutex.Lock()
|
||||
if dm.cache == nil {
|
||||
|
||||
dm.cache = make(map[string]net.IP)
|
||||
}
|
||||
domain = strings.TrimSuffix(domain, ".")
|
||||
dm.cache[domain] = ip
|
||||
dm.mux.Unlock()
|
||||
dm.mutex.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
dm.mux.RLock()
|
||||
defer dm.mux.RUnlock()
|
||||
dm.mutex.RLock()
|
||||
defer dm.mutex.RUnlock()
|
||||
|
||||
//先从 cache找,有就直接返回
|
||||
//然后,
|
||||
@@ -152,6 +187,10 @@ func (dm *DNSMachine) Query(domain string, dns_type uint16) (ip net.IP) {
|
||||
|
||||
if dm.cache != nil {
|
||||
if ip = dm.cache[domain]; ip != nil {
|
||||
cacheHit = true
|
||||
if ce := utils.CanLogDebug("hit dns cache"); ce != nil {
|
||||
ce.Write(zap.String("domain", domain))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -180,7 +219,7 @@ func (dm *DNSMachine) Query(domain string, dns_type uint16) (ip net.IP) {
|
||||
}
|
||||
}
|
||||
|
||||
theDNSServerConn := dm.DefaultConn
|
||||
theDNSServerConn := &dm.DefaultConn
|
||||
if dm.conns != nil && dm.SpecialServerPollicy != nil {
|
||||
|
||||
if sn := dm.SpecialServerPollicy[domain]; sn != "" {
|
||||
@@ -192,5 +231,5 @@ func (dm *DNSMachine) Query(domain string, dns_type uint16) (ip net.IP) {
|
||||
}
|
||||
|
||||
domain = dns.Fqdn(domain)
|
||||
return DNSQuery(domain, dns_type, theDNSServerConn, 0)
|
||||
return DNSQuery(domain, dns_type, theDNSServerConn.Conn, &theDNSServerConn.mutex, 0)
|
||||
}
|
||||
|
||||
+18
-14
@@ -1,4 +1,4 @@
|
||||
/*Package proxy 定义了代理转发所需的必备组件.
|
||||
/*Package proxy defines necessary components for proxy.
|
||||
|
||||
Layer Definition
|
||||
|
||||
@@ -24,21 +24,25 @@ New Model - VSI 新的VSI 模型
|
||||
那么我们verysimple实际上就是 基于 “层” 的架构,或称 可分层结构.
|
||||
|
||||
|
||||
9 | tcp data
|
||||
--------------------
|
||||
8 | vless/trojan/socks5
|
||||
--------------------
|
||||
7 | ws/grpc
|
||||
--------------------
|
||||
6 | http
|
||||
--------------------
|
||||
5 | tls
|
||||
--------------------
|
||||
4 | tcp
|
||||
--------------------
|
||||
9 | client real tcp data
|
||||
----------------------------------------
|
||||
8 | vless/trojan/socks5
|
||||
----------------------------------------
|
||||
7 | ws/grpc/quic
|
||||
----------------------------------------
|
||||
6 | http (headers)
|
||||
----------------------------------------
|
||||
5 | tls
|
||||
----------------------------------------
|
||||
4 | tcp/udp/unix domain socket
|
||||
----------------------------------------
|
||||
|
||||
|
||||
基本上5-8层都是可控的.
|
||||
基本上5-8层都是可控的.第四层也可以给出一些参数进行控制,比如在tproxy时。
|
||||
|
||||
实际上quic属于一种超级协议,横跨传输层一直到高级层,不过为了分类方便,这里认为它也是一种 高级层.
|
||||
|
||||
也就是说,如果遇到横跨多个层的协议,我们认为它属于其中最高的层级。
|
||||
|
||||
对应的理想配置文件应该如下.
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWrit
|
||||
|
||||
//log.Println("尝试拨号 Cmd_CRUMFURS 信道")
|
||||
|
||||
//这段代码明显有问题,如果直接dial的话,那就是脱离tls的裸协议,所以这里以后需要处理一下
|
||||
UMFURS_conn, err := target.Dial()
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("尝试拨号 Cmd_CRUMFURS 信道时发生错误"); ce != nil {
|
||||
|
||||
@@ -160,7 +160,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
count := 0
|
||||
|
||||
for {
|
||||
t.Log(" udp for! ")
|
||||
//t.Log(" udp for! ")
|
||||
// 读取数据
|
||||
readNum, remoteAddr, err := fakeRealUDPServerListener.ReadFromUDP(readbuf)
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
//Package quic 实现高级层中的quic
|
||||
//Package quic defines functions to listen and dial quic, with some customizable congestion settings.
|
||||
package quic
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Package tlsLayer 提供tls层的各种支持. 也包括tls流量的嗅探功能
|
||||
Package tlsLayer provides support for tlsLayer, including sniffing.
|
||||
*/
|
||||
package tlsLayer
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Package utils provides utils that needed by all sub-packages in verysimle
|
||||
// Package utils provides utilities that is used in all sub-packages in verysimple
|
||||
package utils
|
||||
|
||||
import (
|
||||
|
||||
+5
-7
@@ -47,7 +47,7 @@ func (c *Conn) Read(p []byte) (int, error) {
|
||||
// https://www.rfc-editor.org/rfc/rfc6455#section-5.2
|
||||
// (使用了 Extended payload length 字段)
|
||||
// 肯定会有多读的情况,此时如果一次用 wsutil.ReadServerBinary()的话,那么服务器缓存就超大,不可能如此实现
|
||||
// (wsutil.ReadServerBinary内部使用了 io.ReadAll, 而ReadAll是会无限增长内存的
|
||||
// ( wsutil.ReadServerBinary内部使用了 io.ReadAll, 而ReadAll是会无限增长内存的 )
|
||||
// 所以我们肯定要分段读, 直接用 wsutil.Reader.Read 即可, 但是每个Read前必须要有 NextFrame调用
|
||||
//
|
||||
//关于读 的完整过程,建议参考 ws/example.autoban.go 里的 wsHandler 函数
|
||||
@@ -70,7 +70,6 @@ func (c *Conn) Read(p []byte) (int, error) {
|
||||
}
|
||||
if h.OpCode.IsControl() {
|
||||
//log.Println("Got control frame")
|
||||
//return 0, nil
|
||||
|
||||
// 控制帧已经在我们的 OnIntermediate 里被处理了, 直接读取下一个数据即可
|
||||
return c.Read(p)
|
||||
@@ -88,8 +87,7 @@ func (c *Conn) Read(p []byte) (int, error) {
|
||||
OpPong OpCode = 0xa
|
||||
*/
|
||||
|
||||
//log.Println("OpCode not Binary", h.OpCode)
|
||||
return 0, utils.ErrInErr{ErrDesc: "ws OpCode not Binary", Data: h.OpCode}
|
||||
return 0, utils.ErrInErr{ErrDesc: "ws OpCode not OpBinary/OpContinuation", Data: h.OpCode}
|
||||
}
|
||||
//log.Println("Read next frame header ok,", h.Length, c.r.State.Fragmented(), "givenbuf len", len(p))
|
||||
|
||||
@@ -102,9 +100,9 @@ func (c *Conn) Read(p []byte) (int, error) {
|
||||
|
||||
// 但是后来发现,只有 fragmented的情况下,才会处理EOF,否则还是会传递到我们这里
|
||||
// 也就是说,websocket虽然一个数据帧可以超大,但是 还有一种 分片功能,而如果不分片的话,gobwas就不处理EOF
|
||||
//经过实测,如果数据比较小的话,就不会分片,此时就会出现EOF; 如果数据比较大,比如 4327,就要分片
|
||||
//经过实测,如果数据比较小的话,就不会分片,此时就会出现EOF; 如果数据比较大,比如 4327,某客户端就可能选择分片
|
||||
|
||||
//这种产生EOF的情况,时 gobwas/ws包的一种特性,这样可以说每一次读取都能有明确的EOF边界,便于使用 io.ReadAll
|
||||
//这种产生EOF的情况,是 gobwas/ws包的一种特性,这样可以说每一次读取都能有明确的EOF边界,便于使用 io.ReadAll
|
||||
|
||||
n, e := c.r.Read(p)
|
||||
//log.Println("read data result", e, n, h.Length)
|
||||
@@ -169,7 +167,7 @@ func (c *Conn) ReadFrom(r io.Reader) (written int64, err error) {
|
||||
if rt, ok := c.Conn.(io.ReaderFrom); ok {
|
||||
return rt.ReadFrom(r)
|
||||
} else {
|
||||
panic("uc.underlayIsBasic, but can't cast to ReadFrom")
|
||||
panic("ws.Conn underlayIsBasic, but can't cast to ReadFrom")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// 2048 /3 = 682.6666 ,
|
||||
// 683 * 4 = 2732
|
||||
// 683 * 4 = 2732, 若你不信,运行 we_test.go中的 TestBase64Len
|
||||
const MaxEarlyDataLen_Base64 = 2732
|
||||
|
||||
type Server struct {
|
||||
|
||||
@@ -3,6 +3,7 @@ package ws_test
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
@@ -10,6 +11,13 @@ import (
|
||||
"github.com/hahahrfool/v2ray_simple/ws"
|
||||
)
|
||||
|
||||
func TestBase64Len(t *testing.T) {
|
||||
var arr [2048]byte
|
||||
str := base64.StdEncoding.EncodeToString(arr[:])
|
||||
t.Log(len(str)) //2732
|
||||
//t.Log((str)) //一堆A后面跟一个等号
|
||||
}
|
||||
|
||||
// ws基本读写功能测试.
|
||||
// 分别测试写入短数据和长数据
|
||||
func TestWs(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user