Skip to content

Commit 7109669

Browse files
committed
SECURITY: First 6 bytes of payload should be printable characters
Observation shows that prepending 6 bytes of printable characters to random payload will exempt it from blocking. by 2022-01-13 gfw.report
1 parent 19f7653 commit 7109669

File tree

3 files changed

+55
-29
lines changed

3 files changed

+55
-29
lines changed

Cargo.lock

+39-29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/shadowsocks/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ spin = { version = "0.9", features = ["std"], optional = true }
4848
pin-project = "1.0"
4949
bloomfilter = { version = "1.0.8", optional = true }
5050
thiserror = "1.0"
51+
rand = "0.8"
5152

5253
serde = { version = "1.0", features = ["derive"] }
5354
serde_urlencoded = "0.7"

crates/shadowsocks/src/context.rs

+15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{io, net::SocketAddr, sync::Arc};
44

55
use byte_string::ByteStr;
66
use log::warn;
7+
use rand::Rng;
78

89
use crate::{
910
config::{ReplayAttackPolicy, ServerType},
@@ -66,6 +67,20 @@ impl Context {
6667
loop {
6768
random_iv_or_salt(nonce);
6869

70+
// SECURITY: First 6 bytes of payload should be printable characters
71+
// Observation shows that prepending 6 bytes of printable characters to random payload will exempt it from blocking.
72+
// by 2022-01-13 gfw.report.
73+
const SECURITY_PRINTABLE_PREFIX_LEN: usize = 6;
74+
if nonce.len() >= SECURITY_PRINTABLE_PREFIX_LEN {
75+
// Printable characters follows definition of isprint in C/C++
76+
static ASCII_PRINTABLE_CHARS: &[u8] = br##"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ "##;
77+
78+
let mut rng = rand::thread_rng();
79+
for b in nonce.iter_mut().take(SECURITY_PRINTABLE_PREFIX_LEN) {
80+
*b = ASCII_PRINTABLE_CHARS[rng.gen_range::<usize, _>(0..ASCII_PRINTABLE_CHARS.len())];
81+
}
82+
}
83+
6984
// Salt already exists, generate a new one.
7085
if unique && self.check_nonce_and_set(nonce) {
7186
continue;

0 commit comments

Comments
 (0)