diff options
-rw-r--r-- | handshake_ntor.go | 14 | ||||
-rw-r--r-- | obfs4.go | 18 |
2 files changed, 23 insertions, 9 deletions
diff --git a/handshake_ntor.go b/handshake_ntor.go index 80a9698..b8fd222 100644 --- a/handshake_ntor.go +++ b/handshake_ntor.go @@ -44,19 +44,23 @@ import ( ) const ( - clientMinPadLength = serverMinHandshakeLength - clientMinHandshakeLength + clientMinPadLength = (serverMinHandshakeLength + inlineSeedFrameLength) - + clientMinHandshakeLength clientMaxPadLength = framing.MaximumSegmentLength - clientMinHandshakeLength clientMinHandshakeLength = ntor.RepresentativeLength + markLength + macLength clientMaxHandshakeLength = framing.MaximumSegmentLength - serverMinPadLength = 0 - serverMaxPadLength = framing.MaximumSegmentLength - serverMinHandshakeLength + serverMinPadLength = 0 + serverMaxPadLength = framing.MaximumSegmentLength - (serverMinHandshakeLength + + inlineSeedFrameLength) serverMinHandshakeLength = ntor.RepresentativeLength + ntor.AuthLength + markLength + macLength serverMaxHandshakeLength = framing.MaximumSegmentLength markLength = sha256.Size / 2 macLength = sha256.Size / 2 + + inlineSeedFrameLength = framing.FrameOverhead + packetOverhead + seedPacketPayloadLength ) var ErrMarkNotFoundYet = errors.New("handshake: M_[C,S] not found yet") @@ -121,7 +125,7 @@ func (hs *clientHandshake) generateHandshake() ([]byte, error) { // The client handshake is X | P_C | M_C | MAC(X | P_C | M_C | E) where: // * X is the client's ephemeral Curve25519 public key representative. - // * P_C is [0,clientMaxPadLength] bytes of random padding. + // * P_C is [clientMinPadLength,clientMaxPadLength] bytes of random padding. // * M_C is HMAC-SHA256-128(serverIdentity | NodeID, X) // * MAC is HMAC-SHA256-128(serverIdentity | NodeID, X .... E) // * E is the string representation of the number of hours since the UNIX @@ -314,7 +318,7 @@ func (hs *serverHandshake) generateHandshake() ([]byte, error) { // The server handshake is Y | AUTH | P_S | M_S | MAC(Y | AUTH | P_S | M_S | E) where: // * Y is the server's ephemeral Curve25519 public key representative. // * AUTH is the ntor handshake AUTH value. - // * P_S is [0,serverMaxPadLength] bytes of random padding. + // * P_S is [serverMinPadLength,serverMaxPadLength] bytes of random padding. // * M_S is HMAC-SHA256-128(serverIdentity | NodeID, Y) // * MAC is HMAC-SHA256-128(serverIdentity | NodeID, Y .... E) // * E is the string representation of the number of hours since the UNIX @@ -263,29 +263,39 @@ func (c *Obfs4Conn) serverHandshake(nodeID *ntor.NodeID, keypair *ntor.Keypair) break } + // + // Since the current and only implementation always sends a PRNG seed for + // the length obfuscation, this makes the amount of data received from the + // server inconsistent with the length sent from the client. + // + // Rebalance this by tweaking the client mimimum padding/server maximum + // padding, and sending the PRNG seed unpadded (As in, treat the PRNG seed + // as part of the server response). See inlineSeedFrameLength in + // handshake_ntor.go. + // + // Generate/send the response. var blob []byte blob, err = hs.generateHandshake() if err != nil { return } - _, err = c.conn.Write(blob) + var frameBuf bytes.Buffer + _, err = frameBuf.Write(blob) if err != nil { return } c.state = stateEstablished // Send the PRNG seed as the first packet. - var frameBuf bytes.Buffer err = c.producePacket(&frameBuf, packetTypePrngSeed, c.listener.seed.Bytes()[:], 0) if err != nil { return } - err = c.padBurst(&frameBuf) + _, err = c.conn.Write(frameBuf.Bytes()) if err != nil { return } - _, err = c.conn.Write(frameBuf.Bytes()) return } |