FTA7700 commited on
Commit
d6ae4e7
·
1 Parent(s): fbe330c

Add raw TLS-only handshake diagnostic to isolate TLS layer from HTTP layer

Browse files
Files changed (3) hide show
  1. api/Cargo.lock +81 -0
  2. api/Cargo.toml +2 -0
  3. api/src/handlers/admin.rs +30 -0
api/Cargo.lock CHANGED
@@ -755,6 +755,21 @@ version = "0.2.0"
755
  source = "registry+https://github.com/rust-lang/crates.io-index"
756
  checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
757
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  [[package]]
759
  name = "form_urlencoded"
760
  version = "1.2.2"
@@ -1859,6 +1874,23 @@ dependencies = [
1859
  "typenum",
1860
  ]
1861
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1862
  [[package]]
1863
  name = "nonempty"
1864
  version = "0.7.0"
@@ -1999,6 +2031,7 @@ dependencies = [
1999
  "imageproc",
2000
  "jsonwebtoken",
2001
  "moka",
 
2002
  "openposterdb-api",
2003
  "rand 0.9.2",
2004
  "reqwest",
@@ -2011,6 +2044,7 @@ dependencies = [
2011
  "tempfile",
2012
  "thiserror 2.0.18",
2013
  "tokio",
 
2014
  "tower",
2015
  "tower-http",
2016
  "tower_governor",
@@ -2020,12 +2054,49 @@ dependencies = [
2020
  "zeroize",
2021
  ]
2022
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2023
  [[package]]
2024
  name = "openssl-probe"
2025
  version = "0.2.1"
2026
  source = "registry+https://github.com/rust-lang/crates.io-index"
2027
  checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
2028
 
 
 
 
 
 
 
 
 
 
 
 
 
2029
  [[package]]
2030
  name = "ordered-float"
2031
  version = "4.6.0"
@@ -3554,6 +3625,16 @@ dependencies = [
3554
  "syn",
3555
  ]
3556
 
 
 
 
 
 
 
 
 
 
 
3557
  [[package]]
3558
  name = "tokio-rustls"
3559
  version = "0.26.4"
 
755
  source = "registry+https://github.com/rust-lang/crates.io-index"
756
  checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
757
 
758
+ [[package]]
759
+ name = "foreign-types"
760
+ version = "0.3.2"
761
+ source = "registry+https://github.com/rust-lang/crates.io-index"
762
+ checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
763
+ dependencies = [
764
+ "foreign-types-shared",
765
+ ]
766
+
767
+ [[package]]
768
+ name = "foreign-types-shared"
769
+ version = "0.1.1"
770
+ source = "registry+https://github.com/rust-lang/crates.io-index"
771
+ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
772
+
773
  [[package]]
774
  name = "form_urlencoded"
775
  version = "1.2.2"
 
1874
  "typenum",
1875
  ]
1876
 
1877
+ [[package]]
1878
+ name = "native-tls"
1879
+ version = "0.2.18"
1880
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1881
+ checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
1882
+ dependencies = [
1883
+ "libc",
1884
+ "log",
1885
+ "openssl",
1886
+ "openssl-probe",
1887
+ "openssl-sys",
1888
+ "schannel",
1889
+ "security-framework",
1890
+ "security-framework-sys",
1891
+ "tempfile",
1892
+ ]
1893
+
1894
  [[package]]
1895
  name = "nonempty"
1896
  version = "0.7.0"
 
2031
  "imageproc",
2032
  "jsonwebtoken",
2033
  "moka",
2034
+ "native-tls",
2035
  "openposterdb-api",
2036
  "rand 0.9.2",
2037
  "reqwest",
 
2044
  "tempfile",
2045
  "thiserror 2.0.18",
2046
  "tokio",
2047
+ "tokio-native-tls",
2048
  "tower",
2049
  "tower-http",
2050
  "tower_governor",
 
2054
  "zeroize",
2055
  ]
2056
 
2057
+ [[package]]
2058
+ name = "openssl"
2059
+ version = "0.10.81"
2060
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2061
+ checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45"
2062
+ dependencies = [
2063
+ "bitflags",
2064
+ "cfg-if",
2065
+ "foreign-types",
2066
+ "libc",
2067
+ "openssl-macros",
2068
+ "openssl-sys",
2069
+ ]
2070
+
2071
+ [[package]]
2072
+ name = "openssl-macros"
2073
+ version = "0.1.1"
2074
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2075
+ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
2076
+ dependencies = [
2077
+ "proc-macro2",
2078
+ "quote",
2079
+ "syn",
2080
+ ]
2081
+
2082
  [[package]]
