mirror of https://github.com/telemt/telemt.git
Accept as unknown_sni_action
This commit is contained in:
parent
b88457b9bc
commit
13dc1f70bf
|
|
@ -1635,6 +1635,22 @@ mod tests {
|
||||||
cfg_mask.censorship.unknown_sni_action,
|
cfg_mask.censorship.unknown_sni_action,
|
||||||
UnknownSniAction::Mask
|
UnknownSniAction::Mask
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let cfg_accept: ProxyConfig = toml::from_str(
|
||||||
|
r#"
|
||||||
|
[server]
|
||||||
|
[general]
|
||||||
|
[network]
|
||||||
|
[access]
|
||||||
|
[censorship]
|
||||||
|
unknown_sni_action = "accept"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
cfg_accept.censorship.unknown_sni_action,
|
||||||
|
UnknownSniAction::Accept
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -1502,6 +1502,7 @@ pub enum UnknownSniAction {
|
||||||
#[default]
|
#[default]
|
||||||
Drop,
|
Drop,
|
||||||
Mask,
|
Mask,
|
||||||
|
Accept,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -813,16 +813,27 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
if client_sni.is_some() && matched_tls_domain.is_none() && preferred_user_hint.is_none() {
|
if client_sni.is_some() && matched_tls_domain.is_none() && preferred_user_hint.is_none() {
|
||||||
|
let sni = client_sni.as_deref().unwrap_or_default();
|
||||||
|
match config.censorship.unknown_sni_action {
|
||||||
|
UnknownSniAction::Accept => {
|
||||||
|
debug!(
|
||||||
|
peer = %peer,
|
||||||
|
sni = %sni,
|
||||||
|
unknown_sni = true,
|
||||||
|
unknown_sni_action = ?config.censorship.unknown_sni_action,
|
||||||
|
"TLS handshake accepted by unknown SNI policy"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
action @ (UnknownSniAction::Drop | UnknownSniAction::Mask) => {
|
||||||
auth_probe_record_failure_in(shared, peer.ip(), Instant::now());
|
auth_probe_record_failure_in(shared, peer.ip(), Instant::now());
|
||||||
maybe_apply_server_hello_delay(config).await;
|
maybe_apply_server_hello_delay(config).await;
|
||||||
let sni = client_sni.as_deref().unwrap_or_default();
|
|
||||||
let log_now = Instant::now();
|
let log_now = Instant::now();
|
||||||
if should_emit_unknown_sni_warn_in(shared, log_now) {
|
if should_emit_unknown_sni_warn_in(shared, log_now) {
|
||||||
warn!(
|
warn!(
|
||||||
peer = %peer,
|
peer = %peer,
|
||||||
sni = %sni,
|
sni = %sni,
|
||||||
unknown_sni = true,
|
unknown_sni = true,
|
||||||
unknown_sni_action = ?config.censorship.unknown_sni_action,
|
unknown_sni_action = ?action,
|
||||||
"TLS handshake rejected by unknown SNI policy"
|
"TLS handshake rejected by unknown SNI policy"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -830,15 +841,18 @@ where
|
||||||
peer = %peer,
|
peer = %peer,
|
||||||
sni = %sni,
|
sni = %sni,
|
||||||
unknown_sni = true,
|
unknown_sni = true,
|
||||||
unknown_sni_action = ?config.censorship.unknown_sni_action,
|
unknown_sni_action = ?action,
|
||||||
"TLS handshake rejected by unknown SNI policy"
|
"TLS handshake rejected by unknown SNI policy"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return match config.censorship.unknown_sni_action {
|
return match action {
|
||||||
UnknownSniAction::Drop => HandshakeResult::Error(ProxyError::UnknownTlsSni),
|
UnknownSniAction::Drop => HandshakeResult::Error(ProxyError::UnknownTlsSni),
|
||||||
UnknownSniAction::Mask => HandshakeResult::BadClient { reader, writer },
|
UnknownSniAction::Mask => HandshakeResult::BadClient { reader, writer },
|
||||||
|
UnknownSniAction::Accept => unreachable!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let secrets = decode_user_secrets_in(shared, config, preferred_user_hint);
|
let secrets = decode_user_secrets_in(shared, config, preferred_user_hint);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1006,6 +1006,64 @@ async fn tls_unknown_sni_mask_policy_falls_back_to_bad_client() {
|
||||||
assert!(matches!(result, HandshakeResult::BadClient { .. }));
|
assert!(matches!(result, HandshakeResult::BadClient { .. }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn tls_unknown_sni_accept_policy_continues_auth_path() {
|
||||||
|
let secret = [0x4Bu8; 16];
|
||||||
|
let mut config = test_config_with_secret_hex("4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b");
|
||||||
|
config.censorship.unknown_sni_action = UnknownSniAction::Accept;
|
||||||
|
|
||||||
|
let replay_checker = ReplayChecker::new(128, Duration::from_secs(60));
|
||||||
|
let rng = SecureRandom::new();
|
||||||
|
let peer: SocketAddr = "198.51.100.210:44326".parse().unwrap();
|
||||||
|
let handshake =
|
||||||
|
make_valid_tls_client_hello_with_sni_and_alpn(&secret, 0, "unknown.example", &[b"h2"]);
|
||||||
|
|
||||||
|
let result = handle_tls_handshake(
|
||||||
|
&handshake,
|
||||||
|
tokio::io::empty(),
|
||||||
|
tokio::io::sink(),
|
||||||
|
peer,
|
||||||
|
&config,
|
||||||
|
&replay_checker,
|
||||||
|
&rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(matches!(result, HandshakeResult::Success(_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn tls_unknown_sni_accept_policy_still_requires_valid_secret() {
|
||||||
|
let mut config = test_config_with_secret_hex("4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c");
|
||||||
|
config.censorship.unknown_sni_action = UnknownSniAction::Accept;
|
||||||
|
|
||||||
|
let replay_checker = ReplayChecker::new(128, Duration::from_secs(60));
|
||||||
|
let rng = SecureRandom::new();
|
||||||
|
let peer: SocketAddr = "198.51.100.211:44326".parse().unwrap();
|
||||||
|
let attacker_secret = [0x4Du8; 16];
|
||||||
|
let handshake = make_valid_tls_client_hello_with_sni_and_alpn(
|
||||||
|
&attacker_secret,
|
||||||
|
0,
|
||||||
|
"unknown.example",
|
||||||
|
&[b"h2"],
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = handle_tls_handshake(
|
||||||
|
&handshake,
|
||||||
|
tokio::io::empty(),
|
||||||
|
tokio::io::sink(),
|
||||||
|
peer,
|
||||||
|
&config,
|
||||||
|
&replay_checker,
|
||||||
|
&rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(matches!(result, HandshakeResult::BadClient { .. }));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn tls_missing_sni_keeps_legacy_auth_path() {
|
async fn tls_missing_sni_keeps_legacy_auth_path() {
|
||||||
let secret = [0x4Au8; 16];
|
let secret = [0x4Au8; 16];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue