mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-22 10:08:15 -05:00
179 lines
5.1 KiB
Go
179 lines
5.1 KiB
Go
package quic
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"errors"
|
|
"net"
|
|
|
|
"github.com/bifurcation/mint"
|
|
"github.com/lucas-clemente/quic-go/internal/handshake"
|
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
"github.com/lucas-clemente/quic-go/internal/wire"
|
|
)
|
|
|
|
type tlsSession struct {
|
|
connID protocol.ConnectionID
|
|
sess quicSession
|
|
}
|
|
|
|
type serverTLS struct {
|
|
conn net.PacketConn
|
|
config *Config
|
|
mintConf *mint.Config
|
|
params *handshake.TransportParameters
|
|
cookieGenerator *handshake.CookieGenerator
|
|
|
|
newSession func(connection, sessionRunner, protocol.ConnectionID, protocol.ConnectionID, protocol.ConnectionID, protocol.PacketNumber, *Config, *mint.Config, *handshake.TransportParameters, utils.Logger, protocol.VersionNumber) (quicSession, error)
|
|
|
|
sessionRunner sessionRunner
|
|
sessionChan chan<- tlsSession
|
|
|
|
logger utils.Logger
|
|
}
|
|
|
|
func newServerTLS(
|
|
conn net.PacketConn,
|
|
config *Config,
|
|
runner sessionRunner,
|
|
tlsConf *tls.Config,
|
|
logger utils.Logger,
|
|
) (*serverTLS, <-chan tlsSession, error) {
|
|
cookieGenerator, err := handshake.NewCookieGenerator()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
params := &handshake.TransportParameters{
|
|
StreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
|
|
ConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
|
|
IdleTimeout: config.IdleTimeout,
|
|
MaxBidiStreams: uint16(config.MaxIncomingStreams),
|
|
MaxUniStreams: uint16(config.MaxIncomingUniStreams),
|
|
DisableMigration: true,
|
|
// TODO(#855): generate a real token
|
|
StatelessResetToken: bytes.Repeat([]byte{42}, 16),
|
|
}
|
|
mconf, err := tlsToMintConfig(tlsConf, protocol.PerspectiveServer)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
sessionChan := make(chan tlsSession)
|
|
s := &serverTLS{
|
|
conn: conn,
|
|
config: config,
|
|
mintConf: mconf,
|
|
sessionRunner: runner,
|
|
sessionChan: sessionChan,
|
|
cookieGenerator: cookieGenerator,
|
|
params: params,
|
|
newSession: newTLSServerSession,
|
|
logger: logger,
|
|
}
|
|
return s, sessionChan, nil
|
|
}
|
|
|
|
func (s *serverTLS) HandleInitial(p *receivedPacket) {
|
|
// TODO: add a check that DestConnID == SrcConnID
|
|
s.logger.Debugf("<- Received Initial packet.")
|
|
sess, connID, err := s.handleInitialImpl(p)
|
|
if err != nil {
|
|
s.logger.Errorf("Error occurred handling initial packet: %s", err)
|
|
return
|
|
}
|
|
if sess == nil { // a stateless reset was done
|
|
return
|
|
}
|
|
s.sessionChan <- tlsSession{
|
|
connID: connID,
|
|
sess: sess,
|
|
}
|
|
}
|
|
|
|
func (s *serverTLS) handleInitialImpl(p *receivedPacket) (quicSession, protocol.ConnectionID, error) {
|
|
hdr := p.header
|
|
if len(hdr.Token) == 0 && hdr.DestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
|
|
return nil, nil, errors.New("dropping Initial packet with too short connection ID")
|
|
}
|
|
if len(hdr.Raw)+len(p.data) < protocol.MinInitialPacketSize {
|
|
return nil, nil, errors.New("dropping too small Initial packet")
|
|
}
|
|
|
|
var cookie *handshake.Cookie
|
|
if len(hdr.Token) > 0 {
|
|
c, err := s.cookieGenerator.DecodeToken(hdr.Token)
|
|
if err == nil {
|
|
cookie = c
|
|
}
|
|
}
|
|
if !s.config.AcceptCookie(p.remoteAddr, cookie) {
|
|
// Log the Initial packet now.
|
|
// If no Retry is sent, the packet will be logged by the session.
|
|
p.header.Log(s.logger)
|
|
return nil, nil, s.sendRetry(p.remoteAddr, hdr)
|
|
}
|
|
|
|
extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, hdr.Version, s.logger)
|
|
mconf := s.mintConf.Clone()
|
|
mconf.ExtensionHandler = extHandler
|
|
|
|
// A server is allowed to perform multiple Retries.
|
|
// It doesn't make much sense, but it's something that our API allows.
|
|
// In that case it must use a source connection ID of at least 8 bytes.
|
|
connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
s.logger.Debugf("Changing connection ID to %s.", connID)
|
|
sess, err := s.newSession(
|
|
&conn{pconn: s.conn, currentAddr: p.remoteAddr},
|
|
s.sessionRunner,
|
|
hdr.DestConnectionID,
|
|
hdr.SrcConnectionID,
|
|
connID,
|
|
1,
|
|
s.config,
|
|
mconf,
|
|
s.params,
|
|
s.logger,
|
|
hdr.Version,
|
|
)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
go sess.run()
|
|
sess.handlePacket(p)
|
|
return sess, connID, nil
|
|
}
|
|
|
|
func (s *serverTLS) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
|
|
token, err := s.cookieGenerator.NewToken(remoteAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
connID, err := protocol.GenerateConnectionIDForInitial()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
replyHdr := &wire.Header{
|
|
IsLongHeader: true,
|
|
Type: protocol.PacketTypeRetry,
|
|
Version: hdr.Version,
|
|
SrcConnectionID: connID,
|
|
DestConnectionID: hdr.SrcConnectionID,
|
|
OrigDestConnectionID: hdr.DestConnectionID,
|
|
Token: token,
|
|
}
|
|
s.logger.Debugf("Changing connection ID to %s.\n-> Sending Retry", connID)
|
|
replyHdr.Log(s.logger)
|
|
buf := &bytes.Buffer{}
|
|
if err := replyHdr.Write(buf, protocol.PerspectiveServer, hdr.Version); err != nil {
|
|
return err
|
|
}
|
|
if _, err := s.conn.WriteTo(buf.Bytes(), remoteAddr); err != nil {
|
|
s.logger.Debugf("Error sending Retry: %s", err)
|
|
}
|
|
return nil
|
|
}
|