From b30f724dd237c6c687d0f31af4c80889d5697ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Wed, 28 Oct 2026 23:45:49 +0900 Subject: [PATCH] fix(dgw): connect to ngrok through its current agent endpoint Gateway now connects to ngrok through `connect.ngrok-agent.com`, the endpoint ngrok documents for firewall allowlists, instead of the legacy `tunnel.ngrok.com`. Networks that only allow the documented hostname no longer block the tunnel. `ServerAddr` can still point to another endpoint, such as a regional one. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 293 ++++++++++++++++++------------- README.md | 5 +- config_schema.json | 2 +- devolutions-gateway/Cargo.toml | 2 +- devolutions-gateway/src/ngrok.rs | 100 ++++++----- 5 files changed, 226 insertions(+), 176 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e64afe8881..528c3fbd95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,7 +123,7 @@ dependencies = [ "picky-asn1-x509", "quinn", "rcgen", - "rustls 0.23.43", + "rustls", "serde", "sha2 0.10.9", "socket2 0.5.10", @@ -406,17 +406,6 @@ dependencies = [ "syn 2.0.118", ] -[[package]] -name = "async-rustls" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b21a03b7c21702a0110f9f8d228763a533570deb376119042dabf33c37a01a" -dependencies = [ - "futures-io", - "rustls 0.20.9", - "webpki", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -737,12 +726,6 @@ dependencies = [ "safemem", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -1775,8 +1758,8 @@ dependencies = [ "rand 0.8.7", "rcgen", "reqwest", - "rustls 0.23.43", - "rustls-pemfile 2.2.0", + "rustls", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", @@ -1889,7 +1872,7 @@ dependencies = [ "reqwest", "rstest", "rustls-cng", - "rustls-native-certs", + "rustls-native-certs 0.8.4", "secrecy", "secure-memory", "serde", @@ -2229,6 +2212,12 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "doc-comment" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" + [[package]] name = "dunce" version = "1.0.5" @@ -2516,7 +2505,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.9", + "spin", ] [[package]] @@ -2635,6 +2624,17 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "futures-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" +dependencies = [ + "futures-io", + "rustls", + "rustls-pki-types", +] + [[package]] name = "futures-sink" version = "0.3.34" @@ -2915,7 +2915,7 @@ dependencies = [ "atomic-polyfill", "hash32", "rustc_version", - "spin 0.9.9", + "spin", "stable_deref_trait", ] @@ -3157,6 +3157,25 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-http-proxy" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd1d471ea2f65ba45eddb1d6ab7d58ac2671d2d4ac14da5c6516ae1d97e1327a" +dependencies = [ + "bytes 1.12.1", + "futures-util", + "headers", + "http 1.4.2", + "hyper 1.10.1", + "hyper-rustls", + "hyper-util", + "pin-project-lite 0.2.17", + "tokio 1.52.3", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-rustls" version = "0.27.9" @@ -3166,8 +3185,8 @@ dependencies = [ "http 1.4.2", "hyper 1.10.1", "hyper-util", - "rustls 0.23.43", - "rustls-native-certs", + "rustls", + "rustls-native-certs 0.8.4", "tokio 1.52.3", "tokio-rustls", "tower-service", @@ -3727,7 +3746,7 @@ dependencies = [ "ironrdp-tokio", "qoicoubeh", "rayon", - "rustls-pemfile 2.2.0", + "rustls-pemfile", "tokio 1.52.3", "tokio-rustls", "tracing", @@ -3849,14 +3868,14 @@ dependencies = [ "mcp-proxy", "native-tls", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "proxy-http", "proxy-socks", "proxy-types", "proxy_cfg", - "rustls 0.23.43", - "rustls-native-certs", - "rustls-pemfile 2.2.0", + "rustls", + "rustls-native-certs 0.8.4", + "rustls-pemfile", "seahorse", "sysinfo", "tinyjson", @@ -4546,9 +4565,9 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "muxado" -version = "0.4.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e92b89ac3127251efde6f5a9586e5aae99468d06fcf9f133b377f58d5ed66446" +checksum = "8ac23a4a060b60ba42de5e988886790ba6aeb86e0ae0c879c637f5bbf0b78299" dependencies = [ "async-trait", "awaitdrop", @@ -4557,7 +4576,7 @@ dependencies = [ "futures", "pin-project 1.1.13", "rand 0.8.7", - "thiserror 1.0.69", + "thiserror 2.0.20", "tokio 1.52.3", "tokio-util", "tracing", @@ -4572,10 +4591,10 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] @@ -4707,30 +4726,41 @@ dependencies = [ [[package]] name = "ngrok" -version = "0.13.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1454b1edbc5f2c8ff3242c237cb84388b50eced8eb26b4204e49698ed6511784" +checksum = "10f6c455d972d973dded17538cb01426ca79eccb9774ae8ab8f1af637f469f3f" dependencies = [ "arc-swap", - "async-rustls", "async-trait", "awaitdrop", - "base64 0.13.1", + "axum-core 0.4.5", + "base64 0.21.7", + "bitflags 2.13.1", "bytes 1.12.1", "futures", + "futures-rustls", + "futures-util", "hostname 0.3.1", + "hyper-http-proxy", + "hyper-util", "muxado", "once_cell", "parking_lot", + "pin-project 1.1.13", + "proxy-protocol", "regex", - "rustls-pemfile 1.0.4", + "rustls-native-certs 0.7.3", + "rustls-pemfile", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.20", "tokio 1.52.3", "tokio-retry", + "tokio-socks", "tokio-util", + "tower-service", "tracing", + "url", "windows-sys 0.45.0", ] @@ -5139,6 +5169,12 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + [[package]] name = "openssl-probe" version = "0.2.1" @@ -6029,6 +6065,16 @@ dependencies = [ "tokio 1.52.3", ] +[[package]] +name = "proxy-protocol" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e50c72c21c738f5c5f350cc33640aee30bf7cd20f9d9da20ed41bce2671d532" +dependencies = [ + "bytes 1.12.1", + "snafu", +] + [[package]] name = "proxy-server" version = "0.0.0" @@ -6103,7 +6149,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.3", - "rustls 0.23.43", + "rustls", "socket2 0.6.5", "thiserror 2.0.20", "tokio 1.52.3", @@ -6123,9 +6169,9 @@ dependencies = [ "lru-slab", "rand 0.10.2", "rand_pcg", - "ring 0.17.14", + "ring", "rustc-hash 2.1.3", - "rustls 0.23.43", + "rustls", "rustls-pki-types", "rustls-platform-verifier", "slab", @@ -6315,7 +6361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" dependencies = [ "pem", - "ring 0.17.14", + "ring", "rustls-pki-types", "time", "x509-parser", @@ -6431,8 +6477,8 @@ dependencies = [ "percent-encoding", "pin-project-lite 0.2.17", "quinn", - "rustls 0.23.43", - "rustls-native-certs", + "rustls", + "rustls-native-certs 0.8.4", "rustls-pki-types", "serde", "serde_json", @@ -6477,21 +6523,6 @@ dependencies = [ "hmac 0.13.0", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.14" @@ -6666,18 +6697,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.23.43" @@ -6687,7 +6706,7 @@ dependencies = [ "aws-lc-rs", "log", "once_cell", - "ring 0.17.14", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -6700,30 +6719,34 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c742cb7d8e43daae2dd9ca4b1da442b4500a461ce1c84249e6ac99b4bc12562e" dependencies = [ - "rustls 0.23.43", + "rustls", "sha2 0.10.9", "windows-sys 0.59.0", ] [[package]] name = "rustls-native-certs" -version = "0.8.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", + "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] -name = "rustls-pemfile" -version = "1.0.4" +name = "rustls-native-certs" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ - "base64 0.21.7", + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.7.0", ] [[package]] @@ -6756,11 +6779,11 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.43", - "rustls-native-certs", + "rustls", + "rustls-native-certs 0.8.4", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -6779,7 +6802,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", - "ring 0.17.14", + "ring", "rustls-pki-types", "untrusted 0.9.0", ] @@ -6898,16 +6921,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "seahorse" version = "2.2.0" @@ -6956,6 +6969,19 @@ dependencies = [ "windows 0.61.3", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework" version = "3.7.0" @@ -7301,6 +7327,27 @@ dependencies = [ "serde_core", ] +[[package]] +name = "snafu" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.46", + "syn 1.0.109", +] + [[package]] name = "socket2" version = "0.5.10" @@ -7321,12 +7368,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.9" @@ -7403,7 +7444,7 @@ dependencies = [ "rustcrypto-ff", "rustcrypto-ff_derive", "rustcrypto-group", - "rustls 0.23.43", + "rustls", "serde", "sha1 0.11.0", "sha2 0.11.0", @@ -7686,8 +7727,8 @@ dependencies = [ "rcgen", "reqwest", "rstest", - "rustls 0.23.43", - "rustls-pemfile 2.2.0", + "rustls", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", @@ -7964,7 +8005,19 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.43", + "rustls", + "tokio 1.52.3", +] + +[[package]] +name = "tokio-socks" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7e2948f60dbe26b35f2c7fb74ac2854c1fddded0fe9d7548fcc674a246f7615" +dependencies = [ + "either", + "futures-util", + "thiserror 1.0.69", "tokio 1.52.3", ] @@ -7999,8 +8052,8 @@ dependencies = [ "futures-util", "log", "native-tls", - "rustls 0.23.43", - "rustls-native-certs", + "rustls", + "rustls-native-certs 0.8.4", "rustls-pki-types", "tokio 1.52.3", "tokio-native-tls", @@ -8122,8 +8175,8 @@ dependencies = [ "percent-encoding", "pin-project 1.1.13", "prost 0.13.5", - "rustls-native-certs", - "rustls-pemfile 2.2.0", + "rustls-native-certs 0.8.4", + "rustls-pemfile", "socket2 0.5.10", "tokio 1.52.3", "tokio-rustls", @@ -8542,7 +8595,7 @@ dependencies = [ "log", "native-tls", "rand 0.9.5", - "rustls 0.23.43", + "rustls", "rustls-pki-types", "sha1 0.10.7", "thiserror 2.0.20", @@ -8700,7 +8753,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.43", + "rustls", "rustls-pki-types", "url", "webpki-roots 0.26.11", @@ -8982,16 +9035,6 @@ dependencies = [ "ebml-iterable", ] -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "webpki-root-certs" version = "1.0.8" @@ -9729,7 +9772,7 @@ dependencies = [ "lazy_static", "nom", "oid-registry", - "ring 0.17.14", + "ring", "rusticata-macros", "thiserror 1.0.69", "time", diff --git a/README.md b/README.md index cd2b4a3eb0..7293972afb 100644 --- a/README.md +++ b/README.md @@ -184,8 +184,9 @@ Stable options are: tolerance defined as a number in seconds. * **Metadata** (_String_): Opaque, user-supplied string that will be returned as part of the ngrok API response to the list online sessions resource for all tunnels started by Devolutions Gateway service. - * **ServerAddr** (_URL_): This is the URL of the ngrok server to connect to. You should only set this if you are using a - custom ingress URL. + * **ServerAddr** (_String_): Address of the ngrok agent endpoint to connect to, as `host[:port]` (port 443 if omitted). + Defaults to ngrok's standard agent endpoint, `connect.ngrok-agent.com:443`. + Set it only to use another endpoint, such as a regional or custom agent ingress. * **Tunnels** (_Map_): A map of ngrok tunnels. The key is the name of the tunnel and value is a JSON object whose schema depends on tunnel protocol. diff --git a/config_schema.json b/config_schema.json index 321ff7c69b..b37657175e 100644 --- a/config_schema.json +++ b/config_schema.json @@ -330,7 +330,7 @@ }, "ServerAddr": { "type": "string", - "description": "This is the URL of the ngrok server to connect to. You should only set this if you are using a custom ingress URL." + "description": "Address of the ngrok agent endpoint to connect to, as host[:port] (port 443 if omitted). Defaults to ngrok's standard agent endpoint, connect.ngrok-agent.com:443. Set it only to use another endpoint, such as a regional or custom agent ingress." }, "Tunnels": { "type": "object", diff --git a/devolutions-gateway/Cargo.toml b/devolutions-gateway/Cargo.toml index 112024fd36..3b42877624 100644 --- a/devolutions-gateway/Cargo.toml +++ b/devolutions-gateway/Cargo.toml @@ -97,7 +97,7 @@ http-client-proxy = { path = "../crates/http-client-proxy" } futures = "0.3" async-trait = "0.1" tower = { version = "0.5", features = ["timeout"] } -ngrok = "0.13" +ngrok = { version = "0.19", default-features = false, features = ["ring"] } # HTTP hyper = "1.6" diff --git a/devolutions-gateway/src/ngrok.rs b/devolutions-gateway/src/ngrok.rs index 9adb561a74..94f1ac857c 100644 --- a/devolutions-gateway/src/ngrok.rs +++ b/devolutions-gateway/src/ngrok.rs @@ -5,7 +5,8 @@ use async_trait::async_trait; use devolutions_gateway_task::{ChildTask, ShutdownSignal, Task}; use futures::TryStreamExt as _; use ngrok::config::{HttpTunnelBuilder, TcpTunnelBuilder, TunnelBuilder as _}; -use ngrok::tunnel::UrlTunnel as _; +use ngrok::conn::ConnInfo as _; +use ngrok::tunnel::EndpointInfo as _; use tracing::Instrument as _; use crate::DgwState; @@ -19,22 +20,36 @@ pub struct NgrokSession { impl NgrokSession { pub async fn connect(conf: &NgrokConf) -> anyhow::Result { - let mut builder = ngrok::Session::builder().authtoken(&conf.auth_token); + let mut builder = ngrok::Session::builder(); + + builder.authtoken(&conf.auth_token); if let Some(heartbeat_interval) = conf.heartbeat_interval { - builder = builder.heartbeat_interval(Duration::from_secs(heartbeat_interval)); + builder + .heartbeat_interval(Duration::from_secs(heartbeat_interval)) + .context("invalid Ngrok.HeartbeatInterval")?; } if let Some(heartbeat_tolerance) = conf.heartbeat_tolerance { - builder = builder.heartbeat_tolerance(Duration::from_secs(heartbeat_tolerance)); + builder + .heartbeat_tolerance(Duration::from_secs(heartbeat_tolerance)) + .context("invalid Ngrok.HeartbeatTolerance")?; } if let Some(metadata) = &conf.metadata { - builder = builder.metadata(metadata); + builder.metadata(metadata); } if let Some(server_addr) = &conf.server_addr { - builder = builder.server_addr(server_addr); + // The SDK reads `https://host` as the host `https`, which would only fail later at name resolution. + anyhow::ensure!( + !server_addr.contains("://"), + "invalid Ngrok.ServerAddr {server_addr}, expected host[:port] without a URL scheme" + ); + + builder + .server_addr(server_addr) + .context("invalid Ngrok.ServerAddr, expected host[:port]")?; } info!("Connecting to ngrok service"); @@ -53,32 +68,30 @@ impl NgrokSession { match conf { NgrokTunnelConf::Tcp(tcp_conf) => { - let mut builder = self.inner.tcp_endpoint().remote_addr(&tcp_conf.remote_addr); + let mut builder = self.inner.tcp_endpoint(); + + builder.remote_addr(&tcp_conf.remote_addr); if let Some(metadata) = &tcp_conf.metadata { - builder = builder.metadata(metadata); + builder.metadata(metadata); } let before_cidrs = builder.clone(); - builder = tcp_conf - .allow_cidrs - .iter() - .fold(builder, |builder, cidr| builder.allow_cidr(cidr)); + for cidr in &tcp_conf.allow_cidrs { + builder.allow_cidr(cidr); + } - builder = tcp_conf - .deny_cidrs - .iter() - .fold(builder, |builder, cidr| builder.deny_cidr(cidr)); + for cidr in &tcp_conf.deny_cidrs { + builder.deny_cidr(cidr); + } // HACK: Find the subscription plan. This uses ngrok-rs internal API, so it’s not great. // Ideally, we could use the `Session` to find out about the subscription plan without dirty tricks. - match builder - .clone() - .forwards_to("Devolutions Gateway Subscription probe") - .listen() - .await - { + let mut probe = builder.clone(); + probe.forwards_to("Devolutions Gateway Subscription probe"); + + match probe.listen().await { // https://ngrok.com/docs/errors/err_ngrok_9017/ // "Your account is not authorized to use ip restrictions." Err(ngrok::session::RpcError::Response(e)) @@ -102,44 +115,38 @@ impl NgrokSession { } } NgrokTunnelConf::Http(http_conf) => { - let mut builder = self - .inner - .http_endpoint() - .domain(&http_conf.domain) - .scheme(Scheme::HTTPS); + let mut builder = self.inner.http_endpoint(); + + builder.domain(&http_conf.domain).scheme(Scheme::HTTPS); if let Some(metadata) = &http_conf.metadata { - builder = builder.metadata(metadata); + builder.metadata(metadata); } if let Some(circuit_breaker) = http_conf.circuit_breaker { - builder = builder.circuit_breaker(circuit_breaker); + builder.circuit_breaker(circuit_breaker); } if matches!(http_conf.compression, Some(true)) { - builder = builder.compression(); + builder.compression(); } let before_cidrs = builder.clone(); - builder = http_conf - .allow_cidrs - .iter() - .fold(builder, |builder, cidr| builder.allow_cidr(cidr)); + for cidr in &http_conf.allow_cidrs { + builder.allow_cidr(cidr); + } - builder = http_conf - .deny_cidrs - .iter() - .fold(builder, |builder, cidr| builder.deny_cidr(cidr)); + for cidr in &http_conf.deny_cidrs { + builder.deny_cidr(cidr); + } // HACK: Find the subscription plan. This uses ngrok-rs internal API, so it’s not great. // Ideally, we could use the `Session` to find out about the subscription plan without dirty tricks. - match builder - .clone() - .forwards_to("Devolutions Gateway Subscription probe") - .listen() - .await - { + let mut probe = builder.clone(); + probe.forwards_to("Devolutions Gateway Subscription probe"); + + match probe.listen().await { // https://ngrok.com/docs/errors/err_ngrok_9017/ // "Your account is not authorized to use ip restrictions." Err(ngrok::session::RpcError::Response(e)) @@ -166,7 +173,6 @@ impl NgrokSession { } } -// fn handle_http_tunnel(mut tunnel: impl UrlTunnel, ) -> pub struct NgrokTunnel { name: String, inner: NgrokTunnelInner, @@ -188,7 +194,7 @@ impl NgrokTunnel { let hostname = state.conf_handle.get_conf().hostname.clone(); match self.inner { - NgrokTunnelInner::Tcp(builder) => { + NgrokTunnelInner::Tcp(mut builder) => { // Start tunnel with a TCP edge let tunnel = builder .forwards_to(hostname) @@ -200,7 +206,7 @@ impl NgrokTunnel { run_tcp_tunnel(tunnel, state).await; } - NgrokTunnelInner::Http(builder) => { + NgrokTunnelInner::Http(mut builder) => { // Start tunnel with an HTTP edge let tunnel = builder .forwards_to(hostname)