mirror of
https://github.com/fumiama/dnskip.git
synced 2026-06-05 00:32:41 +08:00
fix: too many conn in parallel
This commit is contained in:
12
go.mod
12
go.mod
@@ -1,17 +1,17 @@
|
||||
module github.com/fumiama/dnskip
|
||||
|
||||
go 1.22
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d
|
||||
github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5
|
||||
github.com/fumiama/terasu v1.0.2
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d // indirect
|
||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/sys v0.23.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
)
|
||||
|
||||
26
go.sum
26
go.sum
@@ -2,7 +2,6 @@ github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d h1:mUQ/c3wXKsUGa4Sg9
|
||||
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
|
||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5 h1:j9o0XVvdAeLwrBYMnh0SerrMc9CgNU6AGszbsvFzoc0=
|
||||
@@ -11,20 +10,15 @@ github.com/fumiama/terasu v1.0.2 h1:Dxj2vPIgLHyeMlBd61xYHx5Jg8v7k24yg7taNLlK8/8=
|
||||
github.com/fumiama/terasu v1.0.2/go.mod h1:1eHzpL/GJVcOnqEkh1vUbKu2zo6gojSuueUNJ9yHJE0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
83
main.go
83
main.go
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"flag"
|
||||
@@ -9,11 +10,12 @@ import (
|
||||
"math"
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/FloatTech/ttl"
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
"github.com/fumiama/terasu"
|
||||
"github.com/fumiama/terasu/dns"
|
||||
@@ -22,14 +24,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
freeconn = uintptr(0)
|
||||
tlsconnCache = ttl.NewCacheOn(
|
||||
5*time.Minute, [4]func(uint8, net.Conn){
|
||||
nil, nil, func(_ uint8, c net.Conn) {
|
||||
logrus.Warnln("Close idle/error tls conn to", c.RemoteAddr())
|
||||
_ = c.Close()
|
||||
}, nil,
|
||||
})
|
||||
fallback *net.UDPAddr
|
||||
forcefb bool
|
||||
timeout uint
|
||||
@@ -103,7 +97,8 @@ RECONN:
|
||||
func response(cnt uint8, conn *net.UDPConn, addr *net.UDPAddr, payload pbuf.Bytes) {
|
||||
var (
|
||||
err error
|
||||
tlsconn net.Conn
|
||||
cl func()
|
||||
tlsconn *tls.Conn
|
||||
loopcnt = 0
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
@@ -114,12 +109,12 @@ func response(cnt uint8, conn *net.UDPConn, addr *net.UDPAddr, payload pbuf.Byte
|
||||
}
|
||||
|
||||
defer releasefree(cnt)
|
||||
logrus.Debugln(addr, "Run on lock", cnt)
|
||||
logrus.Debugln(addr, "Run thread", cnt)
|
||||
|
||||
REDAIL:
|
||||
ctx, cancel = context.WithTimeout(context.Background(), time.Second*time.Duration(timeout))
|
||||
defer cancel()
|
||||
tlsconn, err = dialtls(cnt, ctx)
|
||||
tlsconn, cl, err = dialtls(cnt, ctx)
|
||||
if err != nil {
|
||||
logrus.Warnln(addr, "Dial DNS server err:", err)
|
||||
return
|
||||
@@ -127,6 +122,8 @@ REDAIL:
|
||||
logrus.Debugln(addr, "Dial to DNS server", tlsconn.RemoteAddr())
|
||||
|
||||
payload.V(func(b []byte) {
|
||||
defer cl()
|
||||
|
||||
var plen [2]byte
|
||||
binary.BigEndian.PutUint16(plen[:], uint16(len(b)))
|
||||
_, err = io.Copy(tlsconn, &net.Buffers{plen[:], b})
|
||||
@@ -162,7 +159,10 @@ REDAIL:
|
||||
return
|
||||
}
|
||||
logrus.Warnln(addr, "Proxy to DNS server err:", err)
|
||||
tlsconnCache.Delete(cnt)
|
||||
atomic.StorePointer(
|
||||
(*unsafe.Pointer)(unsafe.Pointer(&remoconn)),
|
||||
unsafe.Pointer(nil),
|
||||
)
|
||||
loopcnt++
|
||||
if loopcnt < 2 {
|
||||
goto REDAIL
|
||||
@@ -214,17 +214,21 @@ FALLBACK:
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
freeconn = uint32(0)
|
||||
)
|
||||
|
||||
// lockfree is spin update
|
||||
func lockfree() uint8 {
|
||||
old := atomic.LoadUintptr(&freeconn)
|
||||
old := atomic.LoadUint32(&freeconn)
|
||||
for i := uint8(0); i < uint8(unsafe.Sizeof(uintptr(0)))*8; i++ {
|
||||
for old&(1<<i) == 0 { // is free
|
||||
ok := atomic.CompareAndSwapUintptr(&freeconn, old, old|(1<<i))
|
||||
ok := atomic.CompareAndSwapUint32(&freeconn, old, old|(1<<i))
|
||||
if ok {
|
||||
return i
|
||||
}
|
||||
// update latest
|
||||
old = atomic.LoadUintptr(&freeconn)
|
||||
old = atomic.LoadUint32(&freeconn)
|
||||
}
|
||||
}
|
||||
return math.MaxUint8
|
||||
@@ -232,29 +236,52 @@ func lockfree() uint8 {
|
||||
|
||||
// releasefree is spin update
|
||||
func releasefree(i uint8) {
|
||||
old := atomic.LoadUintptr(&freeconn)
|
||||
old := atomic.LoadUint32(&freeconn)
|
||||
for old&(1<<i) != 0 { // is not free
|
||||
ok := atomic.CompareAndSwapUintptr(&freeconn, old, old&^(1<<i))
|
||||
ok := atomic.CompareAndSwapUint32(&freeconn, old, old&^(1<<i))
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
// update latest
|
||||
old = atomic.LoadUintptr(&freeconn)
|
||||
old = atomic.LoadUint32(&freeconn)
|
||||
}
|
||||
logrus.Debugln("Free thread", i)
|
||||
}
|
||||
|
||||
func dialtls(cnt uint8, ctx context.Context) (net.Conn, error) {
|
||||
conn := tlsconnCache.Get(cnt)
|
||||
var (
|
||||
remoconn *tls.Conn
|
||||
connmu sync.Mutex
|
||||
)
|
||||
|
||||
func dialtls(cnt uint8, ctx context.Context) (*tls.Conn, func(), error) {
|
||||
conn := (*tls.Conn)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&remoconn))))
|
||||
if conn != nil {
|
||||
logrus.Debugln("Lock", cnt, "get cached tls conn to", conn.RemoteAddr())
|
||||
return conn, nil
|
||||
logrus.Debugln("Thread", cnt, "get cached tls conn to", conn.RemoteAddr())
|
||||
connmu.Lock()
|
||||
return conn, connmu.Unlock, nil
|
||||
}
|
||||
// slow path
|
||||
connmu.Lock()
|
||||
conn = (*tls.Conn)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&remoconn))))
|
||||
if conn != nil {
|
||||
logrus.Debugln("Thread", cnt, "slowly get cached tls conn to", conn.RemoteAddr())
|
||||
return conn, connmu.Unlock, nil
|
||||
}
|
||||
// dummy nw and addr
|
||||
conn, err := dns.DefaultResolver.Dial(ctx, "", "")
|
||||
connintf, err := dns.DefaultResolver.Dial(ctx, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
connmu.Unlock()
|
||||
return nil, nil, err
|
||||
}
|
||||
tlsconnCache.Set(cnt, conn)
|
||||
logrus.Debugln("Lock", cnt, "set new tls conn to", conn.RemoteAddr())
|
||||
return conn, nil
|
||||
conn = connintf.(*tls.Conn)
|
||||
atomic.StorePointer(
|
||||
(*unsafe.Pointer)(unsafe.Pointer(&remoconn)),
|
||||
unsafe.Pointer(conn),
|
||||
)
|
||||
runtime.SetFinalizer(conn, func(conn *tls.Conn) {
|
||||
logrus.Warnln("Cleanup unused conn to", conn.RemoteAddr())
|
||||
_ = conn.Close()
|
||||
})
|
||||
logrus.Debugln("Thread", cnt, "set new tls conn to", conn.RemoteAddr())
|
||||
return conn, connmu.Unlock, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user