2083
  name = "openssl-probe"
2084
  version = "0.2.1"
2085
  source = "registry+https://github.com/rust-lang/crates.io-index"
2086
  checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
2087
 
2088
+ [[package]]
2089
+ name = "openssl-sys"
2090
+ version = "0.9.117"
2091
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2092
+ checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695"
2093
+ dependencies = [
2094
+ "cc",
2095
+ "libc",
2096
+ "pkg-config",
2097
+ "vcpkg",
2098
+ ]
2099
+
2100
  [[package]]
2101
  name = "ordered-float"
2102
  version = "4.6.0"
 
3625
  "syn",
3626
  ]
3627
 
3628
+ [[package]]
3629
+ name = "tokio-native-tls"
3630
+ version = "0.3.1"
3631
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3632
+ checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
3633
+ dependencies = [
3634
+ "native-tls",
3635
+ "tokio",
3636
+ ]
3637
+
3638
  [[package]]
3639
  name = "tokio-rustls"
3640
  version = "0.26.4"
api/Cargo.toml CHANGED
@@ -32,6 +32,8 @@ tower = { version = "0.5.3", features = ["util"] }
32
  tower_governor = { version = "0.8.0", default-features = false, features = ["axum"] }
33
  utoipa = { version = "5.4.0", features = ["axum_extras"] }
34
  hickory-resolver = "0.24"
 
 
35
 
36
  [features]
37
  test-support = []
 
32
  tower_governor = { version = "0.8.0", default-features = false, features = ["axum"] }
33
  utoipa = { version = "5.4.0", features = ["axum_extras"] }
34
  hickory-resolver = "0.24"
35
+ tokio-native-tls = "0.3"
36
+ native-tls = "0.2"
37
 
38
  [features]
39
  test-support = []
api/src/handlers/admin.rs CHANGED
@@ -793,6 +793,36 @@ pub async fn network_diagnostics() -> axum::Json<serde_json::Value> {
793
  }
794
  }
795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
796
  // Stage 3b: same request, but forced to HTTP/1.1 only — isolates whether a
797
  // PMTU/fragmentation blackhole on larger HTTP/2 handshake/frame packets is the cause.
798
  let t2b = Instant::now();
 
793
  }
794
  }
795
 
796
+ // Stage 2b: raw TLS handshake only, no HTTP request — isolates TLS itself
797
+ // from anything reqwest/HTTP-specific.
798
+ let t1b = Instant::now();
799
+ let tls_result = tokio::time::timeout(std::time::Duration::from_secs(10), async {
800
+ let tcp = tokio::net::TcpStream::connect(addr).await?;
801
+ let native_connector = native_tls::TlsConnector::new()
802
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
803
+ let connector = tokio_native_tls::TlsConnector::from(native_connector);
804
+ let _tls_stream = connector.connect(host, tcp).await
805
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
806
+ Ok::<(), std::io::Error>(())
807
+ }).await;
808
+ let tls_ms = t1b.elapsed().as_millis();
809
+ match tls_result {
810
+ Ok(Ok(())) => {
811
+ results.insert("tls_handshake_only_ms".into(), serde_json::json!(tls_ms));
812
+ results.insert("tls_handshake_only_ok".into(), serde_json::json!(true));
813
+ }
814
+ Ok(Err(e)) => {
815
+ results.insert("tls_handshake_only_ms".into(), serde_json::json!(tls_ms));
816
+ results.insert("tls_handshake_only_ok".into(), serde_json::json!(false));
817
+ results.insert("tls_handshake_only_error".into(), serde_json::json!(e.to_string()));
818
+ }
819
+ Err(_) => {
820
+ results.insert("tls_handshake_only_ms".into(), serde_json::json!(tls_ms));
821
+ results.insert("tls_handshake_only_ok".into(), serde_json::json!(false));
822
+ results.insert("tls_handshake_only_error".into(), serde_json::json!("timed out after 10s"));
823
+ }
824
+ }
825
+
826
  // Stage 3b: same request, but forced to HTTP/1.1 only — isolates whether a
827
  // PMTU/fragmentation blackhole on larger HTTP/2 handshake/frame packets is the cause.
828
  let t2b = Instant::now();