healthcheck: misconfigured bitcoind zmq

This commit is contained in:
ErikEk 2021-09-11 14:43:46 +02:00
parent 71b23a2c54
commit 94cb818dd9
2 changed files with 94 additions and 6 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt"
"io/ioutil"
"net"
"net/url"
"os"
"strconv"
"strings"
@ -485,11 +486,92 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
// The api we will use for our health check depends on the
// bitcoind version.
cmd, err := getBitcoindHealthCheckCmd(chainConn)
cmd, ver, err := getBitcoindHealthCheckCmd(chainConn)
if err != nil {
return nil, nil, err
}
// If the getzmqnotifications api is available (was added in
// version 0.17.0) we make sure lnd subscribes to the correct
// zmq events. We do this to avoid a situation in which we are
// not notified of new transactions or blocks.
if ver >= 170000 {
zmqPubRawBlockURL, err := url.Parse(bitcoindMode.ZMQPubRawBlock)
if err != nil {
return nil, nil, err
}
zmqPubRawTxURL, err := url.Parse(bitcoindMode.ZMQPubRawTx)
if err != nil {
return nil, nil, err
}
// Fetch all active zmq notifications from the bitcoind client.
resp, err := chainConn.RawRequest("getzmqnotifications", nil)
if err != nil {
return nil, nil, err
}
zmq := []struct {
Type string `json:"type"`
Address string `json:"address"`
}{}
if err = json.Unmarshal([]byte(resp), &zmq); err != nil {
return nil, nil, err
}
pubRawBlockActive := false
pubRawTxActive := false
for i := range zmq {
if zmq[i].Type == "pubrawblock" {
url, err := url.Parse(zmq[i].Address)
if err != nil {
return nil, nil, err
}
if url.Port() != zmqPubRawBlockURL.Port() {
return nil, nil, fmt.Errorf(
"unable to subscribe to zmq block events on "+
"%s (bitcoind is running on %s)",
zmqPubRawBlockURL.Host,
url.Host,
)
}
pubRawBlockActive = true
}
if zmq[i].Type == "pubrawtx" {
url, err := url.Parse(zmq[i].Address)
if err != nil {
return nil, nil, err
}
if url.Port() != zmqPubRawTxURL.Port() {
return nil, nil, fmt.Errorf(
"unable to subscribe to zmq tx events on "+
"%s (bitcoind is running on %s)",
zmqPubRawTxURL.Host,
url.Host,
)
}
pubRawTxActive = true
}
}
// Return an error if raw tx or raw block notification over
// zmq is inactive.
if !pubRawBlockActive {
return nil, nil, errors.New(
"block notification over zmq is inactive on " +
"bitcoind",
)
}
if !pubRawTxActive {
return nil, nil, errors.New(
"tx notification over zmq is inactive on " +
"bitcoind",
)
}
}
cc.HealthCheck = func() error {
_, err := chainConn.RawRequest(cmd, nil)
return err
@ -711,11 +793,11 @@ func NewChainControl(walletConfig lnwallet.Config,
// command, because it has no locking and is an inexpensive call, which was
// added in version 0.15. If we are on an earlier version, we fallback to using
// getblockchaininfo.
func getBitcoindHealthCheckCmd(client *rpcclient.Client) (string, error) {
func getBitcoindHealthCheckCmd(client *rpcclient.Client) (string, int64, error) {
// Query bitcoind to get our current version.
resp, err := client.RawRequest("getnetworkinfo", nil)
if err != nil {
return "", err
return "", 0, err
}
// Parse the response to retrieve bitcoind's version.
@ -723,7 +805,7 @@ func getBitcoindHealthCheckCmd(client *rpcclient.Client) (string, error) {
Version int64 `json:"version"`
}{}
if err := json.Unmarshal(resp, &info); err != nil {
return "", err
return "", 0, err
}
// Bitcoind returns a single value representing the semantic version:
@ -733,10 +815,10 @@ func getBitcoindHealthCheckCmd(client *rpcclient.Client) (string, error) {
// The uptime call was added in version 0.15.0, so we return it for
// any version value >= 150000, as per the above calculation.
if info.Version >= 150000 {
return "uptime", nil
return "uptime", info.Version, nil
}
return "getblockchaininfo", nil
return "getblockchaininfo", info.Version, nil
}
var (

View File

@ -1,5 +1,10 @@
# Release Notes
## Security
* [Misconfigured ZMQ
setup now gets reported](https://github.com/lightningnetwork/lnd/pull/5710).
## Misc
* [An example systemd service file](https://github.com/lightningnetwork/lnd/pull/6033)
@ -15,3 +20,4 @@
# Contributors (Alphabetical Order)
* Daniel McNally
* ErikEk