Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use rcgen rather than a public cert in tests/examples #187

Merged
merged 7 commits into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,39 @@ Quinn was created and is maintained by Dirkjan Ochtman and Benjamin Saunders.
- [x] Session resumption
- [ ] HTTP over QUIC

## How to start

The server [currently always requires][insecure] certificates to be supplied.
Example certificates are included in the repository for test purposes.
The client must be configured to trust the test certificate authority unless the
client is built with the `dangerous_configuration` feature and passed
`--accept-insecure-certs`.
## Certificates

By default, Quinn clients validate the cryptographic identity of servers they
connect to. This prevents an active, on-path attacker from intercepting
messages, but requires trusting some certificate authority. For many purposes,
this can be accomplished by using certificates from [Let's Encrypt][letsencrypt]
for servers, and invoking
`ClientConfigBuilder::add_default_certificate_authorities` on clients.

For some cases, including peer-to-peer, trust-on-first-use, deliberately
insecure applications, or any case where servers are not identified by domain
name, this isn't practical. Arbitrary certificate validation logic can be
implemented by enabling the `dangerous_configuration` feature of `rustls` and
constructing a quinn `ClientConfig` with an overridden certificate verifier by
hand.

When operating your own certificate authority doesn't make sense, [rcgen][rcgen]
can be used to generate self-signed certificates on demand. To support
trust-on-first-use, servers that automatically generate self-signed certificates
should write their generated certificate to persistent storage and reuse it on
future runs.

## Running the Examples

```sh
$ cargo run --example server -- --cert ./certs/server.chain --key ./certs/server.rsa ./
$ cargo run --example client -- --ca ./certs/ca.der https://localhost:4433/Cargo.toml
$ cargo run --example server ./
$ cargo run --example client https://localhost:4433/Cargo.toml
```

In the above example, the server will run on localhost and serve the "." folder to
the client. The client will request the "Cargo.toml" file.

To run the example client/server across a network you need to update the
`certs/openssl.cnf` file and change the `DNS.3` entry to suit the DNS name of the
server, and then regenerate the certificates using the `certs/generate.sh` script.
For real-world use, a certificate signed by a legitimate CA is recommended when
possible.
This launches a HTTP 0.9 server on the loopback address serving the current
working directory, with the client fetching `./Cargo.toml`. By default, the
server generates a self-signed certificate and stores it to disk, where the
client will automatically find and trust it.

## Development

Expand All @@ -83,4 +95,5 @@ the variable.
[slides]: https://dirkjan.ochtman.nl/files/quic-future-in-rust.pdf
[animation]: https://dirkjan.ochtman.nl/files/head-of-line-blocking.html
[youtube]: https://www.youtube.com/watch?v=EHgyY5DNdvI
[insecure]: https://github.com/djc/quinn/issues/58
[letsencrypt]: https://letsencrypt.org/
[rcgen]: https://crates.io/crates/rcgen
Binary file removed certs/ca.der
Binary file not shown.
35 changes: 0 additions & 35 deletions certs/generate.sh

This file was deleted.

17 changes: 0 additions & 17 deletions certs/openssl.cnf

This file was deleted.

86 changes: 0 additions & 86 deletions certs/server.chain

This file was deleted.

27 changes: 0 additions & 27 deletions certs/server.rsa

This file was deleted.

4 changes: 1 addition & 3 deletions quinn-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ dangerous_configuration = ["rustls/dangerous_configuration"]
[dependencies]
byteorder = "1.1"
bytes = "0.4.7"
constant_time_eq = "0.1"
failure = "0.1"
fnv = "1.0.6"
lazy_static = "1"
Expand All @@ -39,6 +38,5 @@ block-modes = "0.3"
[dev-dependencies]
assert_matches = "1.1"
hex-literal = "0.1.1"
slog-term = "2"
untrusted = "0.6.2"
webpki-roots = "0.15"
rcgen = "0.1"
33 changes: 12 additions & 21 deletions quinn-proto/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use std::collections::VecDeque;
use std::io::{self, Read, Write};
use std::io::{self, Write};
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket};
use std::ops::RangeFrom;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{env, fmt, fs, mem, str};
use std::{env, fmt, mem, str};

