Skip to content
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
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ curl 7.82 or newer; older versions take

For demo purposes, let's first start the service *without authentication*.
This mode is NOT SECURE! See below how to set up authentication.
`--insecure` also turns TLS off, hence the plain `http://` below.
`--insecure` also turns TLS off, hence the plain `http://` below. It
listens on `127.0.0.1:1031` only. Use `--bind=` if more is needed.

```console
$ systemd-run --user ./target/debug/varlink-httpd --insecure
Expand Down Expand Up @@ -297,7 +298,9 @@ authenticate the client; without mTLS the bridge refuses to start.
mTLS is enabled separately (see below) and applies on top of whatever
`--auth=` selects, so `--auth=ssh` together with mTLS requires both to
pass. `--insecure` is the one way to serve with no authentication at
all, and implies `--auth=none`.
all, and implies `--auth=none`. Because nothing authenticates the
client, it defaults to listening on `127.0.0.1:1031` instead of the
usual `0.0.0.0:1031`. Use `--bind=` if more is needed.

### TLS / mTLS

Expand All @@ -308,7 +311,8 @@ TLS flag names follow the systemd convention.
--key=PATH path to TLS private key PEM file
--trust=PATH path to CA certificate PEM for client verification (mTLS)
--require-mtls require a verified client certificate
--insecure run over plain HTTP without any authentication (DANGEROUS)
--insecure run over plain HTTP without any authentication (DANGEROUS,
listens on localhost only unless --bind= says otherwise)
```

`--require-mtls` makes every client present a certificate signed by the
Expand Down
27 changes: 24 additions & 3 deletions src/bin/varlink-httpd/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1620,7 +1620,8 @@ fn print_help() {
VARLINK_SOCKETS_PATH directory of sockets or a single socket
(default: /run/varlink/registry)
--bind=ADDR address to bind to (repeatable;
default: 0.0.0.0:{DEFAULT_PORT})
default: 0.0.0.0:{DEFAULT_PORT}, or
127.0.0.1:{DEFAULT_PORT} with --insecure)
use vsock::PORT for vsock (e.g. vsock::{DEFAULT_PORT})
--auth=MECHANISMS comma-separated per-request authentication
({auth}); required unless --insecure.
Expand All @@ -1638,7 +1639,9 @@ fn print_help() {
--authorized-keys=PATH authorized SSH public keys file
--api-keys=PATH API key hashes file (see gen-api-key)
--insecure run over plain HTTP without any
authentication (DANGEROUS)
authentication (DANGEROUS); listens
on localhost only unless --bind= says
otherwise
--help display this help and exit
",
auth = AuthMechanism::names(),
Expand Down Expand Up @@ -1683,6 +1686,20 @@ fn check_mechanism_flags(
Ok(())
}

fn default_bind(insecure: bool) -> (String, Option<String>) {
if insecure {
(
format!("127.0.0.1:{DEFAULT_PORT}"),
Some(format!(
"--insecure listens on 127.0.0.1:{DEFAULT_PORT} only, \
pass --bind= if needed"
)),
)
} else {
(format!("0.0.0.0:{DEFAULT_PORT}"), None)
}
}

fn parse_cli() -> anyhow::Result<Command> {
use lexopt::prelude::*;

Expand Down Expand Up @@ -1734,7 +1751,11 @@ fn parse_cli() -> anyhow::Result<Command> {
}

if bind_strs.is_empty() {
bind_strs.push(format!("0.0.0.0:{DEFAULT_PORT}"));
let (bind, note) = default_bind(insecure);
if let Some(note) = note {
warn!("{note}");
}
bind_strs.push(bind);
}
let binds: Vec<BindAddr> = bind_strs
.iter()
Expand Down
15 changes: 15 additions & 0 deletions src/bin/varlink-httpd/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,21 @@ fn test_format_x509_subject_multiple_fields() {

// --- bind address parsing tests ---

#[test]
fn test_default_bind_insecure_is_localhost_only() {
let (bind, note) = crate::default_bind(true);
assert_eq!(bind, format!("127.0.0.1:{DEFAULT_PORT}"));
let note = note.expect("--insecure should explain the narrowed default");
assert!(note.contains("--bind="), "note: {note}");
}

#[test]
fn test_default_bind_authenticated_is_wildcard() {
let (bind, note) = crate::default_bind(false);
assert_eq!(bind, format!("0.0.0.0:{DEFAULT_PORT}"));
assert_eq!(note, None);
}

#[test]
fn test_bind_addr_parse_defaults() {
// "vsock" and "vsock:" both mean CID_ANY + default port
Expand Down
Loading