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  }