diff --git a/crates/shadowsocks-service/Cargo.toml b/crates/shadowsocks-service/Cargo.toml index f8ed77fa477b..85320379107d 100644 --- a/crates/shadowsocks-service/Cargo.toml +++ b/crates/shadowsocks-service/Cargo.toml @@ -79,7 +79,7 @@ rand = { version = "0.8", optional = true } futures = "0.3" tokio = { version = "1.0", features = ["full"] } tokio-native-tls = { version = "0.3", optional = true } -native-tls = { version = "0.2", optional = true } +native-tls = { version = "0.2.7", optional = true, features = ["alpn"] } tokio-rustls = { version = "0.22", optional = true } webpki-roots = { version = "0.21", optional = true } rustls-native-certs = { version = "0.5", optional = true } diff --git a/crates/shadowsocks-service/src/local/http/http_stream.rs b/crates/shadowsocks-service/src/local/http/http_stream.rs index dbff241d0ee5..b25ce120d389 100644 --- a/crates/shadowsocks-service/src/local/http/http_stream.rs +++ b/crates/shadowsocks-service/src/local/http/http_stream.rs @@ -30,7 +30,7 @@ impl ProxyHttpStream { pub async fn connect_https(stream: AutoProxyClientStream, domain: &str) -> io::Result { use native_tls::TlsConnector; - let cx = match TlsConnector::builder().build() { + let cx = match TlsConnector::builder().request_alpns(&["h2", "http/1.1"]).build() { Ok(c) => c, Err(err) => { return Err(io::Error::new(ErrorKind::Other, format!("tls build: {}", err))); @@ -40,9 +40,16 @@ impl ProxyHttpStream { match cx.connect(domain, stream).await { Ok(s) => { - // FIXME: There is no API to set ALPN for negociating H2 - // https://github.com/sfackler/rust-native-tls/issues/49 - Ok(ProxyHttpStream::Https(s, false)) + let negociated_h2 = match s.get_ref().negotiated_alpn() { + Ok(Some(alpn)) => alpn == b"h2", + Ok(None) => false, + Err(err) => { + let ierr = io::Error::new(ErrorKind::Other, format!("tls alpn negociate: {}", err)); + return Err(ierr); + } + }; + + Ok(ProxyHttpStream::Https(s, negociated_h2)) } Err(err) => { let ierr = io::Error::new(ErrorKind::Other, format!("tls connect: {}", err));