feat: complete wgcloak v1 transports
This commit is contained in:
1 parent
49ec9d8c33
commit
cedab4910e
47 files changed
+2849
-400
No files matched your search
+118
-1
@@ -248,6 +248,84 @@ async fn malformed_and_unauthenticated_packets_do_not_kill_server() {
|
||||
server_task.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn direct_auth_attempt_limit_expires_and_recovers() {
|
||||
let backend = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
let backend_addr = backend.local_addr().unwrap();
|
||||
let (mut server_config, _) = configs(45790, backend_addr.port());
|
||||
server_config.limits.max_auth_attempts_per_ip = 2;
|
||||
server_config.limits.auth_attempt_window_secs = 1;
|
||||
let server = DirectUdpServer::bind(server_config).await.unwrap();
|
||||
let stats = server.stats();
|
||||
let server_task = tokio::spawn(server.run());
|
||||
let raw = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
let wrong_secret = [0xabu8; 32];
|
||||
let mut response = [0u8; 2048];
|
||||
|
||||
for nonce_value in [1u8, 2] {
|
||||
let mut nonce = [0u8; 16];
|
||||
nonce[0] = nonce_value;
|
||||
let hello = protocol::HelloPacket::authenticated(
|
||||
&wrong_secret,
|
||||
Bytes::from_static(b"test"),
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs(),
|
||||
nonce,
|
||||
)
|
||||
.unwrap();
|
||||
raw.send_to(&hello.encode().unwrap(), "127.0.0.1:45790")
|
||||
.await
|
||||
.unwrap();
|
||||
let (len, _) = timeout(Duration::from_secs(2), raw.recv_from(&mut response))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
protocol::parse_packet(&response[..len]),
|
||||
Ok(protocol::Packet::Reject(protocol::RejectPacket {
|
||||
reason: protocol::RejectReason::AuthenticationFailed,
|
||||
..
|
||||
}))
|
||||
));
|
||||
}
|
||||
|
||||
let mut limited_nonce = [0u8; 16];
|
||||
limited_nonce[0] = 3;
|
||||
let limited = protocol::HelloPacket::authenticated(
|
||||
&wrong_secret,
|
||||
Bytes::from_static(b"test"),
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs(),
|
||||
limited_nonce,
|
||||
)
|
||||
.unwrap();
|
||||
raw.send_to(&limited.encode().unwrap(), "127.0.0.1:45790")
|
||||
.await
|
||||
.unwrap();
|
||||
let (len, _) = timeout(Duration::from_secs(2), raw.recv_from(&mut response))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
protocol::parse_packet(&response[..len]),
|
||||
Ok(protocol::Packet::Reject(protocol::RejectPacket {
|
||||
reason: protocol::RejectReason::RateLimited,
|
||||
..
|
||||
}))
|
||||
));
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(1_100)).await;
|
||||
let client_config = configs(45790, backend_addr.port()).1;
|
||||
let session = DirectUdpSession::connect(&client_config).await.unwrap();
|
||||
assert!(stats.snapshot().rate_limited_attempts >= 1);
|
||||
session.close().await.unwrap();
|
||||
server_task.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn authenticated_source_port_change_updates_return_peer() {
|
||||
let backend = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
@@ -320,7 +398,9 @@ async fn authenticated_source_port_change_updates_return_peer() {
|
||||
async fn identical_hello_retransmission_recovers_original_accept_and_session() {
|
||||
let backend = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
let backend_addr = backend.local_addr().unwrap();
|
||||
let (server_config, _) = configs(45788, backend_addr.port());
|
||||
let (mut server_config, _) = configs(45788, backend_addr.port());
|
||||
// The cached exact retry must not consume a second auth-attempt slot.
|
||||
server_config.limits.max_auth_attempts_per_ip = 1;
|
||||
let server = DirectUdpServer::bind(server_config).await.unwrap();
|
||||
let observer = server.handle();
|
||||
let server_task = tokio::spawn(server.run());
|
||||
@@ -481,6 +561,43 @@ async fn identical_hello_retransmission_recovers_original_accept_and_session() {
|
||||
server_task.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn direct_udp_supports_ipv6_loopback_listen() {
|
||||
let probe = match UdpSocket::bind("[::1]:0").await {
|
||||
Ok(socket) => socket,
|
||||
Err(_) => return,
|
||||
};
|
||||
let port = probe.local_addr().unwrap().port();
|
||||
drop(probe);
|
||||
let backend = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
let backend_addr = backend.local_addr().unwrap();
|
||||
let (mut server_config, mut client_config) = configs(port, backend_addr.port());
|
||||
server_config.server.listen = "::1".to_owned();
|
||||
client_config.client.server = "::1".to_owned();
|
||||
let server = DirectUdpServer::bind(server_config).await.unwrap();
|
||||
let server_task = tokio::spawn(server.run());
|
||||
let backend_task = tokio::spawn(async move {
|
||||
let mut buffer = [0u8; 2048];
|
||||
let (len, peer) = backend.recv_from(&mut buffer).await.unwrap();
|
||||
backend.send_to(&buffer[..len], peer).await.unwrap();
|
||||
});
|
||||
let session = DirectUdpSession::connect(&client_config).await.unwrap();
|
||||
session
|
||||
.send_datagram(Bytes::from_static(b"ipv6"))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
timeout(Duration::from_secs(2), session.recv_datagram())
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Bytes::from_static(b"ipv6")
|
||||
);
|
||||
session.close().await.unwrap();
|
||||
backend_task.await.unwrap();
|
||||
server_task.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn flags_are_authenticated_and_invalid_close_cannot_remove_session() {
|
||||
let backend = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
|
||||
Reference in new issue
Block a user