From 61d9843fcc3563f45179bab513d8efd94297c681 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 20 Feb 2025 00:50:54 +0100 Subject: [PATCH 1/8] feat(autotls): enable with RegistrationDelay Enables AutoTLS by default, but delays registration by 1h if user did not explicitly set `AutoTLS.Enabled` to `true` --- config/autotls.go | 22 +++++++++++++++------- core/node/libp2p/addrs.go | 9 +++++++++ docs/examples/kubo-as-a-library/go.mod | 2 +- docs/examples/kubo-as-a-library/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- test/dependencies/go.mod | 2 +- test/dependencies/go.sum | 4 ++-- 8 files changed, 33 insertions(+), 16 deletions(-) diff --git a/config/autotls.go b/config/autotls.go index 7c935fc647f..805a9ded65f 100644 --- a/config/autotls.go +++ b/config/autotls.go @@ -1,6 +1,10 @@ package config -import p2pforge "github.com/ipshipyard/p2p-forge/client" +import ( + "time" + + p2pforge "github.com/ipshipyard/p2p-forge/client" +) // AutoTLS includes optional configuration of p2p-forge client of service // for obtaining a domain and TLS certificate to improve connectivity for web @@ -21,6 +25,9 @@ type AutoTLS struct { // Optional Authorization token, used with private/test instances of p2p-forge RegistrationToken *OptionalString `json:",omitempty"` + // Optional registration delay used when AutoTLS.Enabled is not explicitly set to true in config + RegistrationDelay *OptionalDuration `json:",omitempty"` + // Optional override of CA ACME API used by p2p-forge system CAEndpoint *OptionalString `json:",omitempty"` @@ -29,10 +36,11 @@ type AutoTLS struct { } const ( - DefaultAutoTLSEnabled = false // experimental, opt-in for now (https://github.com/ipfs/kubo/pull/10521) - DefaultDomainSuffix = p2pforge.DefaultForgeDomain - DefaultRegistrationEndpoint = p2pforge.DefaultForgeEndpoint - DefaultCAEndpoint = p2pforge.DefaultCAEndpoint - DefaultAutoWSS = true // requires AutoTLS.Enabled - DefaultAutoTLSShortAddrs = true // requires AutoTLS.Enabled + DefaultAutoTLSEnabled = true // with DefaultAutoTLSRegistrationDelay, unless explicitly enabled in config + DefaultDomainSuffix = p2pforge.DefaultForgeDomain + DefaultRegistrationEndpoint = p2pforge.DefaultForgeEndpoint + DefaultCAEndpoint = p2pforge.DefaultCAEndpoint + DefaultAutoWSS = true // requires AutoTLS.Enabled + DefaultAutoTLSShortAddrs = true // requires AutoTLS.Enabled + DefaultAutoTLSRegistrationDelay = 1 * time.Hour ) diff --git a/core/node/libp2p/addrs.go b/core/node/libp2p/addrs.go index 4eee6a00bc5..8cc5287ec1e 100644 --- a/core/node/libp2p/addrs.go +++ b/core/node/libp2p/addrs.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "time" logging "github.com/ipfs/go-log" version "github.com/ipfs/kubo" @@ -145,11 +146,19 @@ func P2PForgeCertMgr(repoPath string, cfg config.AutoTLS, atlsLog *logging.ZapEv certmagic.Default.Logger = rawLogger.Named("default_fixme") certmagic.DefaultACME.Logger = rawLogger.Named("default_acme_client_fixme") + registrationDelay := cfg.RegistrationDelay.WithDefault(config.DefaultAutoTLSRegistrationDelay) + if cfg.Enabled == config.True && cfg.RegistrationDelay.IsDefault() { + // Skip delay if user explicitly enabled AutoTLS.Enabled in config + // and did not set custom AutoTLS.RegistrationDelay + registrationDelay = 0 * time.Second + } + certStorage := &certmagic.FileStorage{Path: storagePath} certMgr, err := p2pforge.NewP2PForgeCertMgr( p2pforge.WithLogger(rawLogger.Sugar()), p2pforge.WithForgeDomain(cfg.DomainSuffix.WithDefault(config.DefaultDomainSuffix)), p2pforge.WithForgeRegistrationEndpoint(cfg.RegistrationEndpoint.WithDefault(config.DefaultRegistrationEndpoint)), + p2pforge.WithRegistrationDelay(registrationDelay), p2pforge.WithCAEndpoint(cfg.CAEndpoint.WithDefault(config.DefaultCAEndpoint)), p2pforge.WithForgeAuth(cfg.RegistrationToken.WithDefault(os.Getenv(p2pforge.ForgeAuthEnv))), p2pforge.WithUserAgent(version.GetUserAgentVersion()), diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index 06f9135d861..559f01988f0 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -112,7 +112,7 @@ require ( github.com/ipld/go-car/v2 v2.14.2 // indirect github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect - github.com/ipshipyard/p2p-forge v0.3.0 // indirect + github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index 638b3f7fb8f..d83df211637 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -406,8 +406,8 @@ github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw= -github.com/ipshipyard/p2p-forge v0.3.0 h1:mdeFqiq8ljX149OCQvveV0vOlKeIt4PWkJjXVfux/GE= -github.com/ipshipyard/p2p-forge v0.3.0/go.mod h1:L0TJMzniMEDjX8G+RB201U2woHvASwbsujNVDNVivDo= +github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 h1:vkyFM3whSC6fC/yWHjcbGeOxrTTa0fpuSSNYe6rMXV0= +github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= diff --git a/go.mod b/go.mod index c11f79b6101..f986e70863e 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/ipld/go-car/v2 v2.14.2 github.com/ipld/go-codec-dagpb v1.6.0 github.com/ipld/go-ipld-prime v0.21.0 - github.com/ipshipyard/p2p-forge v0.3.0 + github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/julienschmidt/httprouter v1.3.0 diff --git a/go.sum b/go.sum index 7f40a2a98b3..fd1ec8569bd 100644 --- a/go.sum +++ b/go.sum @@ -474,8 +474,8 @@ github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw= -github.com/ipshipyard/p2p-forge v0.3.0 h1:mdeFqiq8ljX149OCQvveV0vOlKeIt4PWkJjXVfux/GE= -github.com/ipshipyard/p2p-forge v0.3.0/go.mod h1:L0TJMzniMEDjX8G+RB201U2woHvASwbsujNVDNVivDo= +github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 h1:vkyFM3whSC6fC/yWHjcbGeOxrTTa0fpuSSNYe6rMXV0= +github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index 1c91885f4a9..c65b07986ce 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -131,7 +131,7 @@ require ( github.com/ipfs/kubo v0.31.0 // indirect github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect - github.com/ipshipyard/p2p-forge v0.3.0 // indirect + github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index d3795696230..6d1da0007ea 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -364,8 +364,8 @@ github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6 github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= -github.com/ipshipyard/p2p-forge v0.3.0 h1:mdeFqiq8ljX149OCQvveV0vOlKeIt4PWkJjXVfux/GE= -github.com/ipshipyard/p2p-forge v0.3.0/go.mod h1:L0TJMzniMEDjX8G+RB201U2woHvASwbsujNVDNVivDo= +github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 h1:vkyFM3whSC6fC/yWHjcbGeOxrTTa0fpuSSNYe6rMXV0= +github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= From 539f965a90549b5fa81e607282b0df7c1b7ef356 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 20 Feb 2025 02:36:49 +0100 Subject: [PATCH 2/8] docs: AutoTLS.RegistrationDelay --- docs/config.md | 63 +++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/docs/config.md b/docs/config.md index ea4053f7adf..7c1b7e40ef2 100644 --- a/docs/config.md +++ b/docs/config.md @@ -34,6 +34,7 @@ config file at runtime. - [`AutoTLS.DomainSuffix`](#autotlsdomainsuffix) - [`AutoTLS.RegistrationEndpoint`](#autotlsregistrationendpoint) - [`AutoTLS.RegistrationToken`](#autotlsregistrationtoken) + - [`AutoTLS.RegistrationDelay`](#autotlsregistrationdelay) - [`AutoTLS.CAEndpoint`](#autotlscaendpoint) - [`Bootstrap`](#bootstrap) - [`Datastore`](#datastore) @@ -463,12 +464,7 @@ Type: `duration` (when `0`/unset, the default value is used) ## `AutoTLS` -> [!CAUTION] -> This is an **EXPERIMENTAL** opt-in feature and should not be used in production yet. -> Feel free to enable it and [report issues](https://github.com/ipfs/kubo/issues/new/choose) if you want to help with testing. -> Track progress in [kubo#10560](https://github.com/ipfs/kubo/issues/10560). - -AutoTLS feature enables publicly reachable Kubo nodes (those dialable from the public +The [AutoTLS](https://blog.libp2p.io/autotls/) feature enables publicly reachable Kubo nodes (those dialable from the public internet) to automatically obtain a wildcard TLS certificate for a DNS name unique to their PeerID at `*.[PeerID].libp2p.direct`. This enables direct libp2p connections and retrieval of IPFS content from browsers [Secure Context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts) @@ -480,11 +476,11 @@ broker enabling peer to obtain a wildcard TLS certificate tied to public key of By default, the certificates are requested from Let's Encrypt. Origin and rationale for this project can be found in [community.letsencrypt.org discussion](https://community.letsencrypt.org/t/feedback-on-raising-certificates-per-registered-domain-to-enable-peer-to-peer-networking/223003). + + > [!NOTE] > Public good DNS and [p2p-forge] infrastructure at `libp2p.direct` is run by the team at [Interplanetary Shipyard](https://ipshipyard.com). > -> - [p2p-forge]: https://github.com/ipshipyard/p2p-forge Default: `{}` @@ -493,33 +489,22 @@ Type: `object` ### `AutoTLS.Enabled` -> [!CAUTION] -> This is an **EXPERIMENTAL** opt-in feature and should not be used in production yet. -> Feel free to enable it and [report issues](https://github.com/ipfs/kubo/issues/new/choose) if you want to help with testing. -> Track progress in [kubo#10560](https://github.com/ipfs/kubo/issues/10560). +Enables the AutoTLS feature to provide DNS and TLS support for [libp2p Secure WebSocket](https://github.com/libp2p/specs/blob/master/websockets/README.md) over a `/tcp` port, +to allow JS clients running in web browser [Secure Context](https://w3c.github.io/webappsec-secure-contexts/) to connect to Kubo directly. -Enables AutoTLS feature to get DNS+TLS for [libp2p Secure WebSocket](https://github.com/libp2p/specs/blob/master/websockets/README.md) on `/tcp` port. +When activated, together with [`AutoTLS.AutoWSS`](#autotlsautowss) (default) or manually including a `/tcp/{port}/tls/sni/*.libp2p.direct/ws` multiaddr in [`Addresses.Swarm`](#addressesswarm) +(with SNI suffix matching [`AutoTLS.DomainSuffix`](#autotlsdomainsuffix)), Kubo retrieves a trusted PKI TLS certificate for `*.{peerid}.libp2p.direct` and configures the `/ws` listener to use it. -If `AutoTLS.AutoWSS` is `true`, or `/tcp/../tls/sni/*.libp2p.direct/ws` [multiaddr] is present in [`Addresses.Swarm`](#addressesswarm) -with SNI segment ending with [`AutoTLS.DomainSuffix`](#autotlsdomainsuffix), -Kubo will obtain and set up a trusted PKI TLS certificate for `*.peerid.libp2p.direct`, making it dialable from web browser's [Secure Contexts](https://w3c.github.io/webappsec-secure-contexts/). +**Note:** -> [!TIP] -> - Most users don't need custom `/ws` config in `Addresses.Swarm`. Try running this with `AutoTLS.AutoWSS=true`: it will reuse preexisting catch-all `/tcp` ports that were already forwarded/safelisted on your firewall. -> - Debugging can be enabled by setting environment variable `GOLOG_LOG_LEVEL="error,autotls=debug,p2p-forge/client=debug"`. Less noisy `GOLOG_LOG_LEVEL="error,autotls=info` may be informative enough. -> - Certificates are stored in `$IPFS_PATH/p2p-forge-certs`. Removing directory and restarting daemon will trigger certificate rotation. - -> [!IMPORTANT] -> Caveats: -> - Requires your Kubo node to be publicly dialable. -> - If you want to test this with a node that is behind a NAT and uses manual TCP port forwarding or UPnP (`Swarm.DisableNatPortMap=false`), use `AutoTLS.AutoWSS=true`, or manually -> add catch-all `/ip4/0.0.0.0/tcp/4001/tls/sni/*.libp2p.direct/ws` and `/ip6/::/tcp/4001/tls/sni/*.libp2p.direct/ws` to [`Addresses.Swarm`](#addressesswarm) -> and **wait 5-15 minutes** for libp2p node to set up and learn about own public addresses via [AutoNAT](#autonat). -> - If your node is fresh and just started, the [p2p-forge] client may produce and log ERRORs during this time, but once a publicly dialable addresses are set up, a subsequent retry should be successful. -> - The TLS certificate is used only for [libp2p WebSocket](https://github.com/libp2p/specs/blob/master/websockets/README.md) connections. -> - Right now, this is NOT used for hosting a [Gateway](#gateway) over HTTPS (that use case still requires manual TLS setup on reverse proxy, and your own domain). +- This feature requires a publicly reachable node. If behind NAT, manual port forwarding or UPnP (`Swarm.DisableNatPortMap=false`) is required. +- The first time AutoTLS is used, it may take 5-15 minutes + [`AutoTLS.RegistrationDelay`](#autotlsregistrationdelay) before `/ws` listener is added. Be patient. +- Avoid manual configuration. [`AutoTLS.AutoWSS=true`](#autotlsautowss) should automatically add `/ws` listener to existing, firewall-forwarded `/tcp` ports. +- To troubleshoot, use `GOLOG_LOG_LEVEL="error,autotls=debug` for detailed logs, or `GOLOG_LOG_LEVEL="error,autotls=info` for quieter output. +- Certificates are stored in `$IPFS_PATH/p2p-forge-certs`; deleting this directory and restarting the daemon forces a certificate rotation. +- For now, the TLS cert applies solely to `/ws` libp2p WebSocket connections, not HTTP [`Gateway`](#gateway), which still need separate reverse proxy TLS setup with a custom domain. -Default: `false` +Default: `true` Type: `flag` @@ -527,7 +512,7 @@ Type: `flag` Optional. Controls if Kubo should add `/tls/sni/*.libp2p.direct/ws` listener to every pre-existing `/tcp` port IFF no explicit `/ws` is defined in [`Addresses.Swarm`](#addressesswarm) already. -Default: `true` (active only if `AutoTLS.Enabled` is `true` as well) +Default: `true` (if `AutoTLS.Enabled`) Type: `flag` @@ -535,8 +520,7 @@ Type: `flag` Optional. Controls if final AutoTLS listeners are announced under shorter `/dnsX/A.B.C.D.peerid.libp2p.direct/tcp/4001/tls/ws` addresses instead of fully resolved `/ip4/A.B.C.D/tcp/4001/tls/sni/A-B-C-D.peerid.libp2p.direct/tls/ws`. -> [!TIP] -> The main use for AutoTLS is allowing connectivity from Secure Context in a web browser, and DNS lookup needs to happen there anyway, making `/dnsX` a more compact, more interoperable option without obvious downside. +The main use for AutoTLS is allowing connectivity from Secure Context in a web browser, and DNS lookup needs to happen there anyway, making `/dnsX` a more compact, more interoperable option without obvious downside. Default: `true` @@ -574,6 +558,17 @@ Default: `""` Type: `optionalString` +### `AutoTLS.RegistrationDelay` + +An additional delay applied before sending a request to the `RegistrationEndpoint`. + +The default delay is bypassed if the user explicitly set `AutoTLS.Enabled=true` in the JSON configuration file. +This ensures that ephemeral nodes using the default configuration do not spam the`AutoTLS.CAEndpoint` with unnecessary ACME requests. + +Default: `1h` (or `0` if explicit `AutoTLS.Enabled=true`) + +Type: `optionalDuration` + ### `AutoTLS.CAEndpoint` Optional override of CA ACME API used by [p2p-forge] system. From 9b6e15717c9b92ba3d37dd6f06d9ee3b850638bf Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 20 Feb 2025 21:40:57 +0100 Subject: [PATCH 3/8] fix(ux): log ERROR when AutoTLS is disabled hard fail when TCP or Websocket is not present is a bad UX + explodes complexity of tests. instead, we log user-friendly ERROR and disable AutoTLS when there is no /tcp, no Websocket transport, or PNET is used with default settings --- cmd/ipfs/kubo/daemon.go | 13 ++++++++++--- core/node/groups.go | 24 ++++++++++++++---------- test/cli/transports_test.go | 3 +++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/cmd/ipfs/kubo/daemon.go b/cmd/ipfs/kubo/daemon.go index 0615b26d318..fe01501ece0 100644 --- a/cmd/ipfs/kubo/daemon.go +++ b/cmd/ipfs/kubo/daemon.go @@ -421,9 +421,16 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment // Private setups should not use public AutoTLS infrastructure // as it will leak their existence and PeerID identity to CA // and they will show up at https://crt.sh/?q=libp2p.direct - // Below ensures we hard fail if someone tries to enable both - if cfg.AutoTLS.Enabled.WithDefault(config.DefaultAutoTLSEnabled) { - return errors.New("private networking (swarm.key / LIBP2P_FORCE_PNET) does not work with AutoTLS.Enabled=true, update config to remove this message") + enableAutoTLS := cfg.AutoTLS.Enabled.WithDefault(config.DefaultAutoTLSEnabled) + if enableAutoTLS { + if cfg.AutoTLS.Enabled != config.Default { + // hard fail if someone tries to explicitly enable both + return errors.New("private networking (swarm.key / LIBP2P_FORCE_PNET) does not work with AutoTLS.Enabled=true, update config to remove this message") + } else { + // print error and disable autotls if user runs on default settings + log.Error("private networking (swarm.key / LIBP2P_FORCE_PNET) is not compatible with AutoTLS. Set AutoTLS.Enabled=false in config to remove this message.") + cfg.AutoTLS.Enabled = config.False + } } } diff --git a/core/node/groups.go b/core/node/groups.go index 0f65230dd3c..e8f9739c36e 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -112,6 +112,8 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part autonat = fx.Provide(libp2p.AutoNATService(cfg.AutoNAT.Throttle, true)) } + enableTCPTransport := cfg.Swarm.Transports.Network.TCP.WithDefault(true) + enableWebsocketTransport := cfg.Swarm.Transports.Network.Websocket.WithDefault(true) enableRelayTransport := cfg.Swarm.Transports.Network.Relay.WithDefault(true) // nolint enableRelayService := cfg.Swarm.RelayService.Enabled.WithDefault(enableRelayTransport) enableRelayClient := cfg.Swarm.RelayClient.Enabled.WithDefault(enableRelayTransport) @@ -129,14 +131,8 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part } } - if enableAutoTLS { - if !cfg.Swarm.Transports.Network.TCP.WithDefault(true) { - logger.Fatal("Invalid configuration: AutoTLS.Enabled=true requires Swarm.Transports.Network.TCP to be true as well.") - } - if !cfg.Swarm.Transports.Network.Websocket.WithDefault(true) { - logger.Fatal("Invalid configuration: AutoTLS.Enabled=true requires Swarm.Transports.Network.Websocket to be true as well.") - } - + switch { + case enableAutoTLS && enableTCPTransport && enableWebsocketTransport: // AutoTLS for Secure WebSockets: ensure WSS listeners are in place (manual or automatic) wssWildcard := fmt.Sprintf("/tls/sni/*.%s/ws", cfg.AutoTLS.DomainSuffix.WithDefault(config.DefaultDomainSuffix)) wssWildcardPresent := false @@ -170,7 +166,8 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part // if no manual /ws listener was set by the user if enableAutoWSS && !wssWildcardPresent && !customWsPresent { if len(tcpListeners) == 0 { - logger.Fatal("Invalid configuration: AutoTLS.AutoWSS=true requires at least one /tcp listener present in Addresses.Swarm, see https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls") + logger.Error("Invalid configuration, AutoTLS will be disabled: AutoTLS.AutoWSS=true requires at least one /tcp listener present in Addresses.Swarm, see https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls") + enableAutoTLS = false } for _, tcpListener := range tcpListeners { wssListener := tcpListener + wssWildcard @@ -180,8 +177,15 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part } if !wssWildcardPresent && !enableAutoWSS { - logger.Fatal(fmt.Sprintf("Invalid configuration: AutoTLS.Enabled=true requires a /tcp listener ending with %q to be present in Addresses.Swarm or AutoTLS.AutoWSS=true, see https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls", wssWildcard)) + logger.Error(fmt.Sprintf("Invalid configuration, AutoTLS will be disabled: AutoTLS.Enabled=true requires a /tcp listener ending with %q to be present in Addresses.Swarm or AutoTLS.AutoWSS=true, see https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls", wssWildcard)) + enableAutoTLS = false } + case enableAutoTLS && !enableTCPTransport: + logger.Error("Invalid configuration: AutoTLS.Enabled=true requires Swarm.Transports.Network.TCP to be true as well. AutoTLS will be disabled.") + enableAutoTLS = false + case enableAutoTLS && !enableWebsocketTransport: + logger.Error("Invalid configuration: AutoTLS.Enabled=true requires Swarm.Transports.Network.Websocket to be true as well. AutoTLS will be disabled.") + enableAutoTLS = false } // Gather all the options diff --git a/test/cli/transports_test.go b/test/cli/transports_test.go index cbef5c57da0..ec27e00baf8 100644 --- a/test/cli/transports_test.go +++ b/test/cli/transports_test.go @@ -94,6 +94,7 @@ func TestTransports(t *testing.T) { cfg.Swarm.Transports.Network.QUIC = config.True cfg.Swarm.Transports.Network.WebTransport = config.False cfg.Swarm.Transports.Network.WebRTCDirect = config.False + cfg.Swarm.Transports.Network.Websocket = config.False }) }) disableRouting(nodes) @@ -111,6 +112,7 @@ func TestTransports(t *testing.T) { cfg.Swarm.Transports.Network.QUIC = config.True cfg.Swarm.Transports.Network.WebTransport = config.True cfg.Swarm.Transports.Network.WebRTCDirect = config.False + cfg.Swarm.Transports.Network.Websocket = config.False }) }) disableRouting(nodes) @@ -150,6 +152,7 @@ func TestTransports(t *testing.T) { cfg.Swarm.Transports.Network.QUIC = config.False cfg.Swarm.Transports.Network.WebTransport = config.False cfg.Swarm.Transports.Network.WebRTCDirect = config.True + cfg.Swarm.Transports.Network.Websocket = config.False }) }) disableRouting(nodes) From b519c164eb046313e15318efab05987650d59d27 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Fri, 21 Feb 2025 02:00:51 +0100 Subject: [PATCH 4/8] docs: changelog --- docs/changelogs/v0.34.md | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/changelogs/v0.34.md b/docs/changelogs/v0.34.md index 28b6ecd259b..1a4ae59ff5a 100644 --- a/docs/changelogs/v0.34.md +++ b/docs/changelogs/v0.34.md @@ -6,17 +6,39 @@ - [Overview](#overview) - [๐Ÿ”ฆ Highlights](#-highlights) + - [AutoTLS now enabled by default for nodes with 1 hour uptime](#autotls-now-enabled-by-default-for-nodes-with-1-hour-uptime) - [RPC and CLI command changes](#rpc-and-cli-command-changes) - [Bitswap improvements from Boxo](#bitswap-improvements-from-boxo) - - [IPFS_LOG_LEVEL deprecated](#ipfs_log_level-deprecated) - - [Pebble datastore format upgrade](#pebble_datastore_format_update) - - [Badger datastore update](#badger_datastore_update) + - [`IPFS_LOG_LEVEL` deprecated](#ipfs_log_level-deprecated) + - [Pebble datastore format update](#pebble-datastore-format-update) + - [Badger datastore update](#badger-datastore-update) - [๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Contributors](#-contributors) ### Overview ### ๐Ÿ”ฆ Highlights +#### AutoTLS now enabled by default for nodes with 1 hour uptime + +Starting now, any publicly dialable Kubo node with a `/tcp` listener that remains online for at least one hour will automatically receive a TLS certificate through the [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) feature. This hapens by default, without requiring manual intervention. + +To bypass the 1-hour delay and enable AutoTLS immediately, users can explicitly opt-in by running the following commands: + +```console +$ ipfs config --json AutoTLS.Enabled true +$ ipfs config --json AutoTLS.RegistrationDelay 0 +``` + +AutoTLS will remain disabled under the following conditions: + +- The node already has a manually configured `/ws` (WebSocket) listener +- A private network is in use with a `swarm.key` +- TCP or WebSocket transports are disabled, or there is no `/tcp` listener + +To troubleshoot, use `GOLOG_LOG_LEVEL="error,autotls=info`. + +For more details, check out the [`AutoTLS` configuration documentation](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) or dive deeper with [AutoTLS libp2p blog post](https://blog.libp2p.io/autotls/). + #### RPC and CLI command changes - `ipfs config` is now validating json fields ([#10679](https://github.com/ipfs/kubo/pull/10679)). From 5a7f57ba6461849db671f762cd5f1b689f38b221 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Fri, 21 Feb 2025 02:07:08 +0100 Subject: [PATCH 5/8] test: fix TestIface/Routing/TestRoutingFindPeer --- core/coreapi/test/api_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/coreapi/test/api_test.go b/core/coreapi/test/api_test.go index d647a32c87c..dfd8cf6854b 100644 --- a/core/coreapi/test/api_test.go +++ b/core/coreapi/test/api_test.go @@ -69,6 +69,7 @@ func (NodeProvider) MakeAPISwarm(t *testing.T, ctx context.Context, fullIdentity c.Addresses.Swarm = []string{fmt.Sprintf("/ip4/18.0.%d.1/tcp/4001", i)} c.Identity = ident c.Experimental.FilestoreEnabled = true + c.AutoTLS.Enabled = config.False // disable so no /ws listener is added ds := syncds.MutexWrap(datastore.NewMapDatastore()) r := &repo.Mock{ From 78766eab6bd61f8a381847bdc934a30ac7933cda Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Fri, 21 Feb 2025 02:18:25 +0100 Subject: [PATCH 6/8] fix: disable AutoTLS in test profile --- config/profile.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/profile.go b/config/profile.go index 03e62172ae2..69aaf66dcb6 100644 --- a/config/profile.go +++ b/config/profile.go @@ -86,6 +86,7 @@ is useful when using the daemon in test environments.`, c.Bootstrap = []string{} c.Discovery.MDNS.Enabled = false + c.AutoTLS.Enabled = False return nil }, }, @@ -104,6 +105,7 @@ Inverse profile of the test profile.`, c.Swarm.DisableNatPortMap = false c.Discovery.MDNS.Enabled = true + c.AutoTLS.Enabled = Default return nil }, }, From 26220dda6a5f32a45124aee5a307054a7e8fd1a7 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Fri, 21 Feb 2025 02:29:43 +0100 Subject: [PATCH 7/8] chore: spellcheck --- docs/changelogs/v0.34.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changelogs/v0.34.md b/docs/changelogs/v0.34.md index 1a4ae59ff5a..5981ef7be69 100644 --- a/docs/changelogs/v0.34.md +++ b/docs/changelogs/v0.34.md @@ -20,7 +20,8 @@ #### AutoTLS now enabled by default for nodes with 1 hour uptime -Starting now, any publicly dialable Kubo node with a `/tcp` listener that remains online for at least one hour will automatically receive a TLS certificate through the [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) feature. This hapens by default, without requiring manual intervention. +Starting now, any publicly dialable Kubo node with a `/tcp` listener that remains online for at least one hour will receive a TLS certificate through the [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls) feature. +This occurs automatically, with no need for manual setup. To bypass the 1-hour delay and enable AutoTLS immediately, users can explicitly opt-in by running the following commands: From afd6538f3d544b2f9761c3deb13dd785d35f9c01 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 25 Feb 2025 19:24:20 +0100 Subject: [PATCH 8/8] chore: p2p-forge v0.4.0 https://github.com/ipshipyard/p2p-forge/releases/tag/v0.4.0 --- docs/examples/kubo-as-a-library/go.mod | 2 +- docs/examples/kubo-as-a-library/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- test/dependencies/go.mod | 2 +- test/dependencies/go.sum | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index 559f01988f0..0c6809728ba 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -112,7 +112,7 @@ require ( github.com/ipld/go-car/v2 v2.14.2 // indirect github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect - github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 // indirect + github.com/ipshipyard/p2p-forge v0.4.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index d83df211637..26112037a7f 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -406,8 +406,8 @@ github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw= -github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 h1:vkyFM3whSC6fC/yWHjcbGeOxrTTa0fpuSSNYe6rMXV0= -github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= +github.com/ipshipyard/p2p-forge v0.4.0 h1:A40PW027nCZn0d/pw5ufMoxnAo9wZwrG+iuz18A8P5I= +github.com/ipshipyard/p2p-forge v0.4.0/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= diff --git a/go.mod b/go.mod index f986e70863e..393338505af 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/ipld/go-car/v2 v2.14.2 github.com/ipld/go-codec-dagpb v1.6.0 github.com/ipld/go-ipld-prime v0.21.0 - github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 + github.com/ipshipyard/p2p-forge v0.4.0 github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/julienschmidt/httprouter v1.3.0 diff --git a/go.sum b/go.sum index fd1ec8569bd..a77d134ae27 100644 --- a/go.sum +++ b/go.sum @@ -474,8 +474,8 @@ github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd/go.mod h1:wZ8hH8UxeryOs4kJEJaiui/s00hDSbE37OKsL47g+Sw= -github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 h1:vkyFM3whSC6fC/yWHjcbGeOxrTTa0fpuSSNYe6rMXV0= -github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= +github.com/ipshipyard/p2p-forge v0.4.0 h1:A40PW027nCZn0d/pw5ufMoxnAo9wZwrG+iuz18A8P5I= +github.com/ipshipyard/p2p-forge v0.4.0/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index c65b07986ce..f491a0325f9 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -131,7 +131,7 @@ require ( github.com/ipfs/kubo v0.31.0 // indirect github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect - github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 // indirect + github.com/ipshipyard/p2p-forge v0.4.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index 6d1da0007ea..af831ba7d48 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -364,8 +364,8 @@ github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6 github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= -github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050 h1:vkyFM3whSC6fC/yWHjcbGeOxrTTa0fpuSSNYe6rMXV0= -github.com/ipshipyard/p2p-forge v0.3.2-0.20250219220033-0b73f1a01050/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= +github.com/ipshipyard/p2p-forge v0.4.0 h1:A40PW027nCZn0d/pw5ufMoxnAo9wZwrG+iuz18A8P5I= +github.com/ipshipyard/p2p-forge v0.4.0/go.mod h1:hVGPP24xrRezP2+z6q8udEW36w89M+jWuWBz9meLggY= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=