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