RFC: Add a configurable sized nonce generator
The aim of This PR is to reduce the amplification factor in reflection attacks against our TURN servers. To summarize, it seems that recently TURN servers were targeted in large-scale reflection+amplification attacks that abuse the TURN allocation request/response mechanism. See background and the corresponding coturn issue.
The default amplification factor, the ratio of the size of the initial Allocation Response message reflected by the server to the victim IP compared to the size of the initial Allocation Request sent by the malevolent client, for pion/turn is currently about 2.2x. This makes pion TURN servers an appealing target for reflection+amplification attacks. Luckily we don't not generate the SOFTWARE attribute by default and by using a 2 byte REALM we can go down to about 2.1x without touching the code. The rest, however, is mostly caused by the 80 byte nonces pion/turn uses.
This PR makes the nonce size configurable and removes some redundancy by using a shorter 4-byte timestamp at one minute precision and using a more efficient base36 encoder/decoder. The default is 4 bytes timestamp + 12 byte truncated HMAC hash, which gives about 24 bytes long nonces including the overhead of base36 encoding and padding.
Warning: this PR has not been tested against real browsers. The pion/turn TURN client seems to handle the smaller nonces reliably though.
Codecov Report
:x: Patch coverage is 68.42105% with 36 lines in your changes missing coverage. Please review.
:warning: Please upload report for BASE (master@78b5b11). Learn more about missing BASE report.
:warning: Report is 1 commits behind head on master.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| internal/server/short_nonce.go | 56.00% | 24 Missing and 9 partials :warning: |
| internal/server/base36.go | 91.89% | 2 Missing and 1 partial :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## master #460 +/- ##
=========================================
Coverage ? 68.63%
=========================================
Files ? 45
Lines ? 3300
Branches ? 0
=========================================
Hits ? 2265
Misses ? 863
Partials ? 172
| Flag | Coverage Δ | |
|---|---|---|
| go | 68.63% <68.42%> (?) |
|
| wasm | 26.90% <64.91%> (?) |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
This is awesome.
Warning: this PR has not been tested against real browsers. The pion/turn TURN client seems to handle the smaller nonces reliably though.
Okay, I'm going to test this branch with real browsers.
Redid the PR to pass the linter checks. Always full of excitement. Maybe we should add some tests for the base36 encoder/decoder, I just copy-pasted a quick implementation from an older repo.
I've remade the PR with your modifications, thanks.
Merged this into STUNner dev, no reports so far. Also tested with STUNner+LiveKit+FF, no issues.
@JoeTurki I've rebased the commit and added tests for the base36 encoder. pls merge if you think this is OK.
@JoeTurki rebased on top of master, I think this can be safely merged. This would let the new nonce manager to get some broader testing: we have not seen any browser incompatibility yet but you can never know.
We have created a minimal tool to test the amplification factor of different TURN servers, see here. Below are the results.
| Server | Amplification factor |
|---|---|
| undisclosed proprietary TURN server | 4.22x |
| pion/turn (default) | 3.44x |
| pion/turn (no realm) | 3.22x |
| short-nonce (default) | 1.89x |
| short-nonce (no realm) | 1.44x |
| short-nonce (maclen=2, no realm) | 1.22x |
This PR reduces the amplification factor from 3.44x of default pion/turn to 1.44x (using an empty realm which I'm not sure is valid). Security savvy people can enforce maclen=2 during server initialization to bring down the amplification factor to 1.22x. I think there's room for further improvement (use a fully random nonce, say, 4 bytes), not sure it's worth the pain.
Perfect, thank you <3