pull/2507/merge
yixinin 10 months ago committed by GitHub
commit 0022892403
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -17,6 +17,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/pkg/crontab" "github.com/cloudreve/Cloudreve/v4/pkg/crontab"
"github.com/cloudreve/Cloudreve/v4/pkg/email" "github.com/cloudreve/Cloudreve/v4/pkg/email"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver/onedrive" "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver/onedrive"
"github.com/cloudreve/Cloudreve/v4/pkg/h3"
"github.com/cloudreve/Cloudreve/v4/pkg/logging" "github.com/cloudreve/Cloudreve/v4/pkg/logging"
"github.com/cloudreve/Cloudreve/v4/pkg/setting" "github.com/cloudreve/Cloudreve/v4/pkg/setting"
"github.com/cloudreve/Cloudreve/v4/pkg/util" "github.com/cloudreve/Cloudreve/v4/pkg/util"
@ -46,6 +47,7 @@ type server struct {
dbClient *ent.Client dbClient *ent.Client
config conf.ConfigProvider config conf.ConfigProvider
server *http.Server server *http.Server
h3Servers map[string]*h3.H3Server
kv cache.Driver kv cache.Driver
mailQueue email.Driver mailQueue email.Driver
} }
@ -125,7 +127,12 @@ func (s *server) Start() error {
api := routers.InitRouter(s.dep) api := routers.InitRouter(s.dep)
api.TrustedPlatform = s.config.System().ProxyHeader api.TrustedPlatform = s.config.System().ProxyHeader
s.server = &http.Server{Handler: api}
s.server = &http.Server{
Handler: api,
}
s.h3Servers = make(map[string]*h3.H3Server)
// 如果启用了SSL // 如果启用了SSL
if s.config.SSL().CertPath != "" { if s.config.SSL().CertPath != "" {
@ -155,6 +162,8 @@ func (s *server) Start() error {
return nil return nil
} }
api.POST("/api/v4/p2p/signal", s.handleSignal)
s.logger.Info("Listening to %q", s.config.System().Listen) s.logger.Info("Listening to %q", s.config.System().Listen)
s.server.Addr = s.config.System().Listen s.server.Addr = s.config.System().Listen
if err := s.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { if err := s.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
@ -187,6 +196,12 @@ func (s *server) Close() {
s.logger.Error("Failed to shutdown server: %s", err) s.logger.Error("Failed to shutdown server: %s", err)
} }
} }
for laddr, hs := range s.h3Servers {
err := hs.Shutdown(ctx)
if err != nil {
s.logger.Error("Failed to shutdown h3 server: %s %s", laddr, err)
}
}
if s.kv != nil { if s.kv != nil {
if err := s.kv.Persist(util.DataPath(cache.DefaultCacheFile)); err != nil { if err := s.kv.Persist(util.DataPath(cache.DefaultCacheFile)); err != nil {
@ -222,3 +237,38 @@ func (s *server) runUnix(server *http.Server) error {
return server.Serve(listener) return server.Serve(listener)
} }
func (s *server) handleSignal(c *gin.Context) {
var req struct {
Addr string `json:"addr"`
}
if err := c.BindJSON(&req); err != nil {
c.Status(400)
s.logger.Error("bind req error:%v", err)
return
}
hs, err := h3.NewH3Server()
if err != nil {
c.Status(500)
s.logger.Error("create h3 server error:%v", err)
return
}
hs.Handler = s.server.Handler
localAddr, pubAddr := hs.GetAddrs()
c.String(http.StatusOK, pubAddr)
go func() {
err := h3.PunchHole(localAddr, req.Addr)
if err != nil {
s.logger.Error("punch h3 server error:%v", err)
return
}
s.h3Servers[localAddr] = hs
err = hs.Serve()
if err != nil {
s.logger.Error("punch h3 server error:%v", err)
}
delete(s.h3Servers, localAddr)
}()
}

@ -42,10 +42,13 @@ require (
github.com/juju/ratelimit v1.0.1 github.com/juju/ratelimit v1.0.1
github.com/ks3sdklib/aws-sdk-go v1.6.2 github.com/ks3sdklib/aws-sdk-go v1.6.2
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/libp2p/go-reuseport v0.4.0
github.com/mholt/archives v0.1.3 github.com/mholt/archives v0.1.3
github.com/mojocn/base64Captcha v0.0.0-20190801020520-752b1cd608b2 github.com/mojocn/base64Captcha v0.0.0-20190801020520-752b1cd608b2
github.com/pion/stun/v3 v3.0.0
github.com/pquerna/otp v1.2.0 github.com/pquerna/otp v1.2.0
github.com/qiniu/go-sdk/v7 v7.19.0 github.com/qiniu/go-sdk/v7 v7.19.0
github.com/quic-go/quic-go v0.55.0
github.com/rafaeljusto/redigomock v0.0.0-20191117212112-00b2509252a1 github.com/rafaeljusto/redigomock v0.0.0-20191117212112-00b2509252a1
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/samber/lo v1.38.1 github.com/samber/lo v1.38.1
@ -59,6 +62,7 @@ require (
github.com/wneessen/go-mail v0.7.1 github.com/wneessen/go-mail v0.7.1
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e
golang.org/x/image v0.18.0 golang.org/x/image v0.18.0
golang.org/x/sync v0.17.0
golang.org/x/text v0.30.0 golang.org/x/text v0.30.0
golang.org/x/time v0.5.0 golang.org/x/time v0.5.0
golang.org/x/tools v0.38.0 golang.org/x/tools v0.38.0
@ -132,15 +136,18 @@ require (
github.com/nwaples/rardecode/v2 v2.1.0 // indirect github.com/nwaples/rardecode/v2 v2.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pion/dtls/v3 v3.0.1 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sorairolake/lzip-go v0.3.5 // indirect github.com/sorairolake/lzip-go v0.3.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.0 // indirect github.com/ugorji/go/codec v1.3.0 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect github.com/ulikunitz/xz v0.5.12 // indirect
github.com/wlynxg/anet v0.0.3 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect github.com/zclconf/go-cty v1.8.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect
@ -148,7 +155,6 @@ require (
golang.org/x/crypto v0.43.0 // indirect golang.org/x/crypto v0.43.0 // indirect
golang.org/x/mod v0.29.0 // indirect golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect golang.org/x/net v0.46.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect golang.org/x/sys v0.37.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

@ -655,6 +655,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU= github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU=
@ -784,6 +786,14 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pion/dtls/v3 v3.0.1 h1:0kmoaPYLAo0md/VemjcrAXQiSf8U+tuU3nDYVNpEKaw=
github.com/pion/dtls/v3 v3.0.1/go.mod h1:dfIXcFkKoujDQ+jtd8M6RgqKK3DuaUilm3YatAbGp5k=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -977,6 +987,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
github.com/wlynxg/anet v0.0.3 h1:PvR53psxFXstc12jelG6f1Lv4MWqE0tI76/hHGjh9rg=
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/wneessen/go-mail v0.7.1 h1:rvy63sp14N06/kdGqCYwW8Na5gDCXjTQM1E7So4PuKk= github.com/wneessen/go-mail v0.7.1 h1:rvy63sp14N06/kdGqCYwW8Na5gDCXjTQM1E7So4PuKk=
github.com/wneessen/go-mail v0.7.1/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k= github.com/wneessen/go-mail v0.7.1/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=

@ -1,9 +1,10 @@
package cache package cache
import ( import (
"github.com/stretchr/testify/assert"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
) )
func TestNewMemoStore(t *testing.T) { func TestNewMemoStore(t *testing.T) {

@ -0,0 +1,21 @@
package h3
import (
"net/http"
"sync"
"golang.org/x/sync/syncmap"
)
type server struct {
handler http.Handler
conns syncmap.Map
}
func NewServer(api http.Handler) *server {
return &server{
handler: api,
conns: sync.Map{},
}
}

@ -0,0 +1,56 @@
package h3
import (
"net"
"github.com/libp2p/go-reuseport"
)
func PunchHole(localAddr, remoteAddr string) error {
conn, err := reuseport.ListenPacket("udp4", localAddr)
if err != nil {
return err
}
defer conn.Close()
remoteUDPAddr, err := net.ResolveUDPAddr("udp", remoteAddr)
if err != nil {
return err
}
// tk := time.NewTicker(5 * time.Second)
// defer tk.Stop()
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
// var ch = make(chan bool)
// go func() {
// defer cancel()
// defer func() {
// cancel()
// close(ch)
// }()
// buf := make([]byte, 512)
// for {
// select {
// case <-ctx.Done():
// default:
// conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
// _, raddr, err := conn.ReadFrom(buf)
// if err != nil {
// conn.SetReadDeadline(time.Time{}) // 清除超时
// continue
// }
// if raddr.String() == remoteAddr {
// ch <- true
// return
// }
// conn.SetReadDeadline(time.Time{}) // 清除超时
// }
// }
// }()
conn.WriteTo([]byte("PUNCH"), remoteUDPAddr)
return err
}

@ -0,0 +1,89 @@
package h3
import (
"fmt"
"net"
"time"
"github.com/libp2p/go-reuseport"
"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/http3"
)
type H3Server struct {
*http3.Server
localAddr string
pubAddr string
conn net.PacketConn
incoming chan string
}
func NewH3Server() (*H3Server, error) {
localAddr := "0.0.0.0:0"
localAddr, pubLocalAddr, err := GetPublicAddrWithFallback(localAddr)
if err != nil {
return nil, err
}
conn, err := reuseport.ListenPacket("udp4", localAddr)
if err != nil {
return nil, err
}
tlsConfig := GenerateTLSConfig()
quicConfig := &quic.Config{
KeepAlivePeriod: 15 * time.Second,
EnableDatagrams: true,
MaxIdleTimeout: time.Hour,
}
server := &http3.Server{
Addr: conn.LocalAddr().String(),
QUICConfig: quicConfig,
TLSConfig: tlsConfig,
IdleTimeout: time.Hour,
}
return &H3Server{
localAddr: localAddr,
pubAddr: pubLocalAddr,
conn: conn,
Server: server,
incoming: make(chan string, 1),
}, nil
}
func (s *H3Server) GetAddrs() (string, string) {
return s.localAddr, s.pubAddr
}
func (s *H3Server) Serve() error {
return s.Server.Serve(s.conn)
}
func (s *H3Server) Close() error {
var errs = make([]error, 0, 2)
if s.Server != nil {
if err := s.Close(); err != nil {
errs = append(errs, err)
}
}
if s.conn != nil {
if err := s.conn.Close(); err != nil {
errs = append(errs, err)
}
}
switch len(errs) {
case 0:
return nil
case 1:
return errs[0]
case 2:
return fmt.Errorf("close server err: %v, close conn err: %v", errs[0], errs[1])
}
return nil
}
func (s *H3Server) HandleRemote(remoteAddr string) error {
return PunchHole(s.localAddr, remoteAddr)
}

@ -0,0 +1,150 @@
package h3
import (
"context"
"errors"
"net"
"sync"
"github.com/libp2p/go-reuseport"
"github.com/pion/stun/v3"
)
type stunAddr struct {
localAddr string
pubAddr string
}
// 尝试多个STUN服务器
func GetPublicAddrWithFallback(localAddr string) (string, string, error) {
servers := []string{
"stun.miwifi.com:3478",
"stun.chat.bilibili.com:3478",
"turn.cloudflare.com:3478",
"fwa.lifesizecloud.com:3478",
"stun.isp.net.au:3478",
"stun.voipbusterpro.com:3478",
"stun.freeswitch.org:3478",
"stun.nextcloud.com:3478",
"stun.l.google.com:19302",
"stun.sipnet.com:3478",
}
ctx, cancel := context.WithCancel(context.Background())
var ch = make(chan stunAddr, 1)
defer func() {
cancel()
close(ch)
}()
var wg sync.WaitGroup
for _, server := range servers {
wg.Add(1)
go func(server string) {
defer func() {
recover()
wg.Done()
}()
localAddr, pubAddr, err := getPublicAddr(ctx, localAddr, server)
if err == nil {
select {
case <-ctx.Done():
return
default:
ch <- stunAddr{
localAddr: localAddr,
pubAddr: pubAddr,
}
}
return
}
}(server)
}
go func() {
wg.Wait()
cancel()
}()
select {
case <-ctx.Done():
return "", "", ctx.Err()
case addr, ok := <-ch:
if !ok {
return "", "", errors.New("all STUN servers failed")
}
return addr.localAddr, addr.pubAddr, nil
}
}
type stunConn struct {
net.PacketConn
raddr *net.UDPAddr
}
func (c *stunConn) Write(data []byte) (int, error) {
return c.WriteTo(data, c.raddr)
}
func (c *stunConn) Read(data []byte) (int, error) {
n, _, err := c.PacketConn.ReadFrom(data)
return n, err
}
func getPublicAddr(ctx context.Context, laddr, stunServer string) (localAddr, pubAddr string, err error) {
if laddr == "" {
laddr = "0.0.0.0:0"
}
raddr, err := net.ResolveUDPAddr("udp", stunServer)
if err != nil {
return
}
conn, err := reuseport.ListenPacket("udp4", laddr)
if err != nil {
return
}
defer conn.Close()
client, err := stun.NewClient(&stunConn{
PacketConn: conn,
raddr: raddr,
})
if err != nil {
return
}
defer client.Close()
localAddr = conn.LocalAddr().String()
message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
select {
case <-ctx.Done():
return "", "", ctx.Err()
default:
err = client.Do(message, func(res stun.Event) {
if res.Error != nil {
err = res.Error
return
}
// Decoding XOR-MAPPED-ADDRESS attribute from message.
var xorAddr stun.XORMappedAddress
if err = xorAddr.GetFrom(res.Message); err != nil {
return
}
select {
case <-ctx.Done():
err = ctx.Err()
return
default:
pubAddr = xorAddr.String()
}
})
if err != nil {
return "", "", err
}
}
if err != nil {
return
}
if pubAddr == "" {
return "", "", errors.New("get pun addr fail")
}
return
}

@ -0,0 +1,38 @@
package h3
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"math/big"
"time"
)
func GenerateTLSConfig() *tls.Config {
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
panic(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
panic(err)
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"h3"},
}
}
Loading…
Cancel
Save