Skip to content

Commit

Permalink
Merge pull request #140 from ngrok/bob/cert-valid-option
Browse files Browse the repository at this point in the history
disable backend cert verification option
  • Loading branch information
bobzilladev authored Mar 11, 2024
2 parents 12efb0d + 4cd7b94 commit 49a5d16
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 25 deletions.
3 changes: 2 additions & 1 deletion ngrok/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ngrok"
version = "0.14.0-pre.11"
version = "0.14.0-pre.12"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "The ngrok agent SDK"
Expand Down Expand Up @@ -43,6 +43,7 @@ url = "2.4.0"
rustls-native-certs = "0.7.0"
proxy-protocol = "0.5.0"
pin-project = "1.1.3"
bitflags = "2.4.2"

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.45.0", features = ["Win32_Foundation"] }
Expand Down
1 change: 1 addition & 0 deletions ngrok/examples/axum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ async fn start_tunnel() -> anyhow::Result<HttpTunnel> {
// .circuit_breaker(0.5)
// .compression()
// .deny_cidr("10.1.1.1/32")
// .verify_upstream_tls(false)
// .domain("<somedomain>.ngrok.io")
// .forwards_to("example rust")
// .mutual_tlsca(CA_CERT.into())
Expand Down
1 change: 1 addition & 0 deletions ngrok/examples/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async fn main() -> anyhow::Result<()> {
.tcp_endpoint()
// .allow_cidr("0.0.0.0/0")
// .deny_cidr("10.1.1.1/32")
// .verify_upstream_tls(false)
// .forwards_to("example rust"),
// .proxy_proto(ProxyProto::None)
// .remote_addr("<n>.tcp.ngrok.io:<p>")
Expand Down
3 changes: 2 additions & 1 deletion ngrok/examples/labeled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ async fn start_tunnel() -> anyhow::Result<LabeledTunnel> {

let tun = sess
.labeled_tunnel()
//.app_protocol("http2")
// .app_protocol("http2")
// .verify_upstream_tls(false)
.label("edge", "edghts_<edge_id>")
.metadata("example tunnel metadata from rust")
.listen()
Expand Down
1 change: 1 addition & 0 deletions ngrok/examples/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async fn start_tunnel() -> anyhow::Result<TlsTunnel> {
.tls_endpoint()
// .allow_cidr("0.0.0.0/0")
// .deny_cidr("10.1.1.1/32")
// .verify_upstream_tls(false)
// .domain("<somedomain>.ngrok.io")
// .forwards_to("example rust"),
// .mutual_tlsca(CA_CERT.into())
Expand Down
15 changes: 15 additions & 0 deletions ngrok/src/config/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ pub(crate) trait TunnelConfig {
fn forwards_to(&self) -> String;
/// The L7 protocol the upstream service expects
fn forwards_proto(&self) -> String;
/// Whether to disable certificate verification for this tunnel.
fn verify_upstream_tls(&self) -> bool;
/// Internal-only, extra data sent when binding a tunnel.
fn extra(&self) -> BindExtra;
/// The protocol for this tunnel.
Expand All @@ -152,6 +154,9 @@ where
fn forwards_proto(&self) -> String {
(**self).forwards_proto()
}
fn verify_upstream_tls(&self) -> bool {
(**self).verify_upstream_tls()
}
fn extra(&self) -> BindExtra {
(**self).extra()
}
Expand Down Expand Up @@ -199,6 +204,8 @@ pub(crate) struct CommonOpts {
pub(crate) forwards_to: Option<String>,
// Tunnel L7 app protocol
pub(crate) forwards_proto: Option<String>,
// Whether to disable certificate verification for this tunnel.
verify_upstream_tls: Option<bool>,
// Policy that defines rules that should be applied to incoming or outgoing
// connections to the edge.
pub(crate) policy: Option<Policy>,
Expand All @@ -215,6 +222,14 @@ impl CommonOpts {
self.forwards_to = Some(to_url.as_str().into());
self
}

pub(crate) fn set_verify_upstream_tls(&mut self, verify_upstream_tls: bool) {
self.verify_upstream_tls = Some(verify_upstream_tls)
}

pub(crate) fn verify_upstream_tls(&self) -> bool {
self.verify_upstream_tls.unwrap_or(true)
}
}

// transform into the wire protocol format
Expand Down
12 changes: 12 additions & 0 deletions ngrok/src/config/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ impl TunnelConfig for HttpOptions {
self.common_opts.forwards_proto.clone().unwrap_or_default()
}

fn verify_upstream_tls(&self) -> bool {
self.common_opts.verify_upstream_tls()
}

fn extra(&self) -> BindExtra {
BindExtra {
token: Default::default(),
Expand Down Expand Up @@ -266,6 +270,14 @@ impl HttpTunnelBuilder {
self
}

/// Disables backend TLS certificate verification for forwards from this tunnel.
pub fn verify_upstream_tls(&mut self, verify_upstream_tls: bool) -> &mut Self {
self.options
.common_opts
.set_verify_upstream_tls(verify_upstream_tls);
self
}

/// Sets the scheme for this edge.
pub fn scheme(&mut self, scheme: Scheme) -> &mut Self {
self.options.scheme = scheme;
Expand Down
12 changes: 12 additions & 0 deletions ngrok/src/config/labeled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ impl TunnelConfig for LabeledOptions {
self.common_opts.forwards_proto.clone().unwrap_or_default()
}

fn verify_upstream_tls(&self) -> bool {
self.common_opts.verify_upstream_tls()
}

fn extra(&self) -> BindExtra {
BindExtra {
token: Default::default(),
Expand Down Expand Up @@ -101,6 +105,14 @@ impl LabeledTunnelBuilder {
self
}

/// Disables backend TLS certificate verification for forwards from this tunnel.
pub fn verify_upstream_tls(&mut self, verify_upstream_tls: bool) -> &mut Self {
self.options
.common_opts
.set_verify_upstream_tls(verify_upstream_tls);
self
}

pub(crate) async fn for_forwarding_to(&mut self, to_url: &Url) -> &mut Self {
self.options.common_opts.for_forwarding_to(to_url);
self
Expand Down
13 changes: 13 additions & 0 deletions ngrok/src/config/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ impl TunnelConfig for TcpOptions {
String::new()
}

fn verify_upstream_tls(&self) -> bool {
self.common_opts.verify_upstream_tls()
}

fn opts(&self) -> Option<BindOpts> {
// fill out all the options, translating to proto here
let mut tcp_endpoint = proto::TcpEndpoint::default();
Expand Down Expand Up @@ -124,6 +128,15 @@ impl TcpTunnelBuilder {
self.options.common_opts.forwards_to = Some(forwards_to.into());
self
}

/// Disables backend TLS certificate verification for forwards from this tunnel.
pub fn verify_upstream_tls(&mut self, verify_upstream_tls: bool) -> &mut Self {
self.options
.common_opts
.set_verify_upstream_tls(verify_upstream_tls);
self
}

/// Sets the TCP address to request for this edge.
///
/// https://ngrok.com/docs/network-edge/domains-and-tcp-addresses/#tcp-addresses
Expand Down
13 changes: 13 additions & 0 deletions ngrok/src/config/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ impl TunnelConfig for TlsOptions {
String::new()
}

fn verify_upstream_tls(&self) -> bool {
self.common_opts.verify_upstream_tls()
}

fn extra(&self) -> BindExtra {
BindExtra {
token: Default::default(),
Expand Down Expand Up @@ -143,6 +147,15 @@ impl TlsTunnelBuilder {
self.options.common_opts.forwards_to = Some(forwards_to.into());
self
}

/// Disables backend TLS certificate verification for forwards from this tunnel.
pub fn verify_upstream_tls(&mut self, verify_upstream_tls: bool) -> &mut Self {
self.options
.common_opts
.set_verify_upstream_tls(verify_upstream_tls);
self
}

/// Sets the domain to request for this edge.
///
/// https://ngrok.com/docs/network-edge/domains-and-tcp-addresses/#domains
Expand Down
1 change: 1 addition & 0 deletions ngrok/src/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub(crate) struct Info {
pub(crate) remote_addr: SocketAddr,
pub(crate) proxy_proto: ProxyProto,
pub(crate) app_protocol: Option<String>,
pub(crate) verify_upstream_tls: bool,
}

impl ConnInfo for Info {
Expand Down
43 changes: 43 additions & 0 deletions ngrok/src/online_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use futures_rustls::rustls::{
ClientConfig,
RootCertStore,
};
// use native_tls;
use hyper::{
header,
HeaderMap,
Expand Down Expand Up @@ -688,6 +689,48 @@ async fn tls() -> Result<(), Error> {
Ok(())
}

#[test]
#[cfg_attr(not(feature = "authenticated-tests"), ignore)]
async fn app_protocol() -> Result<(), Error> {
let tun = Session::builder()
.authtoken_from_env()
.connect()
.await?
.http_endpoint()
.app_protocol("http2")
.listen_and_forward("https://ngrok.com".parse()?)
.await?;

// smoke test
let client = reqwest::Client::new();
let resp = client.get(tun.url()).send().await;

assert!(resp.is_ok());

Ok(())
}

#[test]
#[cfg_attr(not(feature = "authenticated-tests"), ignore)]
async fn verify_upstream_tls() -> Result<(), Error> {
let tun = Session::builder()
.authtoken_from_env()
.connect()
.await?
.http_endpoint()
.verify_upstream_tls(false)
.listen_and_forward("https://ngrok.com".parse()?)
.await?;

// smoke test
let client = reqwest::Client::new();
let resp = client.get(tun.url()).send().await;

assert!(resp.is_ok());

Ok(())
}

#[cfg_attr(not(feature = "online-tests"), ignore)]
#[test]
async fn session_ca_cert() -> Result<(), Error> {
Expand Down
6 changes: 6 additions & 0 deletions ngrok/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ struct BoundTunnel {
labels: HashMap<String, String>,
forwards_to: String,
forwards_proto: String,
verify_upstream_tls: bool,
tx: Sender<Result<ConnInner, AcceptError>>,
}

Expand Down Expand Up @@ -887,6 +888,7 @@ impl Session {
let labels = tunnel_cfg.labels();
let forwards_to = tunnel_cfg.forwards_to();
let forwards_proto = tunnel_cfg.forwards_proto();
let verify_upstream_tls = tunnel_cfg.verify_upstream_tls();

// non-labeled tunnel
let (tunnel, bound) = if tunnel_cfg.proto() != "" {
Expand Down Expand Up @@ -924,6 +926,7 @@ impl Session {
labels,
forwards_to,
forwards_proto,
verify_upstream_tls,
tx,
},
)
Expand Down Expand Up @@ -959,6 +962,7 @@ impl Session {
opts: Default::default(),
forwards_to,
forwards_proto,
verify_upstream_tls,
labels,
tx,
},
Expand Down Expand Up @@ -1034,6 +1038,7 @@ async fn accept_one(
let res = if let Some(tun) = guard.get(&id) {
let mut header = conn.header;
let app_protocol = Some(tun.forwards_proto.to_string()).filter(|s| !s.is_empty());
let verify_upstream_tls = tun.verify_upstream_tls;
// Note: this is a bit of a hack. Normally, passthrough_tls is only
// a thing on edge connections, but we're making sure it's set for
// endpoint connections as well. In their case, we have to look at the
Expand All @@ -1055,6 +1060,7 @@ async fn accept_one(
.send(Ok(ConnInner {
info: crate::conn::Info {
app_protocol,
verify_upstream_tls,
remote_addr,
header,
proxy_proto,
Expand Down
Loading

0 comments on commit 49a5d16

Please sign in to comment.