Skip to content

feat: manual TLS certificates for custom domain WSS listeners (RFC) - #11461

Draft
karawitan wants to merge 1 commit into
ipfs:masterfrom
karawitan:feat/manual-wss-certs
Draft

karawitan wants to merge 1 commit into
ipfs:masterfrom
karawitan:feat/manual-wss-certs

Conversation

@karawitan

Copy link
Copy Markdown
Contributor

Summary

Draft / RFC PR to drive design discussion for #11460.

Adds support for manual TLS certificate/key files for WSS (/wss) listeners on custom domains, complementing the existing AutoTLS feature which only covers *.libp2p.direct domains.

Motivation

This addresses the remaining review concern from @lidel on #8740 (now superseded by #10521):

What if we do the same thing we did for private swarm and if one adds /dns/example.net/.../wss addr, check if $IPFS_PATH/example.net.crt and $IPFS_PATH/example.net.key exist and use them if present? (and if not, do ACME)

Currently, operators who want WSS on their own domain (e.g. example.net) must run a reverse proxy (nginx, Caddy, etc.) in front of Kubo. This PR lets them serve WSS directly from Kubo using their own certificates.

Design

Follows the file convention approach (same as swarm.key for private networks):

  1. Operator places $IPFS_PATH/<domain>.crt and $IPFS_PATH/<domain>.key in the IPFS repo
  2. Adds a /dns/example.net/.../wss address to Addresses.Swarm
  3. When a TLS client connects with SNI example.net, Kubo loads the matching cert/key files
  4. Loaded certificates are cached in memory and reloaded when files change on disk

Coexistence with AutoTLS:

  • Manual certs take precedence for matching SNI hostnames
  • If no manual cert exists for the SNI, falls back to p2p-forge's certmagic (for *.libp2p.direct)
  • If neither is available, the TLS handshake fails for that hostname

Implementation

  • core/node/libp2p/manualtls.go — cert cache + GetCertificate callback that checks manual files first, falls back to p2p-forge
  • core/node/libp2p/transport.go — wires the manual cert getter into the websocket transport's TLS config
  • core/node/groups.go — passes repo path to Transports()
  • docs/config.md — documents the file convention
  • docs/changelogs/v0.44.md — changelog entry
  • core/node/libp2p/manualtls_test.go — unit tests for cache, loading, fallback, and edge cases

Open questions for reviewers

  1. File location: Files in repo root ($IPFS_PATH/<domain>.crt) vs. a subdirectory ($IPFS_PATH/wss-certs/<domain>.crt)? The repo root follows the swarm.key precedent but could get cluttered with many domains.
  2. Config option: Should this also have an explicit config flag (e.g. Swarm.Transports.Network.Websocket.ManualTLS), or is the file convention sufficient as an implicit opt-in?
  3. Security: Should we restrict cert file permissions (e.g. warn if key is world-readable)?
  4. Wildcard certs: Should we support wildcard matching (e.g. *.example.net.crt matching foo.example.net)?

Closes #11460.

Test plan

  • go build ./core/... ./cmd/... passes
  • go vet ./core/node/... passes
  • gofmt clean
  • Unit tests pass: go test ./core/node/libp2p/ -run TestManualCert -v
  • Integration test: start daemon with manual cert files, verify WSS handshake
  • Integration test: verify AutoTLS fallback when no manual cert exists

Generated with Devin

Add support for manual TLS certificate/key files for WSS listeners on
custom domains, complementing the existing AutoTLS feature which only
covers *.libp2p.direct domains.

Operators place $IPFS_PATH/<domain>.crt and $IPFS_PATH/<domain>.key in
the IPFS repo, and Kubo serves those certificates for the matching SNI
hostname on /wss connections. This follows the same file-convention
approach as the private network swarm.key.

Manual certs coexist with AutoTLS: manual certs take precedence for
matching SNI hostnames, and p2p-forge's certmagic is used as fallback
for *.libp2p.direct domains. Loaded certificates are cached in memory
and automatically reloaded when files change on disk.

Closes ipfs#11460.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support manual TLS certificate/key for custom domain WSS listeners

1 participant