chore: better restls
This commit is contained in:
parent
a2e1f0d956
commit
f8c1d4d4c7
2 changed files with 34 additions and 59 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue