Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent replays of server data #78

Merged
merged 15 commits into from
Aug 27, 2020
Merged

Prevent replays of server data #78

merged 15 commits into from
Aug 27, 2020

Conversation

bemasc
Copy link

@bemasc bemasc commented Aug 18, 2020

No description provided.

@bemasc bemasc mentioned this pull request Aug 18, 2020
@fortuna fortuna self-requested a review August 18, 2020 21:26
@fortuna fortuna marked this pull request as ready for review August 18, 2020 21:26
@fortuna fortuna changed the base branch from fortuna-fix to master August 18, 2020 21:26
shadowsocks/stream.go Outdated Show resolved Hide resolved
shadowsocks/stream.go Outdated Show resolved Hide resolved
shadowsocks/tcp.go Outdated Show resolved Hide resolved
shadowsocks/stream.go Outdated Show resolved Hide resolved
shadowsocks/tcp.go Outdated Show resolved Hide resolved
shadowsocks/tcp.go Outdated Show resolved Hide resolved
shadowsocks/stream.go Show resolved Hide resolved
shadowsocks/stream.go Outdated Show resolved Hide resolved
@fortuna
Copy link

fortuna commented Aug 19, 2020

@riobard, answering your comment #77 (comment) here to keep it in context.

Yeah, this new implementation has a separate filter for the server. I'm asking @bemasc to add a new error string to track that in the Prometheus metrics, so we'll be able to tell whether the attacker is actually using that.

He decided to use a different approach:

salt_prefix = 28 random bytes
encrypted, tag = cipher.seal(nil, 0, salt_prefix, "outline-salt-mark")
salt = salt_prefix || tag

Validation happens by repeating the operation and checking the tag.

This way we don't need to rewire the code to get the cipher secret.

@fortuna fortuna changed the title Use the shadowsocks cipher to mark the salt Prevent replays of server data Aug 19, 2020
@bemasc bemasc requested a review from fortuna August 20, 2020 01:16
@@ -259,7 +269,11 @@ func (s *tcpService) handleConnection(listenerPort int, clientConn onet.DuplexCo
logger.Debugf("TCP Error: %v: %v", connError.Message, connError.Cause)
status = connError.Status
}
s.m.AddClosedTCPConnection(clientLocation, keyID, status, proxyMetrics, timeToCipher, connDuration)
var id string
if cipherEntry != nil {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this always true if keyErr is nil? This if is confusing me.

Copy link
Author

@bemasc bemasc Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is equivalent to if keyErr == nil. This code runs whether keyErr is nil or not. If it would be clearer, we could move this to line 234.

@riobard
Copy link

riobard commented Aug 20, 2020

@fortuna I think the salt-size issue still applies here. Assuming you're using 32-byte salt and 28-byte random, that leaves 4 bytes for the tag. Not sure if it's sufficient.

@bemasc
Copy link
Author

bemasc commented Aug 20, 2020

@riobard With a 4-byte tag, the false-positive rejection probability is one in 4 billion. That's much lower than the false positive rejection rate from our existing replay defense, so I think it's acceptable.

@riobard
Copy link

riobard commented Aug 20, 2020

@bemasc Ah, right! I forgot about the Bloom filter false positive rate :P Anyway, does Outline enforce 32-byte salt?

@fortuna
Copy link

fortuna commented Aug 20, 2020

The Outline Server only uses chacha20-ietf-poly1305, which has a 32-byte salt.
outline-ss-server supports only the AEAD ciphers, but all of them, including aes-128-gcm, which has a 16-byte salt.

I recommend against aes-128-gcm, and if someone is worried about a 12-byte salt, they can always migrate to the longer ciphers.

shadowsocks/salt_generator.go Outdated Show resolved Hide resolved
bemasc pushed a commit that referenced this pull request Aug 21, 2020
This was caught by the presubmit in #78
@bemasc
Copy link
Author

bemasc commented Aug 21, 2020

I recommend against aes-128-gcm, and if someone is worried about a 12-byte salt, they can always migrate to the longer ciphers.

In this version I added a check that disables the marking for this case, to be conservative.

Copy link

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I like that you added the test. This looks really good. I only have a small suggestion for the case of a small salt, so we catch that early, output a warning, and keep the salt generator simpler.

shadowsocks/salt_generator.go Outdated Show resolved Hide resolved
Copy link

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add a section to the README explaining how the replay protection works? It can be short, but I'd like to have something I can point to other than the code. Cover both the client and server replays. Thanks!

@bemasc bemasc requested a review from fortuna August 24, 2020 15:24
shadowsocks/salt_generator.go Outdated Show resolved Hide resolved
shadowsocks/salt_generator.go Outdated Show resolved Hide resolved
@fortuna
Copy link

fortuna commented Aug 24, 2020

@madeye You may be interested in this marked salt approach for shadowsocks-libev. It removes the need for saving server salts and can survive resets and old replays.

@bemasc
Copy link
Author

bemasc commented Aug 25, 2020

Could you also add a section to the README explaining how the replay protection works?

Done. I put it in a separate file and linked it from the README.

Copy link

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Thanks for suggesting and implementing the crypto salts. And I really like the document you added too. I'm looking forward to releasing this!

shadowsocks/cipher_list.go Show resolved Hide resolved
@bemasc bemasc merged commit 13f8610 into master Aug 27, 2020
@bemasc bemasc deleted the bemasc-blocksalt branch August 27, 2020 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants