add otls
This commit is contained in:
parent
c7568170ac
commit
a99ff4aa15
@ -197,6 +197,7 @@ type ConnectOptions struct {
|
||||
Selector gosocks5.Selector
|
||||
UserAgent string
|
||||
NoTLS bool
|
||||
NoDelay bool
|
||||
}
|
||||
|
||||
// ConnectOption allows a common way to set ConnectOptions.
|
||||
@ -243,3 +244,10 @@ func NoTLSConnectOption(b bool) ConnectOption {
|
||||
opts.NoTLS = b
|
||||
}
|
||||
}
|
||||
|
||||
// NoDelayConnectOption specifies the NoDelay option for ss.Connect.
|
||||
func NoDelayConnectOption(b bool) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.NoDelay = b
|
||||
}
|
||||
}
|
||||
|
@ -137,8 +137,6 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
|
||||
timeout := node.GetDuration("timeout")
|
||||
|
||||
var host string
|
||||
|
||||
var tr gost.Transporter
|
||||
switch node.Transport {
|
||||
case "tls":
|
||||
@ -195,8 +193,9 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
case "obfs4":
|
||||
tr = gost.Obfs4Transporter()
|
||||
case "ohttp":
|
||||
host = node.Get("host")
|
||||
tr = gost.ObfsHTTPTransporter()
|
||||
case "otls":
|
||||
tr = gost.ObfsTLSTransporter()
|
||||
case "ftcp":
|
||||
tr = gost.FakeTCPTransporter()
|
||||
case "udp":
|
||||
@ -240,8 +239,10 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
node.ConnectOptions = []gost.ConnectOption{
|
||||
gost.UserAgentConnectOption(node.Get("agent")),
|
||||
gost.NoTLSConnectOption(node.GetBool("notls")),
|
||||
gost.NoDelayConnectOption(node.GetBool("nodelay")),
|
||||
}
|
||||
|
||||
host := node.Get("host")
|
||||
if host == "" {
|
||||
host = node.Host
|
||||
}
|
||||
@ -441,6 +442,8 @@ func (r *route) GenRouters() ([]router, error) {
|
||||
ln, err = gost.Obfs4Listener(node.Addr)
|
||||
case "ohttp":
|
||||
ln, err = gost.ObfsHTTPListener(node.Addr)
|
||||
case "otls":
|
||||
ln, err = gost.ObfsTLSListener(node.Addr)
|
||||
case "tun":
|
||||
cfg := gost.TunConfig{
|
||||
Name: node.Get("name"),
|
||||
|
2
go.mod
2
go.mod
@ -14,7 +14,7 @@ require (
|
||||
github.com/docker/libcontainer v2.2.1+incompatible
|
||||
github.com/ginuerzh/gosocks4 v0.0.1
|
||||
github.com/ginuerzh/gosocks5 v0.2.0
|
||||
github.com/ginuerzh/tls-dissector v0.0.1
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796
|
||||
github.com/go-log/log v0.1.0
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/golang/mock v1.2.0 // indirect
|
||||
|
10
go.sum
10
go.sum
@ -30,6 +30,16 @@ github.com/ginuerzh/gosocks5 v0.2.0 h1:K0Ua23U9LU3BZrf3XpGDcs0mP8DiEpa6PJE4TA/MU
|
||||
github.com/ginuerzh/gosocks5 v0.2.0/go.mod h1:qp22mr6tH/prEoaN0pFukq76LlScIE+F2rP2ZP5ZHno=
|
||||
github.com/ginuerzh/tls-dissector v0.0.1 h1:yF6fIt78TO4CdjiLLn6R8r0XajQJE1Lbnuq6rP8mGW8=
|
||||
github.com/ginuerzh/tls-dissector v0.0.1/go.mod h1:u/kbBOqIOgJv39gywuUb3VwyzdZG5DKquOqfToKE6lk=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223041816-c0cb3da7ea91 h1:bFBTbZglO4xNVWSLwDEcVKBIurTXGL2sNKi9UuQima4=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223041816-c0cb3da7ea91/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223072427-83db9c3e4eb5 h1:pmGmno31njvF5xncoDcDuM8mE1984cxrQ0DeVD4lVfA=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223072427-83db9c3e4eb5/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223110639-e9c10af0eb19 h1:t/AZCq8FiVNN+Mx6UmIv7bXj3+OVThg070G8ajZ3wJw=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223110639-e9c10af0eb19/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223121713-a8bf02a99d69 h1:h9lREy0OWSTrjweGxduikppA2tCjGPoUj32SVHI3dr0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223121713-a8bf02a99d69/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796 h1:VPXbYRvZUzTemsI7u0FzOnEuHeHwQuMTPXApAu8aeX4=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U=
|
||||
github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
|
2
gost.go
2
gost.go
@ -20,7 +20,7 @@ import (
|
||||
)
|
||||
|
||||
// Version is the gost version.
|
||||
const Version = "2.10.1"
|
||||
const Version = "2.10.2-dev"
|
||||
|
||||
// Debug is a flag that enables the debug log.
|
||||
var Debug bool
|
||||
|
3
node.go
3
node.go
@ -83,10 +83,9 @@ func ParseNode(s string) (node Node, err error) {
|
||||
case "kcp", "ssh", "quic":
|
||||
case "ssu":
|
||||
node.Transport = "udp"
|
||||
case "obfs4":
|
||||
case "ohttp", "otls", "obfs4": // obfs
|
||||
case "tcp", "udp":
|
||||
case "rtcp", "rudp": // rtcp and rudp are for remote port forwarding
|
||||
case "ohttp": // obfs-http
|
||||
case "tun", "tap": // tun/tap device
|
||||
case "ftcp": // fake TCP
|
||||
case "dns":
|
||||
|
312
obfs.go
312
obfs.go
@ -5,6 +5,8 @@ package gost
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -20,6 +22,7 @@ import (
|
||||
pt "git.torproject.org/pluggable-transports/goptlib.git"
|
||||
"git.torproject.org/pluggable-transports/obfs4.git/transports/base"
|
||||
"git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4"
|
||||
dissector "github.com/ginuerzh/tls-dissector"
|
||||
)
|
||||
|
||||
type obfsHTTPTransporter struct {
|
||||
@ -249,6 +252,315 @@ func (c *obfsHTTPConn) Write(b []byte) (n int, err error) {
|
||||
return c.Conn.Write(b)
|
||||
}
|
||||
|
||||
type obfsTLSTransporter struct {
|
||||
tcpTransporter
|
||||
}
|
||||
|
||||
// ObfsTLSTransporter creates a Transporter that is used by TLS obfuscating.
|
||||
func ObfsTLSTransporter() Transporter {
|
||||
return &obfsTLSTransporter{}
|
||||
}
|
||||
|
||||
func (tr *obfsTLSTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||
opts := &HandshakeOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
return ClientObfsTLSConn(conn, opts.Host), nil
|
||||
}
|
||||
|
||||
type obfsTLSListener struct {
|
||||
net.Listener
|
||||
}
|
||||
|
||||
// ObfsTLSListener creates a Listener for TLS obfuscating server.
|
||||
func ObfsTLSListener(addr string) (Listener, error) {
|
||||
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ln, err := net.ListenTCP("tcp", laddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &obfsTLSListener{Listener: tcpKeepAliveListener{ln}}, nil
|
||||
}
|
||||
|
||||
func (l *obfsTLSListener) Accept() (net.Conn, error) {
|
||||
conn, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ServerObfsTLSConn(conn, ""), nil
|
||||
}
|
||||
|
||||
var (
|
||||
cipherSuites = []uint16{
|
||||
0xc02c, 0xc030, 0x009f, 0xcca9, 0xcca8, 0xccaa, 0xc02b, 0xc02f,
|
||||
0x009e, 0xc024, 0xc028, 0x006b, 0xc023, 0xc027, 0x0067, 0xc00a,
|
||||
0xc014, 0x0039, 0xc009, 0xc013, 0x0033, 0x009d, 0x009c, 0x003d,
|
||||
0x003c, 0x0035, 0x002f, 0x00ff,
|
||||
}
|
||||
|
||||
compressionMethods = []uint8{0x00}
|
||||
|
||||
algorithms = []uint16{
|
||||
0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402,
|
||||
0x0403, 0x0301, 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,
|
||||
}
|
||||
)
|
||||
|
||||
type obfsTLSConn struct {
|
||||
net.Conn
|
||||
rbuf bytes.Buffer
|
||||
wbuf bytes.Buffer
|
||||
host string
|
||||
isServer bool
|
||||
handshaked chan struct{}
|
||||
handshakeMutex sync.Mutex
|
||||
}
|
||||
|
||||
func ClientObfsTLSConn(conn net.Conn, host string) net.Conn {
|
||||
return &obfsTLSConn{
|
||||
Conn: conn,
|
||||
host: host,
|
||||
handshaked: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func ServerObfsTLSConn(conn net.Conn, host string) net.Conn {
|
||||
return &obfsTLSConn{
|
||||
Conn: conn,
|
||||
host: host,
|
||||
isServer: true,
|
||||
handshaked: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *obfsTLSConn) Handshaked() bool {
|
||||
select {
|
||||
case <-c.handshaked:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *obfsTLSConn) Handshake(payload []byte) (err error) {
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if c.Handshaked() {
|
||||
return
|
||||
}
|
||||
|
||||
if c.isServer {
|
||||
err = c.serverHandshake()
|
||||
} else {
|
||||
err = c.clientHandshake(payload)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
close(c.handshaked)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *obfsTLSConn) clientHandshake(payload []byte) error {
|
||||
clientMsg := &dissector.ClientHelloMsg{
|
||||
Version: tls.VersionTLS12,
|
||||
SessionID: make([]byte, 32),
|
||||
CipherSuites: cipherSuites,
|
||||
CompressionMethods: compressionMethods,
|
||||
Extensions: []dissector.Extension{
|
||||
&dissector.SessionTicketExtension{
|
||||
Data: payload,
|
||||
},
|
||||
&dissector.ServerNameExtension{
|
||||
Name: c.host,
|
||||
},
|
||||
&dissector.ECPointFormatsExtension{
|
||||
Formats: []uint8{0x01, 0x00, 0x02},
|
||||
},
|
||||
&dissector.SupportedGroupsExtension{
|
||||
Groups: []uint16{0x001d, 0x0017, 0x0019, 0x0018},
|
||||
},
|
||||
&dissector.SignatureAlgorithmsExtension{
|
||||
Algorithms: algorithms,
|
||||
},
|
||||
&dissector.EncryptThenMacExtension{},
|
||||
&dissector.ExtendedMasterSecretExtension{},
|
||||
},
|
||||
}
|
||||
clientMsg.Random.Time = uint32(time.Now().Unix())
|
||||
rand.Read(clientMsg.Random.Opaque[:])
|
||||
rand.Read(clientMsg.SessionID)
|
||||
b, err := clientMsg.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := &dissector.Record{
|
||||
Type: dissector.Handshake,
|
||||
Version: tls.VersionTLS10,
|
||||
Opaque: b,
|
||||
}
|
||||
if _, err := record.WriteTo(c.Conn); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// server hello handshake message
|
||||
if _, err := record.ReadFrom(c.Conn); err != nil {
|
||||
return err
|
||||
}
|
||||
if record.Type != dissector.Handshake {
|
||||
return dissector.ErrBadType
|
||||
}
|
||||
|
||||
// change cipher spec message
|
||||
if _, err := record.ReadFrom(c.Conn); err != nil {
|
||||
return err
|
||||
}
|
||||
if record.Type != dissector.ChangeCipherSpec {
|
||||
return dissector.ErrBadType
|
||||
}
|
||||
|
||||
// encrypted handshake message
|
||||
if _, err := record.ReadFrom(c.Conn); err != nil {
|
||||
return err
|
||||
}
|
||||
if record.Type != dissector.Handshake {
|
||||
return dissector.ErrBadType
|
||||
}
|
||||
|
||||
_, err = c.rbuf.Write(record.Opaque)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *obfsTLSConn) serverHandshake() error {
|
||||
record := &dissector.Record{}
|
||||
if _, err := record.ReadFrom(c.Conn); err != nil {
|
||||
log.Log(err)
|
||||
return err
|
||||
}
|
||||
if record.Type != dissector.Handshake {
|
||||
return dissector.ErrBadType
|
||||
}
|
||||
|
||||
clientMsg := &dissector.ClientHelloMsg{}
|
||||
if err := clientMsg.Decode(record.Opaque); err != nil {
|
||||
log.Log(err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ext := range clientMsg.Extensions {
|
||||
if ext.Type() == dissector.ExtSessionTicket {
|
||||
b, err := ext.Encode()
|
||||
if err != nil {
|
||||
log.Log(err)
|
||||
return err
|
||||
}
|
||||
c.rbuf.Write(b)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
serverMsg := &dissector.ServerHelloMsg{
|
||||
Version: tls.VersionTLS12,
|
||||
SessionID: clientMsg.SessionID,
|
||||
CipherSuite: 0xcca8,
|
||||
CompressionMethod: 0x00,
|
||||
Extensions: []dissector.Extension{
|
||||
&dissector.RenegotiationInfoExtension{},
|
||||
&dissector.ExtendedMasterSecretExtension{},
|
||||
&dissector.ECPointFormatsExtension{
|
||||
Formats: []uint8{0x00},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
serverMsg.Random.Time = uint32(time.Now().Unix())
|
||||
rand.Read(serverMsg.Random.Opaque[:])
|
||||
b, err := serverMsg.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record = &dissector.Record{
|
||||
Type: dissector.Handshake,
|
||||
Version: tls.VersionTLS10,
|
||||
Opaque: b,
|
||||
}
|
||||
|
||||
if _, err := record.WriteTo(&c.wbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record = &dissector.Record{
|
||||
Type: dissector.ChangeCipherSpec,
|
||||
Version: tls.VersionTLS12,
|
||||
Opaque: []byte{0x01},
|
||||
}
|
||||
if _, err := record.WriteTo(&c.wbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *obfsTLSConn) Read(b []byte) (n int, err error) {
|
||||
if c.isServer { // NOTE: only Write performs the handshake operation on client side.
|
||||
if err = c.Handshake(nil); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-c.handshaked:
|
||||
}
|
||||
|
||||
if c.rbuf.Len() > 0 {
|
||||
return c.rbuf.Read(b)
|
||||
}
|
||||
record := &dissector.Record{}
|
||||
if _, err = record.ReadFrom(c.Conn); err != nil {
|
||||
return
|
||||
}
|
||||
n = copy(b, record.Opaque)
|
||||
_, err = c.rbuf.Write(record.Opaque[n:])
|
||||
return
|
||||
}
|
||||
|
||||
func (c *obfsTLSConn) Write(b []byte) (n int, err error) {
|
||||
n = len(b)
|
||||
if !c.Handshaked() {
|
||||
if err = c.Handshake(b); err != nil {
|
||||
return
|
||||
}
|
||||
if !c.isServer { // the data b has been sended during handshake phase.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
record := &dissector.Record{
|
||||
Type: dissector.AppData,
|
||||
Version: tls.VersionTLS12,
|
||||
Opaque: b,
|
||||
}
|
||||
|
||||
if c.wbuf.Len() > 0 {
|
||||
record.Type = dissector.Handshake
|
||||
record.WriteTo(&c.wbuf)
|
||||
_, err = c.wbuf.WriteTo(c.Conn)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = record.WriteTo(c.Conn); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type obfs4Context struct {
|
||||
cf base.ClientFactory
|
||||
cargs interface{} // type obfs4ClientArgs
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: gost
|
||||
type: app
|
||||
version: '2.10.1'
|
||||
version: '2.10.2'
|
||||
title: GO Simple Tunnel
|
||||
summary: A simple security tunnel written in golang
|
||||
description: |
|
||||
|
9
sni.go
9
sni.go
@ -270,7 +270,7 @@ func readClientHelloRecord(r io.Reader, host string, isClient bool) ([]byte, str
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
clientHello := &dissector.ClientHelloHandshake{}
|
||||
clientHello := &dissector.ClientHelloMsg{}
|
||||
if err := clientHello.Decode(record.Opaque); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -280,7 +280,8 @@ func readClientHelloRecord(r io.Reader, host string, isClient bool) ([]byte, str
|
||||
|
||||
for _, ext := range clientHello.Extensions {
|
||||
if ext.Type() == 0xFFFE {
|
||||
if host, err = decodeServerName(string(ext.Bytes()[4:])); err == nil {
|
||||
b, _ := ext.Encode()
|
||||
if host, err = decodeServerName(string(b)); err == nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -296,8 +297,8 @@ func readClientHelloRecord(r io.Reader, host string, isClient bool) ([]byte, str
|
||||
host = snExtension.Name
|
||||
}
|
||||
if isClient {
|
||||
clientHello.Extensions = append(clientHello.Extensions,
|
||||
dissector.NewExtension(0xFFFE, []byte(encodeServerName(snExtension.Name))))
|
||||
e, _ := dissector.NewExtension(0xFFFE, []byte(encodeServerName(snExtension.Name)))
|
||||
clientHello.Extensions = append(clientHello.Extensions, e)
|
||||
}
|
||||
if host != "" {
|
||||
snExtension.Name = host
|
||||
|
47
ss.go
47
ss.go
@ -75,10 +75,21 @@ func (c *shadowConnector) ConnectContext(ctx context.Context, conn net.Conn, net
|
||||
if c.cipher != nil {
|
||||
conn = c.cipher.StreamConn(conn)
|
||||
}
|
||||
if _, err := conn.Write(rawaddr[:n]); err != nil {
|
||||
|
||||
sc := &shadowConn{
|
||||
Conn: conn,
|
||||
}
|
||||
|
||||
// write the addr at once.
|
||||
if opts.NoDelay {
|
||||
if _, err := sc.Write(rawaddr[:n]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
} else {
|
||||
sc.wbuf.Write(rawaddr[:n]) // cache the header
|
||||
}
|
||||
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
type shadowHandler struct {
|
||||
@ -111,7 +122,9 @@ func (h *shadowHandler) Handle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
if h.cipher != nil {
|
||||
conn = h.cipher.StreamConn(conn)
|
||||
conn = &shadowConn{
|
||||
Conn: h.cipher.StreamConn(conn),
|
||||
}
|
||||
}
|
||||
|
||||
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||
@ -244,7 +257,9 @@ func (c *shadowUDPConnector) ConnectContext(ctx context.Context, conn net.Conn,
|
||||
}
|
||||
|
||||
if c.cipher != nil {
|
||||
conn = c.cipher.StreamConn(conn)
|
||||
conn = &shadowConn{
|
||||
Conn: c.cipher.StreamConn(conn),
|
||||
}
|
||||
}
|
||||
|
||||
return &socks5UDPTunnelConn{
|
||||
@ -302,7 +317,9 @@ func (h *shadowUDPHandler) Handle(conn net.Conn) {
|
||||
}
|
||||
|
||||
if h.cipher != nil {
|
||||
conn = h.cipher.StreamConn(conn)
|
||||
conn = &shadowConn{
|
||||
Conn: h.cipher.StreamConn(conn),
|
||||
}
|
||||
}
|
||||
|
||||
log.Logf("[ssu] %s <-> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
@ -469,10 +486,17 @@ func (h *shadowUDPHandler) transportUDP(conn net.Conn, cc net.PacketConn) error
|
||||
// we wrap around it to make io.Copy happy.
|
||||
type shadowConn struct {
|
||||
net.Conn
|
||||
wbuf bytes.Buffer
|
||||
}
|
||||
|
||||
func (c *shadowConn) Write(b []byte) (n int, err error) {
|
||||
n = len(b) // force byte length consistent
|
||||
if c.wbuf.Len() > 0 {
|
||||
c.wbuf.Write(b) // append the data to the cached header
|
||||
_, err = c.Conn.Write(c.wbuf.Bytes())
|
||||
c.wbuf.Reset()
|
||||
return
|
||||
}
|
||||
_, err = c.Conn.Write(b)
|
||||
return
|
||||
}
|
||||
@ -546,9 +570,7 @@ type shadowCipher struct {
|
||||
}
|
||||
|
||||
func (c *shadowCipher) StreamConn(conn net.Conn) net.Conn {
|
||||
return &shadowConn{
|
||||
Conn: ss.NewConn(conn, c.cipher.Copy()),
|
||||
}
|
||||
return ss.NewConn(conn, c.cipher.Copy())
|
||||
}
|
||||
|
||||
func (c *shadowCipher) PacketConn(conn net.PacketConn) net.PacketConn {
|
||||
@ -566,14 +588,17 @@ func initShadowCipher(info *url.Userinfo) (cipher core.Cipher) {
|
||||
return
|
||||
}
|
||||
|
||||
cipher, _ = core.PickCipher(method, nil, password)
|
||||
cp, _ := ss.NewCipher(method, password)
|
||||
if cp != nil {
|
||||
cipher = &shadowCipher{cipher: cp}
|
||||
}
|
||||
if cipher == nil {
|
||||
cp, err := ss.NewCipher(method, password)
|
||||
var err error
|
||||
cipher, err = core.PickCipher(method, nil, password)
|
||||
if err != nil {
|
||||
log.Logf("[ss] %s", err)
|
||||
return
|
||||
}
|
||||
cipher = &shadowCipher{cipher: cp}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user