Skip to content

Commit c70d512

Browse files
tatianabalalamav
authored andcommitted
Probing resistance via timeout (#28)
1 parent 15ddf9d commit c70d512

3 files changed

Lines changed: 18 additions & 10 deletions

File tree

server.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import (
4040

4141
var logger *logging.Logger
4242

43+
const tcpReadTimeout time.Duration = 59 * time.Second
44+
4345
func init() {
4446
var prefix = "%{level:.1s}%{time:2006-01-02T15:04:05.000Z07:00} %{pid} %{shortfile}]"
4547
if terminal.IsTerminal(int(os.Stderr.Fd())) {
@@ -75,7 +77,7 @@ func (s *SSServer) startPort(portNum int) error {
7577
logger.Infof("Listening TCP and UDP on port %v", portNum)
7678
port := &SSPort{cipherList: shadowsocks.NewCipherList()}
7779
// TODO: Register initial data metrics at zero.
78-
port.tcpService = shadowsocks.NewTCPService(listener, &port.cipherList, s.m)
80+
port.tcpService = shadowsocks.NewTCPService(listener, &port.cipherList, s.m, tcpReadTimeout)
7981
port.udpService = shadowsocks.NewUDPService(packetConn, s.natTimeout, &port.cipherList, s.m)
8082
s.ports[portNum] = port
8183
go port.udpService.Start()

shadowsocks/tcp.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"bytes"
1919
"fmt"
2020
"io"
21+
"io/ioutil"
2122
"net"
2223
"time"
2324

@@ -29,7 +30,7 @@ import (
2930
)
3031

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

115116
type tcpService struct {
116-
listener *net.TCPListener
117-
ciphers *CipherList
118-
m metrics.ShadowsocksMetrics
119-
isRunning bool
117+
listener *net.TCPListener
118+
ciphers *CipherList
119+
m metrics.ShadowsocksMetrics
120+
isRunning bool
121+
readTimeout time.Duration
120122
}
121123

122124
// NewTCPService creates a TCPService
123-
func NewTCPService(listener *net.TCPListener, ciphers *CipherList, m metrics.ShadowsocksMetrics) TCPService {
124-
return &tcpService{listener: listener, ciphers: ciphers, m: m}
125+
func NewTCPService(listener *net.TCPListener, ciphers *CipherList, m metrics.ShadowsocksMetrics, timeout time.Duration) TCPService {
126+
return &tcpService{listener: listener, ciphers: ciphers, m: m, readTimeout: timeout}
125127
}
126128

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

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

221+
clientConn.SetReadDeadline(time.Time{})
216222
return proxyConnection(clientConn, &proxyMetrics)
217223
}()
218224
}

shadowsocks/tcp_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import (
2121
"testing"
2222
"time"
2323

24-
logging "github.com/op/go-logging"
2524
onet "github.com/Jigsaw-Code/outline-ss-server/net"
25+
logging "github.com/op/go-logging"
2626
)
2727

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

0 commit comments

Comments
 (0)