diff --git a/app/cmd/client.go b/app/cmd/client.go index 857b068..004e328 100644 --- a/app/cmd/client.go +++ b/app/cmd/client.go @@ -31,11 +31,11 @@ import ( ) var clientPacketConnFuncFactoryMap = map[string]pktconns.ClientPacketConnFuncFactory{ - "": pktconns.NewClientUDPConnFunc, - "udp": pktconns.NewClientUDPConnFunc, - "wechat": pktconns.NewClientWeChatConnFunc, - "wechat-video": pktconns.NewClientWeChatConnFunc, - "faketcp": pktconns.NewClientFakeTCPConnFunc, + "": pktconns.NewClientUDPConnFunc, + "udp": pktconns.NewClientUDPConnFunc, + // "wechat": pktconns.NewClientWeChatConnFunc, + // "wechat-video": pktconns.NewClientWeChatConnFunc, + // "faketcp": pktconns.NewClientFakeTCPConnFunc, } func client(config *clientConfig) { diff --git a/app/cmd/server.go b/app/cmd/server.go index c54cbc5..0b72198 100644 --- a/app/cmd/server.go +++ b/app/cmd/server.go @@ -25,11 +25,11 @@ import ( ) var serverPacketConnFuncFactoryMap = map[string]pktconns.ServerPacketConnFuncFactory{ - "": pktconns.NewServerUDPConnFunc, - "udp": pktconns.NewServerUDPConnFunc, - "wechat": pktconns.NewServerWeChatConnFunc, - "wechat-video": pktconns.NewServerWeChatConnFunc, - "faketcp": pktconns.NewServerFakeTCPConnFunc, + "": pktconns.NewServerUDPConnFunc, + "udp": pktconns.NewServerUDPConnFunc, + // "wechat": pktconns.NewServerWeChatConnFunc, + // "wechat-video": pktconns.NewServerWeChatConnFunc, + // "faketcp": pktconns.NewServerFakeTCPConnFunc, } func server(config *serverConfig) { diff --git a/app/go.mod b/app/go.mod index cc6947b..4a4d1e7 100644 --- a/app/go.mod +++ b/app/go.mod @@ -29,12 +29,10 @@ require ( github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/coreos/go-iptables v0.6.0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -92,7 +90,7 @@ require ( replace github.com/apernet/hysteria/core => ../core/ -replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c +replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b replace github.com/LiamHaworth/go-tproxy => github.com/apernet/go-tproxy v0.0.0-20221025153553-ed04a2935f88 diff --git a/app/go.sum b/app/go.sum index 485cc4d..d76dea2 100644 --- a/app/go.sum +++ b/app/go.sum @@ -51,8 +51,8 @@ github.com/apernet/go-tproxy v0.0.0-20221025153553-ed04a2935f88 h1:YNsl7PMiU9x/0 github.com/apernet/go-tproxy v0.0.0-20221025153553-ed04a2935f88/go.mod h1:uxH+nFzlJug5OHjPYmzKwvVVb9wOToeGuLNVeerwWtc= github.com/apernet/goproxy v0.0.0-20221124043924-155acfaf278f h1:v3Bn97M5KWzdVajNphf3PxoHdsRF/RzBVovIsH/DEvY= github.com/apernet/goproxy v0.0.0-20221124043924-155acfaf278f/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= -github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c h1:YoKqNVd+1knWdkYD/VjDNgEV+5FDAXTylFWAZV9PAa0= -github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= +github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b h1:Z49X7P2v8otyir1SAcAbbEzVZNn+AiYwInpf0dbhBJI= +github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b/go.mod h1:NVsR0x0u2DwoSL69OKbkbiF2vljWREImECy9jD04+R0= 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= @@ -72,8 +72,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= -github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -155,8 +153,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= diff --git a/core/go.mod b/core/go.mod index a3a01d6..b78f4fc 100644 --- a/core/go.mod +++ b/core/go.mod @@ -43,4 +43,4 @@ require ( google.golang.org/protobuf v1.28.1 // indirect ) -replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c +replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b diff --git a/core/go.sum b/core/go.sum index 607816e..50024d4 100644 --- a/core/go.sum +++ b/core/go.sum @@ -38,8 +38,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c h1:YoKqNVd+1knWdkYD/VjDNgEV+5FDAXTylFWAZV9PAa0= -github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= +github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b h1:Z49X7P2v8otyir1SAcAbbEzVZNn+AiYwInpf0dbhBJI= +github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b/go.mod h1:NVsR0x0u2DwoSL69OKbkbiF2vljWREImECy9jD04+R0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/core/pktconns/funcs.go b/core/pktconns/funcs.go index b0675f1..47d731b 100644 --- a/core/pktconns/funcs.go +++ b/core/pktconns/funcs.go @@ -5,10 +5,8 @@ import ( "strings" "time" - "github.com/apernet/hysteria/core/pktconns/faketcp" "github.com/apernet/hysteria/core/pktconns/obfs" "github.com/apernet/hysteria/core/pktconns/udp" - "github.com/apernet/hysteria/core/pktconns/wechat" ) type ( @@ -54,6 +52,7 @@ func NewClientUDPConnFunc(obfsPassword string, hopInterval time.Duration) Client } } +/* func NewClientWeChatConnFunc(obfsPassword string, hopInterval time.Duration) ClientPacketConnFunc { if obfsPassword == "" { return func(server string) (net.PacketConn, net.Addr, error) { @@ -108,6 +107,7 @@ func NewClientFakeTCPConnFunc(obfsPassword string, hopInterval time.Duration) Cl } } } +*/ func NewServerUDPConnFunc(obfsPassword string) ServerPacketConnFunc { if obfsPassword == "" { @@ -134,6 +134,7 @@ func NewServerUDPConnFunc(obfsPassword string) ServerPacketConnFunc { } } +/* func NewServerWeChatConnFunc(obfsPassword string) ServerPacketConnFunc { if obfsPassword == "" { return func(listen string) (net.PacketConn, error) { @@ -179,6 +180,7 @@ func NewServerFakeTCPConnFunc(obfsPassword string) ServerPacketConnFunc { } } } +*/ func isMultiPortAddr(addr string) bool { _, portStr, err := net.SplitHostPort(addr) diff --git a/core/pktconns/obfs/obfs.go b/core/pktconns/obfs/obfs.go index 2829560..3ef4243 100644 --- a/core/pktconns/obfs/obfs.go +++ b/core/pktconns/obfs/obfs.go @@ -5,54 +5,73 @@ import ( "math/rand" "sync" "time" + + "github.com/lucas-clemente/quic-go" ) -type Obfuscator interface { - Deobfuscate(in []byte, out []byte) int - Obfuscate(in []byte, out []byte) int -} - -const xpSaltLen = 16 +const ( + xpSaltLen = 16 + udpBufferSize = 4096 +) // XPlusObfuscator obfuscates payload using one-time keys generated from hashing a pre-shared key and random salt. // Packet format: [salt][obfuscated payload] type XPlusObfuscator struct { - Key []byte - RandSrc *rand.Rand - - lk sync.Mutex + key []byte + randSrc *rand.Rand + randLk sync.Mutex + bufPool sync.Pool + saltPool sync.Pool } -func NewXPlusObfuscator(key []byte) *XPlusObfuscator { +func NewXPlusObfuscator(key []byte) quic.Obfuscator { return &XPlusObfuscator{ - Key: key, - RandSrc: rand.New(rand.NewSource(time.Now().UnixNano())), + key: key, + randSrc: rand.New(rand.NewSource(time.Now().UnixNano())), + bufPool: sync.Pool{New: func() interface{} { return make([]byte, udpBufferSize) }}, + saltPool: sync.Pool{New: func() interface{} { return make([]byte, xpSaltLen) }}, } } -func (x *XPlusObfuscator) Deobfuscate(in []byte, out []byte) int { - outLen := len(in) - xpSaltLen - if outLen <= 0 || len(out) < outLen { - return 0 +func (x *XPlusObfuscator) Obfuscate(data []byte, scat bool) ([][]byte, func()) { + if scat { + salt := x.saltPool.Get().([]byte) + x.randLk.Lock() + _, _ = x.randSrc.Read(salt) + x.randLk.Unlock() + key := sha256.Sum256(append(x.key, salt...)) + buf := x.bufPool.Get().([]byte) + for i, c := range data { + buf[i] = c ^ key[i%sha256.Size] + } + payload := buf[:len(data)] + return [][]byte{salt, payload}, func() { + x.saltPool.Put(salt) + x.bufPool.Put(buf) + } + } else { + buf := x.bufPool.Get().([]byte) + x.randLk.Lock() + _, _ = x.randSrc.Read(buf[:xpSaltLen]) + x.randLk.Unlock() + key := sha256.Sum256(append(x.key, buf[:xpSaltLen]...)) + for i, c := range data { + buf[i+xpSaltLen] = c ^ key[i%sha256.Size] + } + payload := buf[:xpSaltLen+len(data)] + return [][]byte{payload}, func() { + x.bufPool.Put(buf) + } } - key := sha256.Sum256(append(x.Key, in[:xpSaltLen]...)) - for i, c := range in[xpSaltLen:] { - out[i] = c ^ key[i%sha256.Size] - } - return outLen } -func (x *XPlusObfuscator) Obfuscate(in []byte, out []byte) int { - outLen := len(in) + xpSaltLen - if len(out) < outLen { +func (x *XPlusObfuscator) Deobfuscate(data []byte) int { + if len(data) <= xpSaltLen { return 0 } - x.lk.Lock() - _, _ = x.RandSrc.Read(out[:xpSaltLen]) - x.lk.Unlock() - key := sha256.Sum256(append(x.Key, out[:xpSaltLen]...)) - for i, c := range in { - out[i+xpSaltLen] = c ^ key[i%sha256.Size] + key := sha256.Sum256(append(x.key, data[:xpSaltLen]...)) + for i, c := range data[xpSaltLen:] { + data[i] = c ^ key[i%sha256.Size] } - return outLen + return len(data) - xpSaltLen } diff --git a/core/pktconns/obfs/obfs_test.go b/core/pktconns/obfs/obfs_test.go index c1cf629..9418b0c 100644 --- a/core/pktconns/obfs/obfs_test.go +++ b/core/pktconns/obfs/obfs_test.go @@ -18,13 +18,35 @@ func TestXPlusObfuscator(t *testing.T) { "And by opposing end them. To die—to sleep,\nNo more; and by a sleep to say we end")}, {name: "empty", p: []byte("")}, } + // Non-scat for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - buf := make([]byte, 10240) - n := x.Obfuscate(tt.p, buf) - n2 := x.Deobfuscate(buf[:n], buf[n:]) - if !bytes.Equal(tt.p, buf[n:n+n2]) { - t.Errorf("Inconsistent deobfuscate result: got %v, want %v", buf[n:n+n2], tt.p) + bb, _ := x.Obfuscate(tt.p, false) + if len(bb) != 1 { + t.Errorf("Incorrect number of buffers returned: %d", len(bb)) + } + n := x.Deobfuscate(bb[0]) + if !bytes.Equal(tt.p, bb[0][:n]) { + t.Errorf("Inconsistent deobfuscation: %s", string(bb[0][:n])) + } + }) + } + // Scat + for _, tt := range tests { + t.Run("scat-"+tt.name, func(t *testing.T) { + bb, _ := x.Obfuscate(tt.p, true) + if len(bb) != 2 { + t.Errorf("Incorrect number of buffers returned: %d", len(bb)) + } + if len(bb[0]) != xpSaltLen || len(bb[1]) != len(tt.p) { + t.Errorf("Incorrect buffer length: %d, %d", len(bb[0]), len(bb[1])) + } + var data []byte + data = append(data, bb[0]...) + data = append(data, bb[1]...) + n := x.Deobfuscate(data) + if !bytes.Equal(tt.p, data[:n]) { + t.Errorf("Inconsistent deobfuscation: %s", string(bb[0][:n])) } }) } diff --git a/core/pktconns/udp/hop.go b/core/pktconns/udp/hop.go index 4458131..ce7f438 100644 --- a/core/pktconns/udp/hop.go +++ b/core/pktconns/udp/hop.go @@ -10,7 +10,7 @@ import ( "syscall" "time" - "github.com/apernet/hysteria/core/pktconns/obfs" + "github.com/lucas-clemente/quic-go" ) const ( @@ -24,7 +24,7 @@ type ObfsUDPHopClientPacketConn struct { serverAddrs []net.Addr hopInterval time.Duration - obfs obfs.Obfuscator + quic.Obfuscator connMutex sync.RWMutex prevConn net.PacketConn @@ -57,7 +57,7 @@ type udpPacket struct { addr net.Addr } -func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obfs obfs.Obfuscator) (*ObfsUDPHopClientPacketConn, net.Addr, error) { +func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obfs quic.Obfuscator) (*ObfsUDPHopClientPacketConn, net.Addr, error) { host, ports, err := parseAddr(server) if err != nil { return nil, nil, err @@ -79,7 +79,7 @@ func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obf serverAddr: &hopAddr, serverAddrs: serverAddrs, hopInterval: hopInterval, - obfs: obfs, + Obfuscator: obfs, addrIndex: rand.Intn(len(serverAddrs)), recvQueue: make(chan *udpPacket, packetQueueSize), closeChan: make(chan struct{}), @@ -155,11 +155,7 @@ func (c *ObfsUDPHopClientPacketConn) hop() { _ = c.prevConn.Close() // recvRoutine will exit on error } c.prevConn = c.currentConn - if c.obfs != nil { - c.currentConn = NewObfsUDPConn(newConn, c.obfs) - } else { - c.currentConn = newConn - } + c.currentConn = newConn // Set buffer sizes if previously set if c.readBufferSize > 0 { _ = trySetPacketConnReadBuffer(c.currentConn, c.readBufferSize) diff --git a/core/pktconns/udp/obfs.go b/core/pktconns/udp/obfs.go index 9f1165e..5346eda 100644 --- a/core/pktconns/udp/obfs.go +++ b/core/pktconns/udp/obfs.go @@ -2,99 +2,20 @@ package udp import ( "net" - "os" - "sync" - "syscall" - "time" - "github.com/apernet/hysteria/core/pktconns/obfs" + "github.com/lucas-clemente/quic-go" ) const udpBufferSize = 4096 -type ObfsUDPPacketConn struct { - orig *net.UDPConn - obfs obfs.Obfuscator - - readBuf []byte - readMutex sync.Mutex - writeBuf []byte - writeMutex sync.Mutex +type ObfsUDPConn struct { + net.UDPConn + quic.Obfuscator } -func NewObfsUDPConn(orig *net.UDPConn, obfs obfs.Obfuscator) *ObfsUDPPacketConn { - return &ObfsUDPPacketConn{ - orig: orig, - obfs: obfs, - readBuf: make([]byte, udpBufferSize), - writeBuf: make([]byte, udpBufferSize), +func NewObfsUDPConn(udpConn *net.UDPConn, obfs quic.Obfuscator) *ObfsUDPConn { + return &ObfsUDPConn{ + UDPConn: *udpConn, + Obfuscator: obfs, } } - -func (c *ObfsUDPPacketConn) ReadFrom(p []byte) (int, net.Addr, error) { - for { - c.readMutex.Lock() - n, addr, err := c.orig.ReadFrom(c.readBuf) - if n <= 0 { - c.readMutex.Unlock() - return 0, addr, err - } - newN := c.obfs.Deobfuscate(c.readBuf[:n], p) - c.readMutex.Unlock() - if newN > 0 { - // Valid packet - return newN, addr, err - } else if err != nil { - // Not valid and orig.ReadFrom had some error - return 0, addr, err - } - } -} - -func (c *ObfsUDPPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { - c.writeMutex.Lock() - bn := c.obfs.Obfuscate(p, c.writeBuf) - _, err = c.orig.WriteTo(c.writeBuf[:bn], addr) - c.writeMutex.Unlock() - if err != nil { - return 0, err - } else { - return len(p), nil - } -} - -func (c *ObfsUDPPacketConn) Close() error { - return c.orig.Close() -} - -func (c *ObfsUDPPacketConn) LocalAddr() net.Addr { - return c.orig.LocalAddr() -} - -func (c *ObfsUDPPacketConn) SetDeadline(t time.Time) error { - return c.orig.SetDeadline(t) -} - -func (c *ObfsUDPPacketConn) SetReadDeadline(t time.Time) error { - return c.orig.SetReadDeadline(t) -} - -func (c *ObfsUDPPacketConn) SetWriteDeadline(t time.Time) error { - return c.orig.SetWriteDeadline(t) -} - -func (c *ObfsUDPPacketConn) SetReadBuffer(bytes int) error { - return c.orig.SetReadBuffer(bytes) -} - -func (c *ObfsUDPPacketConn) SetWriteBuffer(bytes int) error { - return c.orig.SetWriteBuffer(bytes) -} - -func (c *ObfsUDPPacketConn) SyscallConn() (syscall.RawConn, error) { - return c.orig.SyscallConn() -} - -func (c *ObfsUDPPacketConn) File() (f *os.File, err error) { - return c.orig.File() -} diff --git a/go.work.sum b/go.work.sum index e1fad8c..8cab2f1 100644 --- a/go.work.sum +++ b/go.work.sum @@ -6,7 +6,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= +github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b h1:Z49X7P2v8otyir1SAcAbbEzVZNn+AiYwInpf0dbhBJI= +github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b/go.mod h1:NVsR0x0u2DwoSL69OKbkbiF2vljWREImECy9jD04+R0= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=