github.com/sagernet/sing-box@v1.2.7/common/tls/reality_server.go (about)

     1  //go:build with_reality_server
     2  
     3  package tls
     4  
     5  import (
     6  	"context"
     7  	"crypto/tls"
     8  	"encoding/base64"
     9  	"encoding/hex"
    10  	"net"
    11  	"time"
    12  
    13  	"github.com/sagernet/reality"
    14  	"github.com/sagernet/sing-box/adapter"
    15  	"github.com/sagernet/sing-box/common/dialer"
    16  	"github.com/sagernet/sing-box/log"
    17  	"github.com/sagernet/sing-box/option"
    18  	"github.com/sagernet/sing/common/debug"
    19  	E "github.com/sagernet/sing/common/exceptions"
    20  	M "github.com/sagernet/sing/common/metadata"
    21  	N "github.com/sagernet/sing/common/network"
    22  )
    23  
    24  var _ ServerConfigCompat = (*RealityServerConfig)(nil)
    25  
    26  type RealityServerConfig struct {
    27  	config *reality.Config
    28  }
    29  
    30  func NewRealityServer(ctx context.Context, router adapter.Router, logger log.Logger, options option.InboundTLSOptions) (*RealityServerConfig, error) {
    31  	var tlsConfig reality.Config
    32  
    33  	if options.ACME != nil && len(options.ACME.Domain) > 0 {
    34  		return nil, E.New("acme is unavailable in reality")
    35  	}
    36  	tlsConfig.Time = router.TimeFunc()
    37  	if options.ServerName != "" {
    38  		tlsConfig.ServerName = options.ServerName
    39  	}
    40  	if len(options.ALPN) > 0 {
    41  		tlsConfig.NextProtos = append(tlsConfig.NextProtos, options.ALPN...)
    42  	}
    43  	if options.MinVersion != "" {
    44  		minVersion, err := ParseTLSVersion(options.MinVersion)
    45  		if err != nil {
    46  			return nil, E.Cause(err, "parse min_version")
    47  		}
    48  		tlsConfig.MinVersion = minVersion
    49  	}
    50  	if options.MaxVersion != "" {
    51  		maxVersion, err := ParseTLSVersion(options.MaxVersion)
    52  		if err != nil {
    53  			return nil, E.Cause(err, "parse max_version")
    54  		}
    55  		tlsConfig.MaxVersion = maxVersion
    56  	}
    57  	if options.CipherSuites != nil {
    58  	find:
    59  		for _, cipherSuite := range options.CipherSuites {
    60  			for _, tlsCipherSuite := range tls.CipherSuites() {
    61  				if cipherSuite == tlsCipherSuite.Name {
    62  					tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, tlsCipherSuite.ID)
    63  					continue find
    64  				}
    65  			}
    66  			return nil, E.New("unknown cipher_suite: ", cipherSuite)
    67  		}
    68  	}
    69  	if options.Certificate != "" || options.CertificatePath != "" {
    70  		return nil, E.New("certificate is unavailable in reality")
    71  	}
    72  	if options.Key != "" || options.KeyPath != "" {
    73  		return nil, E.New("key is unavailable in reality")
    74  	}
    75  
    76  	tlsConfig.SessionTicketsDisabled = true
    77  	tlsConfig.Type = N.NetworkTCP
    78  	tlsConfig.Dest = options.Reality.Handshake.ServerOptions.Build().String()
    79  
    80  	tlsConfig.ServerNames = map[string]bool{options.ServerName: true}
    81  	privateKey, err := base64.RawURLEncoding.DecodeString(options.Reality.PrivateKey)
    82  	if err != nil {
    83  		return nil, E.Cause(err, "decode private key")
    84  	}
    85  	if len(privateKey) != 32 {
    86  		return nil, E.New("invalid private key")
    87  	}
    88  	tlsConfig.PrivateKey = privateKey
    89  	tlsConfig.MaxTimeDiff = time.Duration(options.Reality.MaxTimeDifference)
    90  
    91  	tlsConfig.ShortIds = make(map[[8]byte]bool)
    92  	for i, shortIDString := range options.Reality.ShortID {
    93  		var shortID [8]byte
    94  		decodedLen, err := hex.Decode(shortID[:], []byte(shortIDString))
    95  		if err != nil {
    96  			return nil, E.Cause(err, "decode short_id[", i, "]: ", shortIDString)
    97  		}
    98  		if decodedLen > 8 {
    99  			return nil, E.New("invalid short_id[", i, "]: ", shortIDString)
   100  		}
   101  		tlsConfig.ShortIds[shortID] = true
   102  	}
   103  
   104  	handshakeDialer := dialer.New(router, options.Reality.Handshake.DialerOptions)
   105  	tlsConfig.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
   106  		return handshakeDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
   107  	}
   108  
   109  	if debug.Enabled {
   110  		tlsConfig.Show = true
   111  	}
   112  
   113  	return &RealityServerConfig{&tlsConfig}, nil
   114  }
   115  
   116  func (c *RealityServerConfig) ServerName() string {
   117  	return c.config.ServerName
   118  }
   119  
   120  func (c *RealityServerConfig) SetServerName(serverName string) {
   121  	c.config.ServerName = serverName
   122  }
   123  
   124  func (c *RealityServerConfig) NextProtos() []string {
   125  	return c.config.NextProtos
   126  }
   127  
   128  func (c *RealityServerConfig) SetNextProtos(nextProto []string) {
   129  	c.config.NextProtos = nextProto
   130  }
   131  
   132  func (c *RealityServerConfig) Config() (*tls.Config, error) {
   133  	return nil, E.New("unsupported usage for reality")
   134  }
   135  
   136  func (c *RealityServerConfig) Client(conn net.Conn) (Conn, error) {
   137  	return ClientHandshake(context.Background(), conn, c)
   138  }
   139  
   140  func (c *RealityServerConfig) Start() error {
   141  	return nil
   142  }
   143  
   144  func (c *RealityServerConfig) Close() error {
   145  	return nil
   146  }
   147  
   148  func (c *RealityServerConfig) Server(conn net.Conn) (Conn, error) {
   149  	return ServerHandshake(context.Background(), conn, c)
   150  }
   151  
   152  func (c *RealityServerConfig) ServerHandshake(ctx context.Context, conn net.Conn) (Conn, error) {
   153  	tlsConn, err := reality.Server(ctx, conn, c.config)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	return &realityConnWrapper{Conn: tlsConn}, nil
   158  }
   159  
   160  func (c *RealityServerConfig) Clone() Config {
   161  	return &RealityServerConfig{
   162  		config: c.config.Clone(),
   163  	}
   164  }
   165  
   166  var _ Conn = (*realityConnWrapper)(nil)
   167  
   168  type realityConnWrapper struct {
   169  	*reality.Conn
   170  }
   171  
   172  func (c *realityConnWrapper) ConnectionState() ConnectionState {
   173  	state := c.Conn.ConnectionState()
   174  	return tls.ConnectionState{
   175  		Version:                     state.Version,
   176  		HandshakeComplete:           state.HandshakeComplete,
   177  		DidResume:                   state.DidResume,
   178  		CipherSuite:                 state.CipherSuite,
   179  		NegotiatedProtocol:          state.NegotiatedProtocol,
   180  		NegotiatedProtocolIsMutual:  state.NegotiatedProtocolIsMutual,
   181  		ServerName:                  state.ServerName,
   182  		PeerCertificates:            state.PeerCertificates,
   183  		VerifiedChains:              state.VerifiedChains,
   184  		SignedCertificateTimestamps: state.SignedCertificateTimestamps,
   185  		OCSPResponse:                state.OCSPResponse,
   186  		TLSUnique:                   state.TLSUnique,
   187  	}
   188  }
   189  
   190  func (c *realityConnWrapper) Upstream() any {
   191  	return c.Conn
   192  }