github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/common/qtls/wrapper.go (about) 1 package qtls 2 3 import ( 4 "context" 5 "crypto/tls" 6 "net" 7 "net/http" 8 9 "github.com/sagernet/quic-go" 10 "github.com/sagernet/quic-go/http3" 11 M "github.com/sagernet/sing/common/metadata" 12 aTLS "github.com/sagernet/sing/common/tls" 13 ) 14 15 type QUICConfig interface { 16 Dial(ctx context.Context, conn net.PacketConn, addr net.Addr, config *quic.Config) (quic.Connection, error) 17 DialEarly(ctx context.Context, conn net.PacketConn, addr net.Addr, config *quic.Config) (quic.EarlyConnection, error) 18 CreateTransport(conn net.PacketConn, quicConnPtr *quic.EarlyConnection, serverAddr M.Socksaddr, quicConfig *quic.Config, enableDatagrams bool) http.RoundTripper 19 } 20 21 type QUICServerConfig interface { 22 Listen(conn net.PacketConn, config *quic.Config) (QUICListener, error) 23 ListenEarly(conn net.PacketConn, config *quic.Config) (QUICEarlyListener, error) 24 ConfigureHTTP3() 25 } 26 27 type QUICListener interface { 28 Accept(ctx context.Context) (quic.Connection, error) 29 Close() error 30 Addr() net.Addr 31 } 32 33 type QUICEarlyListener interface { 34 Accept(ctx context.Context) (quic.EarlyConnection, error) 35 Close() error 36 Addr() net.Addr 37 } 38 39 func Dial(ctx context.Context, conn net.PacketConn, addr net.Addr, config aTLS.Config, quicConfig *quic.Config) (quic.Connection, error) { 40 if quicTLSConfig, isQUICConfig := config.(QUICConfig); isQUICConfig { 41 return quicTLSConfig.Dial(ctx, conn, addr, quicConfig) 42 } 43 tlsConfig, err := config.Config() 44 if err != nil { 45 return nil, err 46 } 47 return quic.Dial(ctx, conn, addr, tlsConfig, quicConfig) 48 } 49 50 func DialEarly(ctx context.Context, conn net.PacketConn, addr net.Addr, config aTLS.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { 51 if quicTLSConfig, isQUICConfig := config.(QUICConfig); isQUICConfig { 52 return quicTLSConfig.DialEarly(ctx, conn, addr, quicConfig) 53 } 54 tlsConfig, err := config.Config() 55 if err != nil { 56 return nil, err 57 } 58 return quic.DialEarly(ctx, conn, addr, tlsConfig, quicConfig) 59 } 60 61 func CreateTransport(conn net.PacketConn, quicConnPtr *quic.EarlyConnection, serverAddr M.Socksaddr, config aTLS.Config, quicConfig *quic.Config, enableDatagrams bool) (http.RoundTripper, error) { 62 if quicTLSConfig, isQUICConfig := config.(QUICConfig); isQUICConfig { 63 return quicTLSConfig.CreateTransport(conn, quicConnPtr, serverAddr, quicConfig, enableDatagrams), nil 64 } 65 tlsConfig, err := config.Config() 66 if err != nil { 67 return nil, err 68 } 69 return &http3.RoundTripper{ 70 TLSClientConfig: tlsConfig, 71 QuicConfig: quicConfig, 72 EnableDatagrams: enableDatagrams, 73 Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { 74 quicConn, err := quic.DialEarly(ctx, conn, serverAddr.UDPAddr(), tlsCfg, cfg) 75 if err != nil { 76 return nil, err 77 } 78 *quicConnPtr = quicConn 79 return quicConn, nil 80 }, 81 }, nil 82 } 83 84 func Listen(conn net.PacketConn, config aTLS.ServerConfig, quicConfig *quic.Config) (QUICListener, error) { 85 if quicTLSConfig, isQUICConfig := config.(QUICServerConfig); isQUICConfig { 86 return quicTLSConfig.Listen(conn, quicConfig) 87 } 88 tlsConfig, err := config.Config() 89 if err != nil { 90 return nil, err 91 } 92 return quic.Listen(conn, tlsConfig, quicConfig) 93 } 94 95 func ListenEarly(conn net.PacketConn, config aTLS.ServerConfig, quicConfig *quic.Config) (QUICEarlyListener, error) { 96 if quicTLSConfig, isQUICConfig := config.(QUICServerConfig); isQUICConfig { 97 return quicTLSConfig.ListenEarly(conn, quicConfig) 98 } 99 tlsConfig, err := config.Config() 100 if err != nil { 101 return nil, err 102 } 103 return quic.ListenEarly(conn, tlsConfig, quicConfig) 104 } 105 106 func ConfigureHTTP3(config aTLS.ServerConfig) error { 107 if len(config.NextProtos()) == 0 { 108 config.SetNextProtos([]string{http3.NextProtoH3}) 109 } 110 if quicTLSConfig, isQUICConfig := config.(QUICServerConfig); isQUICConfig { 111 quicTLSConfig.ConfigureHTTP3() 112 return nil 113 } 114 tlsConfig, err := config.Config() 115 if err != nil { 116 return err 117 } 118 http3.ConfigureTLSConfig(tlsConfig) 119 return nil 120 }