Support session per connection mode (like GoQuiet) when NumConn = 0.

This commit is contained in:
notsure2 2020-07-06 18:33:52 +02:00
parent 98a7b731f3
commit dab137dbd7
6 changed files with 78 additions and 17 deletions

View File

@ -81,7 +81,7 @@ Example:
`ServerName` is the domain you want to make your ISP or firewall think you are visiting. `ServerName` is the domain you want to make your ISP or firewall think you are visiting.
`NumConn` is the amount of underlying TCP connections you want to use. The default of 4 should be appropriate for most people. Setting it too high will hinder the performance. `NumConn` is the amount of underlying TCP connections you want to use. The default of 4 should be appropriate for most people. Setting it too high will hinder the performance. Setting it to 0 will disable connection multiplexing and each TCP connection will spawn a separate short lived session that will be closed after it is terminated. This makes it behave like GoQuiet. This maybe useful for people with unstable connections.
`BrowserSig` is the browser you want to **appear** to be using. It's not relevant to the browser you are actually using. Currently, `chrome` and `firefox` are supported. `BrowserSig` is the browser you want to **appear** to be using. It's not relevant to the browser you are actually using. Currently, `chrome` and `firefox` are supported.

View File

@ -169,18 +169,20 @@ func main() {
} }
} }
useSessionPerConnection := remoteConfig.NumConn == 0
if authInfo.Unordered { if authInfo.Unordered {
acceptor := func() (*net.UDPConn, error) { acceptor := func() (*net.UDPConn, error) {
udpAddr, _ := net.ResolveUDPAddr("udp", localConfig.LocalAddr) udpAddr, _ := net.ResolveUDPAddr("udp", localConfig.LocalAddr)
return net.ListenUDP("udp", udpAddr) return net.ListenUDP("udp", udpAddr)
} }
client.RouteUDP(acceptor, localConfig.Timeout, seshMaker) client.RouteUDP(acceptor, localConfig.Timeout, seshMaker, useSessionPerConnection)
} else { } else {
listener, err := net.Listen("tcp", localConfig.LocalAddr) listener, err := net.Listen("tcp", localConfig.LocalAddr)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
client.RouteTCP(listener, localConfig.Timeout, seshMaker) client.RouteTCP(listener, localConfig.Timeout, seshMaker, useSessionPerConnection)
} }
} }

View File