use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes;
use rand::RngCore;
use ring::digest;
use ring::hmac::SigningKey;
use rustls::internal::msgs::enums::AlertDescription;
use rustls::{internal::pemfile, KeyLogFile, ProtocolVersion};
use rustls::{KeyLogFile, ProtocolVersion};
use slog::{Drain, Logger, KV};
use untrusted::Input;

Expand Down Expand Up @@ -57,6 +57,8 @@ fn logger() -> Logger {
lazy_static! {
static ref SERVER_PORTS: Mutex<RangeFrom<u16>> = Mutex::new(4433..);
static ref CLIENT_PORTS: Mutex<RangeFrom<u16>> = Mutex::new(44433..);
static ref CERTIFICATE: rcgen::Certificate =
rcgen::generate_simple_self_signed(vec!["localhost".into()]);
}

struct Pair {
Expand All @@ -78,34 +80,23 @@ impl Default for Pair {
}

fn server_config() -> ServerConfig {
let certs = {
let f =
fs::File::open("../certs/server.chain").expect("cannot open '../certs/server.chain'");
let mut reader = io::BufReader::new(f);
pemfile::certs(&mut reader).expect("cannot read certificates")
};

let keys = {
let f = fs::File::open("../certs/server.rsa").expect("cannot open '../certs/server.rsa'");
let mut reader = io::BufReader::new(f);
pemfile::rsa_private_keys(&mut reader).expect("cannot read private keys")
};
let key = CERTIFICATE.serialize_private_key_der();
let cert = CERTIFICATE.serialize_der();

let mut tls_config = crypto::build_server_config();
tls_config.set_protocols(&[str::from_utf8(ALPN_QUIC_HTTP).unwrap().into()]);
tls_config.set_single_cert(certs, keys[0].clone()).unwrap();
tls_config
.set_single_cert(vec![rustls::Certificate(cert)], rustls::PrivateKey(key))
.unwrap();
ServerConfig {
tls_config: Arc::new(tls_config),
..Default::default()
}
}

fn client_config() -> Arc<ClientConfig> {
let mut f = fs::File::open("../certs/ca.der").expect("cannot open '../certs/ca.der'");
let mut bytes = Vec::new();
f.read_to_end(&mut bytes).expect("error while reading");

let anchor = webpki::trust_anchor_util::cert_der_as_trust_anchor(Input::from(&bytes)).unwrap();
let cert = CERTIFICATE.serialize_der();
let anchor = webpki::trust_anchor_util::cert_der_as_trust_anchor(Input::from(&cert)).unwrap();
let anchor_vec = vec![anchor];

let mut tls_client_config = ClientConfig::new();
Expand Down
7 changes: 3 additions & 4 deletions quinn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ codecov = { repository = "djc/quinn" }
maintenance = { status = "experimental" }
travis-ci = { repository = "djc/quinn" }

[features]
dangerous_configuration = ["quinn-proto/dangerous_configuration"]

[dependencies]
bytes = "0.4.7"
failure = "0.1"
Expand All @@ -38,6 +35,7 @@ tokio-timer = "0.2.1"
untrusted = "0.6.2"
webpki = "0.18"
webpki-roots = "0.15"
ct-logs = "0.4.0"
libc = "0.2.46"
mio = "0.6"

Expand All @@ -47,13 +45,14 @@ structopt = "0.2.7"
tokio = "0.1.6"
tokio-current-thread = "0.1"
url = "1.7"
rcgen = "0.1"
directories = "1.0.2"

[[example]]
name = "server"

[[example]]
name = "interop"
required-features = ["dangerous_configuration"]

[[example]]
name = "client"
Loading