github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/server_tls.go (about)

     1  package gquic
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"errors"
     7  	"net"
     8  
     9  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/handshake"
    10  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/protocol"
    11  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/utils"
    12  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/wire"
    13  	"github.com/bifurcation/mint"
    14  )
    15  
    16  type tlsSession struct {
    17  	connID protocol.ConnectionID
    18  	sess   quicSession
    19  }
    20  
    21  type serverTLS struct {
    22  	conn            net.PacketConn
    23  	config          *Config
    24  	mintConf        *mint.Config
    25  	params          *handshake.TransportParameters
    26  	cookieGenerator *handshake.CookieGenerator
    27  
    28  	newSession func(connection, sessionRunner, protocol.ConnectionID, protocol.ConnectionID, protocol.ConnectionID, protocol.PacketNumber, *Config, *mint.Config, <-chan handshake.TransportParameters, utils.Logger, protocol.VersionNumber) (quicSession, error)
    29  
    30  	sessionRunner sessionRunner
    31  	sessionChan   chan<- tlsSession
    32  
    33  	logger utils.Logger
    34  }
    35  
    36  func newServerTLS(
    37  	conn net.PacketConn,
    38  	config *Config,
    39  	runner sessionRunner,
    40  	tlsConf *tls.Config,
    41  	logger utils.Logger,
    42  ) (*serverTLS, <-chan tlsSession, error) {
    43  	cookieGenerator, err := handshake.NewCookieGenerator()
    44  	if err != nil {
    45  		return nil, nil, err
    46  	}
    47  	params := &handshake.TransportParameters{
    48  		StreamFlowControlWindow:     protocol.ReceiveStreamFlowControlWindow,
    49  		ConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
    50  		IdleTimeout:                 config.IdleTimeout,
    51  		MaxBidiStreams:              uint16(config.MaxIncomingStreams),
    52  		MaxUniStreams:               uint16(config.MaxIncomingUniStreams),
    53  		DisableMigration:            true,
    54  		// TODO(#855): generate a real token
    55  		StatelessResetToken: bytes.Repeat([]byte{42}, 16),
    56  	}
    57  	mconf, err := tlsToMintConfig(tlsConf, protocol.PerspectiveServer)
    58  	if err != nil {
    59  		return nil, nil, err
    60  	}
    61  
    62  	sessionChan := make(chan tlsSession)
    63  	s := &serverTLS{
    64  		conn:            conn,
    65  		config:          config,
    66  		mintConf:        mconf,
    67  		sessionRunner:   runner,
    68  		sessionChan:     sessionChan,
    69  		cookieGenerator: cookieGenerator,
    70  		params:          params,
    71  		newSession:      newTLSServerSession,
    72  		logger:          logger,
    73  	}
    74  	return s, sessionChan, nil
    75  }
    76  
    77  func (s *serverTLS) HandleInitial(p *receivedPacket) {
    78  	// TODO: add a check that DestConnID == SrcConnID
    79  	s.logger.Debugf("<- Received Initial packet.")
    80  	sess, connID, err := s.handleInitialImpl(p)
    81  	if err != nil {
    82  		s.logger.Errorf("Error occurred handling initial packet: %s", err)
    83  		return
    84  	}
    85  	if sess == nil { // a stateless reset was done
    86  		return
    87  	}
    88  	s.sessionChan <- tlsSession{
    89  		connID: connID,
    90  		sess:   sess,
    91  	}
    92  }
    93  
    94  func (s *serverTLS) handleInitialImpl(p *receivedPacket) (quicSession, protocol.ConnectionID, error) {
    95  	hdr := p.header
    96  	if len(hdr.Token) == 0 && hdr.DestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
    97  		return nil, nil, errors.New("dropping Initial packet with too short connection ID")
    98  	}
    99  	if len(hdr.Raw)+len(p.data) < protocol.MinInitialPacketSize {
   100  		return nil, nil, errors.New("dropping too small Initial packet")
   101  	}
   102  
   103  	var cookie *handshake.Cookie
   104  	if len(hdr.Token) > 0 {
   105  		c, err := s.cookieGenerator.DecodeToken(hdr.Token)
   106  		if err == nil {
   107  			cookie = c
   108  		}
   109  	}
   110  	if !s.config.AcceptCookie(p.remoteAddr, cookie) {
   111  		// Log the Initial packet now.
   112  		// If no Retry is sent, the packet will be logged by the session.
   113  		p.header.Log(s.logger)
   114  		return nil, nil, s.sendRetry(p.remoteAddr, hdr)
   115  	}
   116  
   117  	extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, hdr.Version, s.logger)
   118  	mconf := s.mintConf.Clone()
   119  	mconf.ExtensionHandler = extHandler
   120  
   121  	connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
   122  	if err != nil {
   123  		return nil, nil, err
   124  	}
   125  	s.logger.Debugf("Changing connection ID to %s.", connID)
   126  	sess, err := s.newSession(
   127  		&conn{pconn: s.conn, currentAddr: p.remoteAddr},
   128  		s.sessionRunner,
   129  		hdr.DestConnectionID,
   130  		hdr.SrcConnectionID,
   131  		connID,
   132  		1,
   133  		s.config,
   134  		mconf,
   135  		extHandler.GetPeerParams(),
   136  		s.logger,
   137  		hdr.Version,
   138  	)
   139  	if err != nil {
   140  		return nil, nil, err
   141  	}
   142  	go sess.run()
   143  	sess.handlePacket(p)
   144  	return sess, connID, nil
   145  }
   146  
   147  func (s *serverTLS) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
   148  	token, err := s.cookieGenerator.NewToken(remoteAddr)
   149  	if err != nil {
   150  		return err
   151  	}
   152  	connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
   153  	if err != nil {
   154  		return err
   155  	}
   156  	replyHdr := &wire.Header{
   157  		IsLongHeader:         true,
   158  		Type:                 protocol.PacketTypeRetry,
   159  		Version:              hdr.Version,
   160  		SrcConnectionID:      connID,
   161  		DestConnectionID:     hdr.SrcConnectionID,
   162  		OrigDestConnectionID: hdr.DestConnectionID,
   163  		Token:                token,
   164  	}
   165  	s.logger.Debugf("Changing connection ID to %s.\n-> Sending Retry", connID)
   166  	replyHdr.Log(s.logger)
   167  	buf := &bytes.Buffer{}
   168  	if err := replyHdr.Write(buf, protocol.PerspectiveServer, hdr.Version); err != nil {
   169  		return err
   170  	}
   171  	if _, err := s.conn.WriteTo(buf.Bytes(), remoteAddr); err != nil {
   172  		s.logger.Debugf("Error sending Retry: %s", err)
   173  	}
   174  	return nil
   175  }