summaryrefslogtreecommitdiff
path: root/ext/fetch/proxy.rs
diff options
context:
space:
mode:
authorSean McArthur <sean@seanmonstar.com>2024-07-24 13:20:06 -0700
committerGitHub <noreply@github.com>2024-07-24 20:20:06 +0000
commitc7f468d33b5d0814b56036639eb2a8226d4bfbbf (patch)
tree7464522c9574c57d2c3e9c4902278864631d83f1 /ext/fetch/proxy.rs
parentb305ba3e1c155a33139ec0d764f547ffde4d4de4 (diff)
fix(ext/fetch): use correct ALPN to proxies (#24696)
Sending ALPN to a proxy, and then when tunneling, requires better juggling of TLS configs. This improves the choice of TLS config in the proxy connector, based on what reqwest does. It also includes some `ext/fetch/tests.rs` that check the different combinations. Fixes #24632 Fixes #24691
Diffstat (limited to 'ext/fetch/proxy.rs')
-rw-r--r--ext/fetch/proxy.rs61
1 files changed, 31 insertions, 30 deletions
diff --git a/ext/fetch/proxy.rs b/ext/fetch/proxy.rs
index db187c3f6..c8e54d5ec 100644
--- a/ext/fetch/proxy.rs
+++ b/ext/fetch/proxy.rs
@@ -17,6 +17,8 @@ use deno_tls::rustls::ClientConfig as TlsConfig;
use http::header::HeaderValue;
use http::uri::Scheme;
use http::Uri;
+use hyper_rustls::HttpsConnector;
+use hyper_rustls::MaybeHttpsStream;
use hyper_util::client::legacy::connect::Connected;
use hyper_util::client::legacy::connect::Connection;
use hyper_util::rt::TokioIo;
@@ -29,10 +31,14 @@ use tower_service::Service;
#[derive(Debug, Clone)]
pub(crate) struct ProxyConnector<C> {
- connector: C,
- proxies: Arc<Proxies>,
- tls: Arc<TlsConfig>,
- user_agent: Option<HeaderValue>,
+ pub(crate) http: C,
+ pub(crate) proxies: Arc<Proxies>,
+ /// TLS config when destination is not a proxy
+ pub(crate) tls: Arc<TlsConfig>,
+ /// TLS config when destination is a proxy
+ /// Notably, does not include ALPN
+ pub(crate) tls_proxy: Arc<TlsConfig>,
+ pub(crate) user_agent: Option<HeaderValue>,
}
#[derive(Debug)]
@@ -361,23 +367,6 @@ impl DomainMatcher {
}
impl<C> ProxyConnector<C> {
- pub(crate) fn new(
- proxies: Arc<Proxies>,
- connector: C,
- tls: Arc<TlsConfig>,
- ) -> Self {
- ProxyConnector {
- connector,
- proxies,
- tls,
- user_agent: None,
- }
- }
-
- pub(crate) fn user_agent(&mut self, val: HeaderValue) {
- self.user_agent = Some(val);
- }
-
fn intercept(&self, dst: &Uri) -> Option<&Intercept> {
self.proxies.intercept(dst)
}
@@ -438,12 +427,13 @@ pub enum Proxied<T> {
impl<C> Service<Uri> for ProxyConnector<C>
where
- C: Service<Uri>,
- C::Response: hyper::rt::Read + hyper::rt::Write + Unpin + Send + 'static,
+ C: Service<Uri> + Clone,
+ C::Response:
+ hyper::rt::Read + hyper::rt::Write + Connection + Unpin + Send + 'static,
C::Future: Send + 'static,
C::Error: Into<BoxError> + 'static,
{
- type Response = Proxied<C::Response>;
+ type Response = Proxied<MaybeHttpsStream<C::Response>>;
type Error = BoxError;
type Future = BoxFuture<Result<Self::Response, Self::Error>>;
@@ -451,7 +441,7 @@ where
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<(), Self::Error>> {
- self.connector.poll_ready(cx).map_err(Into::into)
+ self.http.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, orig_dst: Uri) -> Self::Future {
@@ -467,10 +457,12 @@ where
dst: proxy_dst,
auth,
} => {
- let connecting = self.connector.call(proxy_dst);
+ let mut connector =
+ HttpsConnector::from((self.http.clone(), self.tls_proxy.clone()));
+ let connecting = connector.call(proxy_dst);
let tls = TlsConnector::from(self.tls.clone());
Box::pin(async move {
- let mut io = connecting.await.map_err(Into::into)?;
+ let mut io = connecting.await.map_err(Into::<BoxError>::into)?;
if is_https {
tunnel(&mut io, &orig_dst, user_agent, auth).await?;
@@ -529,9 +521,11 @@ where
}
};
}
+
+ let mut connector =
+ HttpsConnector::from((self.http.clone(), self.tls.clone()));
Box::pin(
- self
- .connector
+ connector
.call(orig_dst)
.map_ok(Proxied::PassThrough)
.map_err(Into::into),
@@ -721,7 +715,14 @@ where
match self {
Proxied::PassThrough(ref p) => p.connected(),
Proxied::HttpForward(ref p) => p.connected().proxy(true),
- Proxied::HttpTunneled(ref p) => p.inner().get_ref().0.connected(),
+ Proxied::HttpTunneled(ref p) => {
+ let tunneled_tls = p.inner().get_ref();
+ if tunneled_tls.1.alpn_protocol() == Some(b"h2") {
+ tunneled_tls.0.connected().negotiated_h2()
+ } else {
+ tunneled_tls.0.connected()
+ }
+ }
Proxied::Socks(ref p) => p.connected(),
Proxied::SocksTls(ref p) => p.inner().get_ref().0.connected(),
}