lightningd: `--message-padding` to allow users to disable padding altogether.
What changed, and why it matters
This commit adds a new command-line/config option `--message-padding` that lets users turn off a recently added privacy feature. By default, Core Lightning now pads peer messages to the same length to hide which type of message is being sent. Some other Lightning implementations (LND variants and Eclair) reportedly reject or mis-handle those padding bytes, so this switch lets operators disable padding entirely if they run into compatibility problems. It is a workaround/configurability change, not a fix for a code vulnerability.
No immediate action required. Operators experiencing peer-connection or message-handling issues with LND/LNDK/Eclair nodes after the message-padding feature was introduced can set `message-padding=false` as a workaround. Security-conscious users should leave the default `true` unless interoperability issues force disabling it, because disabling padding removes a traffic-analysis mitigation.
Security signals we found
Adds an opt-out for a privacy feature (message-length padding)
Default behavior remains enabled; users must explicitly set false to disable
Motivated by interoperability failures with other Lightning implementations
No cryptographic, memory-safety, or authentication change
Does not patch a vulnerability; provides a compatibility escape hatch
Evidence from the diff
The change threads a new boolean message_padding from lightningd through the connectd_init wire message into connectd. The default remains true (padding enabled). In connectd/multiplex.c, the existing use_uniform_writes() predicate now also requires peer->daemon->message_padding to be true before sending padding/no-reply pings. A config option --message-padding=BOOL is registered and documented. The commit references prior work (#8893, #9022) that introduced message padding and explains the new global disable was added because of undetected incompatible peers (LND master, LND with LNDK).
Changed components
lightningd option parsing and configurationconnectd daemon initialization wire protocolconnectd multiplexing / peer write pathdocumentation: doc/lightningd-config.5.mdInspect captured patch +32 / −1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 438771a2..38bc39ac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ This release is named by @Chand-ra.
### Added
- Protocol: we now pad all peer messages to make them the same length (excluding LND < v21 and current Eclair). ([#8893], [#9022])
+ - Config: `message-padding` option can be set to `false` to disable it for all peers. ([#9068])
- JSON-RPC: `bkpr-report` allows flexible summaries of bookkeeper income. ([#8937])
- Config: `bkpr-currency` option to record conversion rate at each bookkeeper event. ([#8937])
- JSON-RPC: `currencyconvert` and `currencyrate` via the new plugin `cln-currencyrate` ([#8842], [#8937])
@@ -137,6 +138,7 @@ Note: You should always set `allow-deprecated-apis=false` to test for changes.
[#9022]: https://github.com/ElementsProject/lightning/pull/9022
[#9046]: https://github.com/ElementsProject/lightning/pull/9046
[#9047]: https://github.com/ElementsProject/lightning/pull/9047
+[#9068]: https://github.com/ElementsProject/lightning/pull/9068
[v26.04rc3]: https://github.com/ElementsProject/lightning/releases/tag/v26.04rc3
diff --git a/connectd/connectd.c b/connectd/connectd.c
index 343a59ec..54ac0891 100644
--- a/connectd/connectd.c
+++ b/connectd/connectd.c
@@ -1687,6 +1687,7 @@ static void connect_init(struct daemon *daemon, const u8 *msg)
&tor_password,
&daemon->timeout_secs,
&daemon->websocket_helper,
+ &daemon->message_padding,
&daemon->dev_fast_gossip,
&dev_disconnect,
&daemon->dev_no_ping_timer,
diff --git a/connectd/connectd.h b/connectd/connectd.h
index d3885c17..11665cc2 100644
--- a/connectd/connectd.h
+++ b/connectd/connectd.h
@@ -367,6 +367,9 @@ struct daemon {
* (--dev-limit-connectsion-inflight sets this to 1 for testing). */
size_t max_connect_in_flight;
+ /* Add padding to messages (if peer seems ok) */
+ bool message_padding;
+
/* Hack to speed up gossip timer */
bool dev_fast_gossip;
/* Hack to avoid ping timeouts */
diff --git a/connectd/connectd_wire.csv b/connectd/connectd_wire.csv
index d5f6aee3..c1361a59 100644
--- a/connectd/connectd_wire.csv
+++ b/connectd/connectd_wire.csv
@@ -18,6 +18,7 @@ msgdata,connectd_init,use_dns,bool,
msgdata,connectd_init,tor_password,wirestring,
msgdata,connectd_init,timeout_secs,u32,
msgdata,connectd_init,websocket_helper,wirestring,
+msgdata,connectd_init,message_padding,bool,
msgdata,connectd_init,dev_fast_gossip,bool,
# If this is set, then fd 5 is dev_disconnect_fd.
msgdata,connectd_init,dev_disconnect,bool,
diff --git a/connectd/multiplex.c b/connectd/multiplex.c
index 7dbacec1..46e3aeb0 100644
--- a/connectd/multiplex.c
+++ b/connectd/multiplex.c
@@ -491,9 +491,13 @@ static bool have_empty_encrypted_queue(const struct peer *peer)
* "Phoenix-specific custom splices implementation" which Tbast
* indicates is being phased out. So if they offer that, don't send
* such pings. */
+
+/* Oh, and then there was a node running LND master. And those running
+ * LND with LNDK: so we added global disable. */
static bool use_uniform_writes(const struct peer *peer)
{
- return feature_offered(peer->their_features, OPT_ONION_MESSAGES)
+ return peer->daemon->message_padding
+ && feature_offered(peer->their_features, OPT_ONION_MESSAGES)
&& !feature_offered(peer->their_features, 154);
}
diff --git a/doc/lightningd-config.5.md b/doc/lightningd-config.5.md
index 6df1d0f8..e85a1a19 100644
--- a/doc/lightningd-config.5.md
+++ b/doc/lightningd-config.5.md
@@ -707,6 +707,12 @@ all DNS lookups, to avoid leaking information.
Disable the DNS bootstrapping mechanism to find a node by its node ID.
+* **message-padding**=*BOOL*
+
+ Normally `connectd` will send extra bytes to peers to make messages
+uniform length. Some implementations don't accept these extra bytes:
+if we can't detect them, this option sets to `false` will disable it.
+
* **tor-service-password**=*PASSWORD*
Set a Tor control password, which may be needed for *autotor:* to
diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c
index e95a04db..9c8afa96 100644
--- a/lightningd/connect_control.c
+++ b/lightningd/connect_control.c
@@ -719,6 +719,7 @@ int connectd_init(struct lightningd *ld)
ld->tor_service_password ? ld->tor_service_password : "",
ld->config.connection_timeout_secs,
websocket_helper_path,
+ ld->message_padding,
ld->dev_fast_gossip,
ld->dev_disconnect_fd >= 0,
ld->dev_no_ping_timer,
diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c
index b0b2030a..8847e663 100644
--- a/lightningd/lightningd.c
+++ b/lightningd/lightningd.c
@@ -372,6 +372,12 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
ld->autoconnect_seeker_peers = 10;
ld->fronting_nodes = tal_arr(ld, struct node_id, 0);
+
+ /*~ connectd usually uses "no-reply" pings to fill out messages
+ * where needed to make them uniform length. Some implementations
+ * don't like it, so it can be disabled. */
+ ld->message_padding = true;
+
return ld;
}
diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h
index 9edba38d..3b4e0e84 100644
--- a/lightningd/lightningd.h
+++ b/lightningd/lightningd.h
@@ -434,6 +434,9 @@ struct lightningd {
/* Nodes to use for invoices / offers */
struct node_id *fronting_nodes;
+
+ /* Whether connectd should pad messages to make them equal length */
+ bool message_padding;
};
/* Turning this on allows a tal allocation to return NULL, rather than aborting.
diff --git a/lightningd/options.c b/lightningd/options.c
index b185d7ea..b724b200 100644
--- a/lightningd/options.c
+++ b/lightningd/options.c
@@ -1668,6 +1668,10 @@ static void register_opts(struct lightningd *ld)
opt_set_talstr, NULL,
&ld->old_bookkeeper_db,
opt_hidden);
+ clnopt_witharg("--message-padding", OPT_SHOWBOOL,
+ opt_set_bool_arg, opt_show_bool,
+ &ld->message_padding,
+ "If true (the default), pad all messages to peers to make them equal length");
dev_register_opts(ld);
}
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.