chore: better restls

This commit is contained in:
gVisor bot 2023-03-14 16:50:27 +08:00
parent a2e1f0d956
commit f8c1d4d4c7
2 changed files with 34 additions and 59 deletions

View file

@ -86,22 +86,14 @@ type restlsOption struct {
// StreamConn implements C.ProxyAdapter // StreamConn implements C.ProxyAdapter
func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
switch ss.obfsMode {
case shadowtls.Mode:
// fix tls handshake not timeout // fix tls handshake not timeout
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
defer cancel() defer cancel()
var err error return ss.StreamConnContext(ctx, c, metadata)
c, err = shadowtls.NewShadowTLS(ctx, c, ss.shadowTLSOption)
if err != nil {
return nil, err
} }
} func (ss *ShadowSocks) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) {
return ss.streamConn(c, metadata) useEarly := false
}
func (ss *ShadowSocks) streamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
switch ss.obfsMode { switch ss.obfsMode {
case "tls": case "tls":
c = obfs.NewTLSObfs(c, ss.obfsOption.Host) c = obfs.NewTLSObfs(c, ss.obfsOption.Host)
@ -114,21 +106,30 @@ func (ss *ShadowSocks) streamConn(c net.Conn, metadata *C.Metadata) (net.Conn, e
if err != nil { if err != nil {
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err) return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
} }
case shadowtls.Mode:
var err error
c, err = shadowtls.NewShadowTLS(ctx, c, ss.shadowTLSOption)
if err != nil {
return nil, err
}
useEarly = true
case restls.Mode: case restls.Mode:
var err error var err error
c, err = restls.NewRestls(c, ss.restlsConfig) c, err = restls.NewRestls(ctx, c, ss.restlsConfig)
if err != nil { if err != nil {
return nil, fmt.Errorf("%s (restls) connect error: %w", ss.addr, err) return nil, fmt.Errorf("%s (restls) connect error: %w", ss.addr, err)
} }
useEarly = true
} }
useEarly = useEarly || N.NeedHandshake(c)
if metadata.NetWork == C.UDP && ss.option.UDPOverTCP { if metadata.NetWork == C.UDP && ss.option.UDPOverTCP {
if N.NeedHandshake(c) { if useEarly {
return ss.method.DialEarlyConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443")), nil return ss.method.DialEarlyConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443")), nil
} else { } else {
return ss.method.DialConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443")) return ss.method.DialConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443"))
} }
} }
if N.NeedHandshake(c) { if useEarly {
return ss.method.DialEarlyConn(c, M.ParseSocksaddr(metadata.RemoteAddress())), nil return ss.method.DialEarlyConn(c, M.ParseSocksaddr(metadata.RemoteAddress())), nil
} else { } else {
return ss.method.DialConn(c, M.ParseSocksaddr(metadata.RemoteAddress())) return ss.method.DialConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
@ -152,15 +153,7 @@ func (ss *ShadowSocks) DialContextWithDialer(ctx context.Context, dialer C.Diale
safeConnClose(c, err) safeConnClose(c, err)
}(c) }(c)
switch ss.obfsMode { c, err = ss.StreamConnContext(ctx, c, metadata)
case shadowtls.Mode:
c, err = shadowtls.NewShadowTLS(ctx, c, ss.shadowTLSOption)
if err != nil {
return nil, err
}
}
c, err = ss.streamConn(c, metadata)
return NewConn(c, ss), err return NewConn(c, ss), err
} }

View file

@ -1,6 +1,7 @@
package restls package restls
import ( import (
"context"
"net" "net"
tls "github.com/3andne/restls-client-go" tls "github.com/3andne/restls-client-go"
@ -10,48 +11,29 @@ const (
Mode string = "restls" Mode string = "restls"
) )
// Restls
type Restls struct { type Restls struct {
net.Conn *tls.UConn
firstPacketCache []byte
firstPacket bool
} }
func (r *Restls) Read(b []byte) (int, error) { func (r *Restls) Upstream() any {
if err := r.Conn.(*tls.UConn).Handshake(); err != nil { return r.UConn.NetConn()
return 0, err
}
n, err := r.Conn.(*tls.UConn).Read(b)
return n, err
}
func (r *Restls) Write(b []byte) (int, error) {
if r.firstPacket {
r.firstPacketCache = append([]byte(nil), b...)
r.firstPacket = false
return len(b), nil
}
if len(r.firstPacketCache) != 0 {
b = append(r.firstPacketCache, b...)
r.firstPacketCache = nil
}
n, err := r.Conn.(*tls.UConn).Write(b)
return n, err
} }
// NewRestls return a Restls Connection // NewRestls return a Restls Connection
func NewRestls(conn net.Conn, config *tls.Config) (net.Conn, error) { func NewRestls(ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, error) {
clientHellowID := tls.HelloChrome_Auto
if config != nil { if config != nil {
clientIDPtr := config.ClientID.Load() clientIDPtr := config.ClientID.Load()
if clientIDPtr != nil { if clientIDPtr != nil {
return &Restls{ clientHellowID = *clientIDPtr
Conn: tls.UClient(conn, config, *clientIDPtr),
firstPacket: true,
}, nil
} }
} }
return &Restls{ restls := &Restls{
Conn: tls.UClient(conn, config, tls.HelloChrome_Auto), UConn: tls.UClient(conn, config, clientHellowID),
firstPacket: true, }
}, nil if err := restls.HandshakeContext(ctx); err != nil {
return nil, err
}
return restls, nil
} }