mirror of https://github.com/ospab/ostp.git
feat: disguise UoT handshake as WebSocket to bypass DPI and proxies
This commit is contained in:
parent
975a0dc0d9
commit
834c244f94
|
|
@ -90,8 +90,11 @@ pub async fn connect_xhttp(
|
||||||
let req = format!(
|
let req = format!(
|
||||||
"GET /stream HTTP/1.1\r\n\
|
"GET /stream HTTP/1.1\r\n\
|
||||||
Host: {}\r\n\
|
Host: {}\r\n\
|
||||||
|
Upgrade: websocket\r\n\
|
||||||
|
Connection: upgrade\r\n\
|
||||||
|
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\
|
||||||
|
Sec-WebSocket-Version: 13\r\n\
|
||||||
Authorization: Bearer {}\r\n\
|
Authorization: Bearer {}\r\n\
|
||||||
Connection: keep-alive\r\n\
|
|
||||||
\r\n",
|
\r\n",
|
||||||
http_host, auth_token
|
http_host, auth_token
|
||||||
);
|
);
|
||||||
|
|
@ -124,8 +127,8 @@ pub async fn connect_xhttp(
|
||||||
if buf[..header_len].windows(4).any(|w| w == b"\r\n\r\n") { break; }
|
if buf[..header_len].windows(4).any(|w| w == b"\r\n\r\n") { break; }
|
||||||
}
|
}
|
||||||
let resp = String::from_utf8_lossy(&buf[..header_len]);
|
let resp = String::from_utf8_lossy(&buf[..header_len]);
|
||||||
if !resp.starts_with("HTTP/1.1 200 OK") {
|
if !resp.starts_with("HTTP/1.1 101 ") && !resp.starts_with("HTTP/1.1 200 ") {
|
||||||
anyhow::bail!("xHTTP handshake failed: expected 200 OK, got: {}", resp.lines().next().unwrap_or(""));
|
anyhow::bail!("xHTTP handshake failed: expected 101 or 200, got: {}", resp.lines().next().unwrap_or(""));
|
||||||
}
|
}
|
||||||
if !resp.to_ascii_lowercase().contains("x-ostp-server:") {
|
if !resp.to_ascii_lowercase().contains("x-ostp-server:") {
|
||||||
anyhow::bail!("xHTTP handshake failed: endpoint is not an OSTP server (missing X-Ostp-Server header)");
|
anyhow::bail!("xHTTP handshake failed: endpoint is not an OSTP server (missing X-Ostp-Server header)");
|
||||||
|
|
@ -152,8 +155,8 @@ pub async fn connect_xhttp(
|
||||||
if buf[..header_len].windows(4).any(|w| w == b"\r\n\r\n") { break; }
|
if buf[..header_len].windows(4).any(|w| w == b"\r\n\r\n") { break; }
|
||||||
}
|
}
|
||||||
let resp = String::from_utf8_lossy(&buf[..header_len]);
|
let resp = String::from_utf8_lossy(&buf[..header_len]);
|
||||||
if !resp.starts_with("HTTP/1.1 200 OK") {
|
if !resp.starts_with("HTTP/1.1 101 ") && !resp.starts_with("HTTP/1.1 200 ") {
|
||||||
anyhow::bail!("xHTTP handshake failed: expected 200 OK, got: {}", resp.lines().next().unwrap_or(""));
|
anyhow::bail!("xHTTP handshake failed: expected 101 or 200, got: {}", resp.lines().next().unwrap_or(""));
|
||||||
}
|
}
|
||||||
if !resp.to_ascii_lowercase().contains("x-ostp-server:") {
|
if !resp.to_ascii_lowercase().contains("x-ostp-server:") {
|
||||||
anyhow::bail!("xHTTP handshake failed: endpoint is not an OSTP server (missing X-Ostp-Server header)");
|
anyhow::bail!("xHTTP handshake failed: endpoint is not an OSTP server (missing X-Ostp-Server header)");
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,8 @@ pub async fn handle_tcp_connection(
|
||||||
anyhow::bail!("unauthorized (invalid HMAC)");
|
anyhow::bail!("unauthorized (invalid HMAC)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reply 200 OK
|
// Reply 101 Switching Protocols
|
||||||
let response = "HTTP/1.1 200 OK\r\nX-Ostp-Server: 1\r\nConnection: keep-alive\r\n\r\n";
|
let response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nX-Ostp-Server: 1\r\n\r\n";
|
||||||
stream.write_all(response.as_bytes()).await?;
|
stream.write_all(response.as_bytes()).await?;
|
||||||
|
|
||||||
info!("UoT client authenticated from {}", peer_addr);
|
info!("UoT client authenticated from {}", peer_addr);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue