Skip to content

Commit

Permalink
Merge pull request #8 from tmccombs/tls-native
Browse files Browse the repository at this point in the history
Tls native
  • Loading branch information
tmccombs authored Feb 24, 2022
2 parents 481186c + e50fd3d commit 50a5682
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 73 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
strategy:
matrix:
rust: [stable, beta, nightly]
tls: [rustls, native-tls]
features:
- hyper-h1,hyper-h2
continue-on-error: ${{ matrix.rust == 'nightly' }}
Expand All @@ -25,10 +26,10 @@ jobs:
profile: minimal
components: rustfmt, clippy
- name: Build
run: cargo build --verbose --examples --features ${{ matrix.features }}
run: cargo build --verbose --examples --features ${{ matrix.tls }},${{ matrix.features }}
- name: Test
run: cargo test --verbose
run: cargo test --verbose --features ${{ matrix.tls }},${{ matrix.features }}
- name: Lint
run: cargo clippy --examples --features ${{ matrix.features }}
run: cargo clippy --examples --features ${{ matrix.tls }},${{ matrix.features }}
- name: Format check
run: cargo fmt -- --check
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
**/*.rs.bk
Cargo.lock
.idea/
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Changelog

## 0.4.0 - 2022-02-22

NOTE: This release contains several breaking changes.

### Added

- Support for [`native-tls`](https://github.com/sfackler/rust-native-tls).

### Changed

- The TLS backend is now configurable. Both rustls and native-tls are supported. Other backends can also be used by implementing the `AsyncTls` trait.
- You must now supply either the `rustls` or `native-tls` features to get support for a tls backend.
- Unfortunately, the machinery for this required adding an additional type parameter to `TlsListener`.
- The `TlsListener` stream now returns a `tls_listener::Error` instead of `std::io::Error` type.
- Signatures of `TcpListener::new()` and `builder()` have changed to now take an argument of the TLS type rather than a `rustls::ServerConfig`,
to update existing calls, replace `builder(config)` with `builder(Arc::new(config).into())`.

### Fixed

- Crate will now compile when linked against a target that doesn't explicitly enable the `tokio/time` and `hyper/tcp`
features.
21 changes: 10 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
[package]
name = "tls-listener"
description = "wrap incoming Stream of connections in TLS"
version = "0.3.0"
version = "0.4.0"
authors = ["Thayne McCombs <[email protected]>"]
repository = "https://github.com/tmccombs/tls-listener"
edition = "2018"
license = "Apache-2.0"

[features]
default = ["tokio-net"]
rustls = ["tokio-rustls"]
native-tls = ["tokio-native-tls"]

tokio-net = ["tokio/net"]
hyper-h1 = ["hyper", "hyper/http1"]
hyper-h2 = ["hyper", "hyper/http2"]

[dependencies]
futures-util = "0.3.8"
tokio = "1.0"
tokio-rustls = "0.23.0"
hyper = { version = "0.14.1", features = ["server", "tcp"], optional = true }
pin-project-lite = "0.2.8"
#tokio-native-tls = "0.3.0"

[dependencies.hyper]
version = "0.14.1"
features = ["server"]
optional = true
thiserror = "1.0.30"
tokio = { version = "1.0", features = ["time"] }
tokio-native-tls = { version = "0.3.0", optional = true }
tokio-rustls = { version = "0.23.0", optional = true }

[dev-dependencies]
hyper = { version = "0.14.1", features = ["server", "http1", "tcp", "stream"] }
hyper = { version = "0.14.1", features = ["http1", "stream"] }
tokio = { version = "1.0", features = ["rt", "macros", "net", "io-util"] }

[[example]]
Expand All @@ -51,5 +50,5 @@ path = "examples/http-low-level.rs"
required-features = ["hyper-h1"]

[package.metadata.docs.rs]
all-features = true
features = ["rustls", "native-tls", "hyper-h1", "hyper-h2"]
rustdoc-args = ["--cfg", "docsrs"]
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ This library is intended to automatically initiate a TLS connection
as for each new connection in a source of new streams (such as a listening
TCP or unix domain socket).

In particular, the `TlsListener` can be used as the `incoming` argument to `hyper::server::Server::builder`.
In particular, the `TlsListener` can be used as the `incoming` argument to `hyper::server::Server::builder` (requires
one of the `hyper-h1` or `hyper-h2` features).

See examples for examples of usage.

You must enable either one of the `rustls` or `native-tls` features depending on which implementation you would
like to use.
9 changes: 7 additions & 2 deletions examples/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ use std::net::SocketAddr;
use tls_listener::TlsListener;
use tokio::io::{copy, split};
use tokio::net::{TcpListener, TcpStream};
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
use tokio_native_tls::TlsStream;
#[cfg(feature = "rustls")]
use tokio_rustls::server::TlsStream;

mod tls_config;
use tls_config::tls_config;
use tls_config::tls_acceptor;

#[inline]
async fn handle_stream(stream: TlsStream<TcpStream>) {
Expand All @@ -17,13 +20,15 @@ async fn handle_stream(stream: TlsStream<TcpStream>) {
};
}

/// For example try opening and closing a connection with:
/// `echo "Q" | openssl s_client -connect host:port`
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();

let listener = TcpListener::bind(&addr).await?;

TlsListener::new(tls_config(), listener)
TlsListener::new(tls_acceptor(), listener)
.for_each_concurrent(None, |s| async {
match s {
Ok(stream) => {
Expand Down
4 changes: 2 additions & 2 deletions examples/http-low-level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use hyper::{Body, Response};
use std::convert::Infallible;

mod tls_config;
use tls_config::tls_config;
use tls_config::tls_acceptor;

#[tokio::main(flavor = "current_thread")]
async fn main() {
let addr = ([127, 0, 0, 1], 3000).into();
let listener = tls_listener::builder(tls_config())
let listener = tls_listener::builder(tls_acceptor())
.max_handshakes(10)
.listen(AddrIncoming::bind(&addr).unwrap());

Expand Down
4 changes: 2 additions & 2 deletions examples/http-stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::future::ready;
use tls_listener::TlsListener;

mod tls_config;
use tls_config::tls_config;
use tls_config::tls_acceptor;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -22,7 +22,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
});

// This uses a filter to handle errors with connecting
let incoming = TlsListener::new(tls_config(), AddrIncoming::bind(&addr)?).filter(|conn| {
let incoming = TlsListener::new(tls_acceptor(), AddrIncoming::bind(&addr)?).filter(|conn| {
if let Err(err) = conn {
eprintln!("Error: {:?}", err);
ready(false)
Expand Down
4 changes: 2 additions & 2 deletions examples/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::convert::Infallible;
use tls_listener::TlsListener;

mod tls_config;
use tls_config::tls_config;
use tls_config::tls_acceptor;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -21,7 +21,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// This could be handled by adding a filter to the stream to filter out
// unwanted errors (and possibly log them), then use `hyper::server::accept::from_stream`,
// or by doing something similar to the http-low-level.rs example.
let incoming = TlsListener::new(tls_config(), AddrIncoming::bind(&addr)?);
let incoming = TlsListener::new(tls_acceptor(), AddrIncoming::bind(&addr)?);

let server = Server::builder(incoming).serve(new_svc);
server.await?;
Expand Down
Binary file added examples/tls_config/local.pfx
Binary file not shown.
40 changes: 29 additions & 11 deletions examples/tls_config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
use tokio_rustls::rustls::{Certificate, PrivateKey, ServerConfig};
#[cfg(feature = "rustls")]
mod cert {
pub const CERT: &[u8] = include_bytes!("local.cert");
pub const PKEY: &[u8] = include_bytes!("local.key");
}
#[cfg(feature = "native-tls")]
const PFX: &[u8] = include_bytes!("local.pfx");

#[cfg(feature = "rustls")]
pub fn tls_acceptor() -> tokio_rustls::TlsAcceptor {
use std::sync::Arc;
use tokio_rustls::rustls::{Certificate, PrivateKey, ServerConfig};

const CERT: &[u8] = include_bytes!("local.cert");
const PKEY: &[u8] = include_bytes!("local.key");
let key = PrivateKey(cert::PKEY.into());
let cert = Certificate(cert::CERT.into());

Arc::new(
ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(vec![cert], key)
.unwrap(),
)
.into()
}

pub fn tls_config() -> ServerConfig {
let key = PrivateKey(PKEY.into());
let cert = Certificate(CERT.into());
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
pub fn tls_acceptor() -> tokio_native_tls::TlsAcceptor {
use tokio_native_tls::native_tls::{Identity, TlsAcceptor};

ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(vec![cert], key)
.unwrap()
let identity = Identity::from_pkcs12(PFX, "").unwrap();
TlsAcceptor::builder(identity).build().unwrap().into()
}
Loading

0 comments on commit 50a5682

Please sign in to comment.