Skip to content

Commit

Permalink
Probing resistance via timeout (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
tatianab authored and alalamav committed Sep 4, 2019
1 parent 15ddf9d commit c70d512
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 10 deletions.
4 changes: 3 additions & 1 deletion server.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import (

var logger *logging.Logger

const tcpReadTimeout time.Duration = 59 * time.Second

func init() {
var prefix = "%{level:.1s}%{time:2006-01-02T15:04:05.000Z07:00} %{pid} %{shortfile}]"
if terminal.IsTerminal(int(os.Stderr.Fd())) {
Expand Down Expand Up @@ -75,7 +77,7 @@ func (s *SSServer) startPort(portNum int) error {
logger.Infof("Listening TCP and UDP on port %v", portNum)
port := &SSPort{cipherList: shadowsocks.NewCipherList()}
// TODO: Register initial data metrics at zero.
port.tcpService = shadowsocks.NewTCPService(listener, &port.cipherList, s.m)
port.tcpService = shadowsocks.NewTCPService(listener, &port.cipherList, s.m, tcpReadTimeout)
port.udpService = shadowsocks.NewUDPService(packetConn, s.natTimeout, &port.cipherList, s.m)
s.ports[portNum] = port
go port.udpService.Start()
Expand Down
22 changes: 14 additions & 8 deletions shadowsocks/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net"
"time"

Expand All @@ -29,7 +30,7 @@ import (
)

// Reads bytes from reader and appends to buf to ensure the needed number of bytes.
// The cpacity of buf must be at least bytesNeeded.
// The capacity of buf must be at least bytesNeeded.
func ensureBytes(reader io.Reader, buf []byte, bytesNeeded int) ([]byte, error) {
if cap(buf) < bytesNeeded {
return buf, io.ErrShortBuffer
Expand Down Expand Up @@ -109,19 +110,20 @@ func findAccessKey(clientConn onet.DuplexConn, cipherList CipherList) (string, o
ssw := NewShadowsocksWriter(clientConn, cipher)
return id, onet.WrapConn(clientConn, ssr, ssw).(onet.DuplexConn), nil
}
return "", nil, fmt.Errorf("Could not find valid TCP cipher")
return "", clientConn, fmt.Errorf("Could not find valid TCP cipher")
}

type tcpService struct {
listener *net.TCPListener
ciphers *CipherList
m metrics.ShadowsocksMetrics
isRunning bool
listener *net.TCPListener
ciphers *CipherList
m metrics.ShadowsocksMetrics
isRunning bool
readTimeout time.Duration
}

// NewTCPService creates a TCPService
func NewTCPService(listener *net.TCPListener, ciphers *CipherList, m metrics.ShadowsocksMetrics) TCPService {
return &tcpService{listener: listener, ciphers: ciphers, m: m}
func NewTCPService(listener *net.TCPListener, ciphers *CipherList, m metrics.ShadowsocksMetrics, timeout time.Duration) TCPService {
return &tcpService{listener: listener, ciphers: ciphers, m: m, readTimeout: timeout}
}

// TCPService is a Shadowsocks TCP service that can be started and stopped.
Expand Down Expand Up @@ -189,6 +191,7 @@ func (s *tcpService) Start() {
}()
connStart := time.Now()
clientConn.(*net.TCPConn).SetKeepAlive(true)
clientConn.SetReadDeadline(connStart.Add(s.readTimeout))
keyID := ""
var proxyMetrics metrics.ProxyMetrics
var timeToCipher time.Duration
Expand All @@ -210,9 +213,12 @@ func (s *tcpService) Start() {
timeToCipher = time.Now().Sub(findStartTime)

if err != nil {
logger.Debugf("Failed to find a valid cipher after reading %v bytes: %v", proxyMetrics.ClientProxy, err)
io.Copy(ioutil.Discard, clientConn) // drain socket
return onet.NewConnectionError("ERR_CIPHER", "Failed to find a valid cipher", err)
}

clientConn.SetReadDeadline(time.Time{})
return proxyConnection(clientConn, &proxyMetrics)
}()
}
Expand Down
2 changes: 1 addition & 1 deletion shadowsocks/tcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import (
"testing"
"time"

logging "github.com/op/go-logging"
onet "github.com/Jigsaw-Code/outline-ss-server/net"
logging "github.com/op/go-logging"
)

// Simulates receiving invalid TCP connection attempts on a server with 100 ciphers.
Expand Down

0 comments on commit c70d512

Please sign in to comment.