@ -25,10 +25,16 @@ func MakeSession(connConfig RemoteConnConfig, authInfo AuthInfo, dialer common.D
authInfo.SessionId = 0 authInfo.SessionId = 0
} }
connsCh := make(chan net.Conn, connConfig.NumConn) numConn := connConfig.NumConn
if numConn <= 0 {
log.Infof("Using session per connection (no multiplexing)")
numConn = 1
}
connsCh := make(chan net.Conn, numConn)
var _sessionKey atomic.Value var _sessionKey atomic.Value
var wg sync.WaitGroup var wg sync.WaitGroup
for i := 0; i < connConfig.NumConn; i++ { for i := 0; i < numConn; i++ {
wg.Add(1) wg.Add(1)
go func() { go func() {
makeconn: makeconn:
@ -70,7 +76,7 @@ func MakeSession(connConfig RemoteConnConfig, authInfo AuthInfo, dialer common.D
} }
sesh := mux.MakeSession(authInfo.SessionId, seshConfig) sesh := mux.MakeSession(authInfo.SessionId, seshConfig)
for i := 0; i < connConfig.NumConn; i++ { for i := 0; i < numConn; i++ {
conn := <-connsCh conn := <-connsCh
sesh.AddConnection(conn) sesh.AddConnection(conn)
} }

View File

@ -10,14 +10,31 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration, newSeshFunc func() *mux.Session) { type ConnWithReadFromTimeout interface {
net.Conn
SetReadFromTimeout(d time.Duration)
}
type CloseSessionAfterCloseStream struct {
ConnWithReadFromTimeout
Session *mux.Session
}
func (s *CloseSessionAfterCloseStream) Close() error {
if err := s.ConnWithReadFromTimeout.Close(); err != nil {
return err
}
return s.Session.Close()
}
func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration, newSeshFunc func() *mux.Session, useSessionPerConnection bool) {
var sesh *mux.Session var sesh *mux.Session
localConn, err := bindFunc() localConn, err := bindFunc()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
streams := make(map[string]*mux.Stream) streams := make(map[string]ConnWithReadFromTimeout)
data := make([]byte, 8192) data := make([]byte, 8192)
for { for {
@ -27,17 +44,34 @@ func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration
continue continue
} }
if sesh == nil || sesh.IsClosed() { if !useSessionPerConnection && (sesh == nil || sesh.IsClosed()) {
sesh = newSeshFunc() sesh = newSeshFunc()
} }
var stream ConnWithReadFromTimeout
stream, ok := streams[addr.String()] stream, ok := streams[addr.String()]
if !ok { if !ok {
stream, err = sesh.OpenStream() connectionSession := sesh
if useSessionPerConnection {
connectionSession = newSeshFunc()
}
stream, err = connectionSession.OpenStream()
if err != nil { if err != nil {
log.Errorf("Failed to open stream: %v", err) log.Errorf("Failed to open stream: %v", err)
if useSessionPerConnection {
connectionSession.Close()
}
continue continue
} }
if useSessionPerConnection {
stream = &CloseSessionAfterCloseStream{
ConnWithReadFromTimeout: stream,
Session: connectionSession,
}
}
streams[addr.String()] = stream streams[addr.String()] = stream
proxyAddr := addr proxyAddr := addr
go func() { go func() {
@ -70,7 +104,7 @@ func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration
} }
} }
func RouteTCP(listener net.Listener, streamTimeout time.Duration, newSeshFunc func() *mux.Session) { func RouteTCP(listener net.Listener, streamTimeout time.Duration, newSeshFunc func() *mux.Session, useSessionPerConnection bool) {
var sesh *mux.Session var sesh *mux.Session
for { for {
localConn, err := listener.Accept() localConn, err := listener.Accept()
@ -78,7 +112,7 @@ func RouteTCP(listener net.Listener, streamTimeout time.Duration, newSeshFunc fu
log.Fatal(err) log.Fatal(err)
continue continue
} }
if sesh == nil || sesh.IsClosed() { if !useSessionPerConnection && (sesh == nil || sesh.IsClosed()) {
sesh = newSeshFunc() sesh = newSeshFunc()
} }
go func() { go func() {
@ -89,12 +123,30 @@ func RouteTCP(listener net.Listener, streamTimeout time.Duration, newSeshFunc fu
localConn.Close() localConn.Close()
return return
} }
stream, err := sesh.OpenStream()
connectionSession := sesh
if useSessionPerConnection {
connectionSession = newSeshFunc()
}
var stream ConnWithReadFromTimeout
stream, err = connectionSession.OpenStream()
if err != nil { if err != nil {
log.Errorf("Failed to open stream: %v", err) log.Errorf("Failed to open stream: %v", err)
localConn.Close() localConn.Close()
if useSessionPerConnection {
connectionSession.Close()
}
return return
} }
if useSessionPerConnection {
stream = &CloseSessionAfterCloseStream{
ConnWithReadFromTimeout: stream,
Session: connectionSession,
}
}
_, err = stream.Write(data[:i]) _, err = stream.Write(data[:i])
if err != nil { if err != nil {
log.Errorf("Failed to write to stream: %v", err) log.Errorf("Failed to write to stream: %v", err)

View File

@ -172,8 +172,8 @@ func (raw *RawConfig) SplitConfigs(worldState common.WorldState) (local LocalCon
return nullErr("RemotePort") return nullErr("RemotePort")
} }
remote.RemoteAddr = net.JoinHostPort(raw.RemoteHost, raw.RemotePort) remote.RemoteAddr = net.JoinHostPort(raw.RemoteHost, raw.RemotePort)
if raw.NumConn == 0 { if raw.NumConn <= 0 {
return nullErr("NumConn") raw.NumConn = 0
} }
remote.NumConn = raw.NumConn remote.NumConn = raw.NumConn

View File

@ -139,6 +139,7 @@ func establishSession(lcc client.LocalConnConfig, rcc client.RemoteConnConfig, a
return client.MakeSession(rcc, ai, ckClientDialer, false) return client.MakeSession(rcc, ai, ckClientDialer, false)
} }
useSessionPerConnection := rcc.NumConn == 0
var proxyToCkClientD common.Dialer var proxyToCkClientD common.Dialer
if ai.Unordered { if ai.Unordered {
addrCh := make(chan *net.UDPAddr, 1) addrCh := make(chan *net.UDPAddr, 1)
@ -151,12 +152,12 @@ func establishSession(lcc client.LocalConnConfig, rcc client.RemoteConnConfig, a
addrCh <- conn.LocalAddr().(*net.UDPAddr) addrCh <- conn.LocalAddr().(*net.UDPAddr)
return conn, err return conn, err
} }
go client.RouteUDP(acceptor, lcc.Timeout, clientSeshMaker) go client.RouteUDP(acceptor, lcc.Timeout, clientSeshMaker, useSessionPerConnection)
proxyToCkClientD = mDialer proxyToCkClientD = mDialer
} else { } else {
var proxyToCkClientL *connutil.PipeListener var proxyToCkClientL *connutil.PipeListener
proxyToCkClientD, proxyToCkClientL = connutil.DialerListener(10 * 1024) proxyToCkClientD, proxyToCkClientL = connutil.DialerListener(10 * 1024)
go client.RouteTCP(proxyToCkClientL, lcc.Timeout, clientSeshMaker) go client.RouteTCP(proxyToCkClientL, lcc.Timeout, clientSeshMaker, useSessionPerConnection)
} }
// set up server // set up server