Change the server failure close delay/discard length to be consistent.

It will vary per bridge as it is based off the DRBG, but ever attempt
at poking at any given bridge will exhibit consistent behavior.
This commit is contained in:
Yawning Angel 2014-05-18 03:37:22 +00:00
parent 745d414645
commit efb9d17c8c
2 changed files with 20 additions and 15 deletions

View File

@ -44,10 +44,8 @@ const (
headerLength = framing.FrameOverhead + packetOverhead
connectionTimeout = time.Duration(30) * time.Second
minCloseThreshold = 0
maxCloseThreshold = framing.MaximumSegmentLength * 5
minCloseInterval = 0
maxCloseInterval = 60
maxCloseDelayBytes = framing.MaximumSegmentLength * 5
maxCloseDelay = 60
)
type connState int
@ -77,6 +75,9 @@ type Obfs4Conn struct {
// Server side state.
listener *Obfs4Listener
startTime time.Time
closeDelayBytes int
closeDelay int
}
func (c *Obfs4Conn) padBurst(burst *bytes.Buffer) (err error) {
@ -116,11 +117,13 @@ func (c *Obfs4Conn) closeAfterDelay() {
// I-it's not like I w-wanna handshake with you or anything. B-b-baka!
defer c.conn.Close()
delaySecs := randRange(minCloseInterval, maxCloseInterval)
toDiscard := randRange(minCloseThreshold, maxCloseThreshold)
delay := time.Duration(c.closeDelay) * time.Second
deadline := c.startTime.Add(delay)
if time.Now().After(deadline) {
return
}
delay := time.Duration(delaySecs) * time.Second
err := c.conn.SetReadDeadline(time.Now().Add(delay))
err := c.conn.SetReadDeadline(deadline)
if err != nil {
return
}
@ -129,7 +132,7 @@ func (c *Obfs4Conn) closeAfterDelay() {
// interval passes or a certain size has been reached.
discarded := 0
var buf [framing.MaximumSegmentLength]byte
for discarded < int(toDiscard) {
for discarded < int(c.closeDelayBytes) {
n, err := c.conn.Read(buf[:])
if err != nil {
return
@ -324,9 +327,6 @@ func (c *Obfs4Conn) ServerHandshake() error {
err := c.serverHandshake(c.listener.nodeID, c.listener.keyPair)
c.listener = nil
if err != nil {
// XXX: Maybe make the timeout period deterministic, since random
// hangup intervals are also suspicious. An ok value would be someting
// like the Nginx client_header_timeout (60s).
c.closeAfterDelay()
}
@ -544,6 +544,9 @@ func (l *Obfs4Listener) Accept() (net.Conn, error) {
c.Close()
return nil, err
}
cObfs.startTime = time.Now()
cObfs.closeDelayBytes = cObfs.lenProbDist.rng.Intn(maxCloseDelayBytes)
cObfs.closeDelay = cObfs.lenProbDist.rng.Intn(maxCloseDelay)
return cObfs, nil
}

View File

@ -136,6 +136,8 @@ type wDist struct {
maxValue int
values []int
buckets []float64
rng *rand.Rand
}
// newWDist creates a weighted distribution of values ranging from min to max
@ -174,15 +176,15 @@ func (w *wDist) sample() int {
func (w *wDist) reset(seed *DrbgSeed) {
// Initialize the deterministic random number generator.
drbg := newHashDrbg(seed)
dRng := rand.New(drbg)
w.rng = rand.New(drbg)
nBuckets := (w.maxValue + 1) - w.minValue
w.values = dRng.Perm(nBuckets)
w.values = w.rng.Perm(nBuckets)
w.buckets = make([]float64, nBuckets)
var totalProb float64
for i, _ := range w.buckets {
prob := dRng.Float64() * (1.0 - totalProb)
prob := w.rng.Float64() * (1.0 - totalProb)
w.buckets[i] = prob
totalProb += prob
}