mirror of
https://github.com/p4gefau1t/trojan-go.git
synced 2024-04-21 12:21:34 +00:00
stick all smux headers, disable smux keep alive
This commit is contained in:
@@ -17,7 +17,7 @@ require (
|
||||
github.com/proullon/ramsql v0.0.0-20181213202341-817cee58a244
|
||||
github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57
|
||||
github.com/smartystreets/goconvey v1.6.4
|
||||
github.com/xtaci/smux v1.5.14
|
||||
github.com/xtaci/smux v1.5.15-0.20200523091831-637399ad4398
|
||||
github.com/ziutek/mymysql v1.5.4 // indirect
|
||||
go.starlark.net v0.0.0-20200519165436-0aa95694c768 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
|
||||
|
||||
@@ -292,8 +292,8 @@ github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP080
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xtaci/smux v1.5.14 h1:1j+zJYDZRv9FHaWqCJfH5RPizIm0fSzJIFbfVn8zsfg=
|
||||
github.com/xtaci/smux v1.5.14/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
|
||||
github.com/xtaci/smux v1.5.15-0.20200523091831-637399ad4398 h1:1nJafFt4SJPzJ5RbWBP2OUJ7Xcx7pdjyjldEdFrLfKs=
|
||||
github.com/xtaci/smux v1.5.15-0.20200523091831-637399ad4398/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
|
||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
|
||||
+67
-15
@@ -19,23 +19,75 @@ import (
|
||||
// HACK stick the smux 8 bytes header to the payload
|
||||
type smuxStickyReadWriteCloser struct {
|
||||
io.ReadWriteCloser
|
||||
smuxHeader []byte
|
||||
synQueue chan []byte
|
||||
finQueue chan []byte
|
||||
}
|
||||
|
||||
func (rwc *smuxStickyReadWriteCloser) stickToPayload(p []byte) []byte {
|
||||
buf := make([]byte, 0, len(p)+16)
|
||||
for {
|
||||
select {
|
||||
case header := <-rwc.synQueue:
|
||||
buf = append(buf, header...)
|
||||
default:
|
||||
goto stick1
|
||||
}
|
||||
}
|
||||
stick1:
|
||||
buf = append(buf, p...)
|
||||
for {
|
||||
select {
|
||||
case header := <-rwc.finQueue:
|
||||
buf = append(buf, header...)
|
||||
default:
|
||||
goto stick2
|
||||
}
|
||||
}
|
||||
stick2:
|
||||
return buf
|
||||
}
|
||||
|
||||
func (rwc *smuxStickyReadWriteCloser) Close() error {
|
||||
const maxPaddingLength = 512
|
||||
padding := [maxPaddingLength + 8]byte{0, 0, 'A', 'B', 'C', 'D', 'E', 'F'}
|
||||
buf := rwc.stickToPayload(nil)
|
||||
rwc.Write(append(buf, padding[:rand.Intn(maxPaddingLength)]...))
|
||||
return rwc.ReadWriteCloser.Close()
|
||||
}
|
||||
|
||||
func (rwc *smuxStickyReadWriteCloser) Write(p []byte) (int, error) {
|
||||
if len(p) == 8 && rwc.smuxHeader == nil {
|
||||
// check version and command, cmdPSH = 2
|
||||
if (p[0] == 1 || p[0] == 2) && (p[1] == 2) {
|
||||
rwc.smuxHeader = p
|
||||
return 8, nil
|
||||
if len(p) == 8 {
|
||||
if p[0] == 1 || p[0] == 2 { //smux 8 bytes header
|
||||
switch p[1] {
|
||||
// THE CONTENT OF THE BUFFER MIGHT CHANGE
|
||||
// NEVER STORE THE POINTER TO HEADER, COPY THE HEADER INSTEAD
|
||||
case 0:
|
||||
//cmdSYN
|
||||
header := make([]byte, 8)
|
||||
copy(header, p)
|
||||
rwc.synQueue <- header
|
||||
return 8, nil
|
||||
case 1:
|
||||
//cmdFIN
|
||||
header := make([]byte, 8)
|
||||
copy(header, p)
|
||||
rwc.finQueue <- header
|
||||
return 8, nil
|
||||
}
|
||||
} else {
|
||||
log.Debug("Unknown 8 bytes")
|
||||
}
|
||||
}
|
||||
if rwc.smuxHeader != nil {
|
||||
_, err := rwc.ReadWriteCloser.Write(append(rwc.smuxHeader, p...))
|
||||
rwc.smuxHeader = nil
|
||||
return len(p), err
|
||||
_, err := rwc.ReadWriteCloser.Write(rwc.stickToPayload(p))
|
||||
return len(p), err
|
||||
}
|
||||
|
||||
func newSmuxStickyReadWriteCloser(rwc io.ReadWriteCloser) *smuxStickyReadWriteCloser {
|
||||
return &smuxStickyReadWriteCloser{
|
||||
ReadWriteCloser: rwc,
|
||||
synQueue: make(chan []byte, 128),
|
||||
finQueue: make(chan []byte, 128),
|
||||
}
|
||||
return rwc.ReadWriteCloser.Write(p)
|
||||
}
|
||||
|
||||
type muxID uint32
|
||||
@@ -84,11 +136,11 @@ func (m *MuxManager) newMuxClient() (*muxClientInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
smuxRWC := &smuxStickyReadWriteCloser{
|
||||
ReadWriteCloser: trojanConn,
|
||||
}
|
||||
smuxRWC := newSmuxStickyReadWriteCloser(trojanConn)
|
||||
|
||||
client, err := smux.Client(smuxRWC, nil)
|
||||
smuxConfig := smux.DefaultConfig()
|
||||
smuxConfig.KeepAliveDisabled = true
|
||||
client, err := smux.Client(smuxRWC, smuxConfig)
|
||||
common.Must(err)
|
||||
log.Info("Mux TLS tunnel established, client id:", id)
|
||||
return &muxClientInfo{
|
||||
|
||||
@@ -17,6 +17,10 @@ type Buildable interface {
|
||||
}
|
||||
|
||||
func RelayConn(ctx context.Context, a, b io.ReadWriter, bufferSize int) {
|
||||
if a == nil || b == nil {
|
||||
log.Debug("Empty RW")
|
||||
return
|
||||
}
|
||||
errChan := make(chan error, 2)
|
||||
copyConn := func(dst io.Writer, src io.Reader) {
|
||||
buf := make([]byte, bufferSize)
|
||||
@@ -36,6 +40,10 @@ func RelayConn(ctx context.Context, a, b io.ReadWriter, bufferSize int) {
|
||||
}
|
||||
|
||||
func RelayPacket(ctx context.Context, a, b protocol.PacketReadWriter) {
|
||||
if a == nil || b == nil {
|
||||
log.Debug("Empty RW")
|
||||
return
|
||||
}
|
||||
errChan := make(chan error, 2)
|
||||
copyPacket := func(dst protocol.PacketWriter, src protocol.PacketReader) {
|
||||
for {
|
||||
|
||||
@@ -79,13 +79,15 @@ func (s *Server) handleConn(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
if req.Command == protocol.Mux {
|
||||
muxServer, err := smux.Server(inboundConn, nil)
|
||||
smuxConfig := smux.DefaultConfig()
|
||||
smuxConfig.KeepAliveDisabled = true
|
||||
muxServer, err := smux.Server(inboundConn, smuxConfig)
|
||||
common.Must(err)
|
||||
defer muxServer.Close()
|
||||
for {
|
||||
stream, err := muxServer.AcceptStream()
|
||||
if err != nil {
|
||||
log.Debug("Mux conn from", conn.RemoteAddr(), "closed:", err)
|
||||
log.Error(common.NewError("Failed to accpet mux conn from " + conn.RemoteAddr().String()).Base(err))
|
||||
return
|
||||
}
|
||||
go s.handleMuxConn(stream)
|
||||
|
||||
+4
-1
@@ -148,6 +148,9 @@ func getBasicClientConfig() *conf.GlobalConfig {
|
||||
Passwords: getPasswords("trojanpassword"),
|
||||
BufferSize: 512 * 1024,
|
||||
}
|
||||
file, err := os.OpenFile("keylog.txt", os.O_CREATE|os.O_WRONLY, 0600)
|
||||
common.Must(err)
|
||||
config.TLS.KeyLogger = file
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -381,7 +384,7 @@ func TestRealProxy(t *testing.T) {
|
||||
if os.Getenv("real_test") == "" {
|
||||
t.Skip("skipping real proxy test")
|
||||
}
|
||||
clientConfig := getBasicClientConfig()
|
||||
clientConfig := addMuxConfig(getBasicClientConfig())
|
||||
serverConfig := getBasicServerConfig()
|
||||
go RunClient(context.Background(), clientConfig)
|
||||
go RunHelloHTTPServer(context.Background())
|
||||
|
||||
Reference in New Issue
Block a user