summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--readme.md15
-rw-r--r--src/config.rs4
-rw-r--r--src/main.rs69
3 files changed, 53 insertions, 35 deletions
diff --git a/readme.md b/readme.md
index e6e7c1c..5d6fe8d 100644
--- a/readme.md
+++ b/readme.md
@@ -19,6 +19,11 @@ a simple stupid reverse proxy
- [Matrix Room](https://matrix.to/#/#gnix:metamuffin.org) for questions,
announcements and general discussion around the software.
+## Installation
+
+On arch use `gnix` from the AUR; Otherwise install `rustup`, then run
+`cargo install --git https://codeberg.org/metamuffin/gnix --tag v2.x.x`.
+
## Quick Start
Run the binary with the a path to the configuration as the first argument. The
@@ -49,7 +54,7 @@ handler: !hosts # !hosts routes requests for different hostnames.
next: !proxy { backend: "otherserver:80" }
```
-## Reference
+## Configuration Reference
The configuration uses YAML formatting. When the configuration file is changed,
it will automatically be loaded and applied if valid. Configuration errors are
@@ -71,6 +76,10 @@ reported in stderr and are only fatal at startup.
is used when no other certificate seems appropriate. This is useful for
testing locally with a self-signed subjectless certificate. (optional
string)
+ - `disable_h1` Stops advertising HTTP/1.1 support but still continues to
+ support it. Default: false
+ - `disable_h2` Stops advertising HTTP/2 support. Default: false
+ - `disable_h3` Disables HTTP/3 support. Default: false
- **section `limits`**
- Note: Make sure you do not exceed the maximum file descriptor limit on your
@@ -269,8 +278,8 @@ that contains that map in YALM format. Currently only `argon2id` is supported.
### Additional Notes
-Internally gnix processes requests as they would be sent in HTTP/1.1. HTTP/2 is
-translated on arrival.
+Internally gnix processes requests as they would be sent in HTTP/1.1. HTTP/2 and
+HTTP/3 is translated on arrival.
Paths matching `/_gnix*` might be used internally in gnix for purposes like
OpenID callback or login action endpoints. I hope your application doesn't rely
diff --git a/src/config.rs b/src/config.rs
index 25b8a12..8a19a53 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -65,6 +65,10 @@ pub struct HttpsConfig {
pub cert_fallback: Option<PathBuf>,
#[serde(default)]
pub disable_h3: bool,
+ #[serde(default)]
+ pub disable_h2: bool,
+ #[serde(default)]
+ pub disable_h1: bool,
}
// try deser Vec<T> but fall back to deser T and putting that in Vec
diff --git a/src/main.rs b/src/main.rs
index 3d4e764..b39eea7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -169,7 +169,12 @@ async fn serve_https(state: Arc<State>) -> Result<()> {
let mut cfg = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_cert_resolver(Arc::new(certs));
- cfg.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
+ if !https_config.disable_h1 {
+ cfg.alpn_protocols.push(b"http/1.1".to_vec());
+ }
+ if !https_config.disable_h2 {
+ cfg.alpn_protocols.push(b"h2".to_vec());
+ }
Arc::new(cfg)
};
let tls_acceptor = Arc::new(TlsAcceptor::from(tls_config));
@@ -200,6 +205,37 @@ async fn serve_https(state: Arc<State>) -> Result<()> {
Ok(())
}
+pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::rt::Write>(
+ state: Arc<State>,
+ stream: T,
+ addr: SocketAddr,
+ secure: bool,
+ listen_addr: SocketAddr,
+) {
+ if let Ok(_semaphore) = state.l_incoming.try_acquire() {
+ let builder = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new());
+ let conn = builder.serve_connection_with_upgrades(
+ stream,
+ service_fn(|req| {
+ let state = state.clone();
+ async move {
+ let req = req.map(|body: Incoming| body.map_err(ServiceError::Hyper).boxed());
+ match service(state, req, addr, secure, listen_addr).await {
+ Ok(r) => Ok(r),
+ Err(ServiceError::Hyper(e)) => Err(e),
+ Err(error) => Ok(error_response(addr, error)),
+ }
+ }
+ }),
+ );
+ if let Err(err) = conn.await {
+ warn!("error: {:?}", err);
+ }
+ } else {
+ warn!("connection dropped: too many incoming");
+ }
+}
+
async fn serve_h3(state: Arc<State>) -> Result<()> {
let config = state.config.read().await.clone();
let https_config = match &config.https {
@@ -310,37 +346,6 @@ async fn serve_h3(state: Arc<State>) -> Result<()> {
Ok(())
}
-pub async fn serve_stream<T: Unpin + Send + 'static + hyper::rt::Read + hyper::rt::Write>(
- state: Arc<State>,
- stream: T,
- addr: SocketAddr,
- secure: bool,
- listen_addr: SocketAddr,
-) {
- if let Ok(_semaphore) = state.l_incoming.try_acquire() {
- let builder = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new());
- let conn = builder.serve_connection_with_upgrades(
- stream,
- service_fn(|req| {
- let state = state.clone();
- async move {
- let req = req.map(|body: Incoming| body.map_err(ServiceError::Hyper).boxed());
- match service(state, req, addr, secure, listen_addr).await {
- Ok(r) => Ok(r),
- Err(ServiceError::Hyper(e)) => Err(e),
- Err(error) => Ok(error_response(addr, error)),
- }
- }
- }),
- );
- if let Err(err) = conn.await {
- warn!("error: {:?}", err);
- }
- } else {
- warn!("connection dropped: too many incoming");
- }
-}
-
fn error_response(addr: SocketAddr, error: ServiceError) -> Response<BoxBody<Bytes, ServiceError>> {
{
warn!("service error {addr} {error:?}");