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