mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-07 23:30:20 +00:00
Add an option to allow disabling endpoint verification after tightening the requirements
This commit is contained in:
@@ -527,6 +527,13 @@
|
||||
#
|
||||
# The current default (which is subject to change) is 300 seconds.
|
||||
#
|
||||
# verify_endpoints = <0 | 1>
|
||||
#
|
||||
# If set to 1, the server will verify the validity of endpoint
|
||||
# addresses received in TMEndpoints peer protocol messages by
|
||||
# checking that they are well-formed and publicly routable. Invalid
|
||||
# endpoints will be dropped. The default is 1 (verification enabled).
|
||||
#
|
||||
#
|
||||
# [transaction_queue] EXPERIMENTAL
|
||||
#
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
async_connect(beast::IP::Endpoint const& ep, Handler&& handler)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
handler(ep, ep, ec);
|
||||
handler(ec);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -541,6 +541,84 @@ public:
|
||||
pass("[2606:4700:4700::1111]:8080");
|
||||
}
|
||||
|
||||
void
|
||||
test_verify_endpoints()
|
||||
{
|
||||
// Helper that sets up a Logic instance, creates and activates a slot,
|
||||
// then calls on_endpoints with the given list and returns the
|
||||
// livecache size afterwards.
|
||||
auto run = [&](bool verifyEndpoints, Endpoints eps) -> std::size_t {
|
||||
TestStore store;
|
||||
TestChecker checker;
|
||||
TestStopwatch clock;
|
||||
Logic<TestChecker> logic(clock, store, checker, journal_);
|
||||
{
|
||||
Config c;
|
||||
c.autoConnect = false;
|
||||
c.listeningPort = 1024;
|
||||
c.ipLimit = 2;
|
||||
c.verifyEndpoints = verifyEndpoints;
|
||||
logic.config(c);
|
||||
}
|
||||
|
||||
auto const remote = beast::IP::Endpoint::from_string("65.0.0.1:5");
|
||||
auto const local =
|
||||
beast::IP::Endpoint::from_string("65.0.0.2:1024");
|
||||
|
||||
auto const [slot, r] = logic.new_outbound_slot(remote);
|
||||
BEAST_EXPECT(slot != nullptr);
|
||||
BEAST_EXPECT(r == Result::success);
|
||||
BEAST_EXPECT(logic.onConnected(slot, local));
|
||||
|
||||
PublicKey const pk(randomKeyPair(KeyType::secp256k1).first);
|
||||
BEAST_EXPECT(logic.activate(slot, pk, false) == Result::success);
|
||||
|
||||
logic.on_endpoints(slot, std::move(eps));
|
||||
|
||||
auto const size = logic.livecache_.size();
|
||||
logic.on_closed(slot);
|
||||
return size;
|
||||
};
|
||||
|
||||
{
|
||||
testcase("verify_endpoints enabled");
|
||||
|
||||
// Valid public addresses
|
||||
Endpoints eps;
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("44.0.0.1:5"), 1});
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("44.0.0.2:6"), 1});
|
||||
// Invalid: private address
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("10.0.0.1:5"), 1});
|
||||
// Invalid: port 0
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("44.0.0.3:0"), 1});
|
||||
|
||||
// With verification enabled, only the 2 valid endpoints survive
|
||||
BEAST_EXPECT(run(true, eps) == 2);
|
||||
}
|
||||
{
|
||||
testcase("verify_endpoints disabled");
|
||||
|
||||
Endpoints eps;
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("44.0.0.1:5"), 1});
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("44.0.0.2:6"), 1});
|
||||
// Private address — kept when verification is off
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("10.0.0.1:5"), 1});
|
||||
// Port 0 — kept when verification is off
|
||||
eps.push_back(
|
||||
Endpoint{beast::IP::Endpoint::from_string("44.0.0.3:0"), 1});
|
||||
|
||||
// Without verification, all 4 endpoints survive
|
||||
BEAST_EXPECT(run(false, eps) == 4);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_onConnected_self_connection()
|
||||
{
|
||||
@@ -597,7 +675,7 @@ public:
|
||||
(c.PEERS_MAX == max && c.PEERS_IN_MAX == 0 && c.PEERS_OUT_MAX == 0) ||
|
||||
(c.PEERS_IN_MAX == *maxIn && c.PEERS_OUT_MAX == *maxOut));
|
||||
|
||||
Config const config = Config::makeConfig(c, port, false, 0);
|
||||
Config config = Config::makeConfig(c, port, false, 0, true);
|
||||
|
||||
Counts counts;
|
||||
counts.onConfig(config);
|
||||
@@ -698,6 +776,7 @@ public:
|
||||
test_addFixedPeer_no_port();
|
||||
test_onConnected_self_connection();
|
||||
test_is_valid_address();
|
||||
test_verify_endpoints();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
std::uint32_t crawlOptions = 0;
|
||||
std::optional<std::uint32_t> networkID;
|
||||
bool vlEnabled = true;
|
||||
bool verifyEndpoints = false;
|
||||
};
|
||||
|
||||
using PeerSequence = std::vector<std::shared_ptr<Peer>>;
|
||||
|
||||
@@ -447,7 +447,8 @@ OverlayImpl::start()
|
||||
app_.config(),
|
||||
serverHandler_.setup().overlay.port(),
|
||||
app_.getValidationPublicKey().has_value(),
|
||||
setup_.ipLimit);
|
||||
setup_.ipLimit,
|
||||
setup_.verifyEndpoints);
|
||||
|
||||
m_peerFinder->setConfig(config);
|
||||
m_peerFinder->start();
|
||||
@@ -1469,6 +1470,8 @@ setup_Overlay(BasicConfig const& config)
|
||||
if (ec || beast::IP::is_private(setup.public_ip))
|
||||
Throw<std::runtime_error>("Configured public IP is invalid");
|
||||
}
|
||||
|
||||
set(setup.verifyEndpoints, true, "verify_endpoints", section);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -61,6 +61,9 @@ struct Config
|
||||
/** Limit how many incoming connections we allow per IP */
|
||||
int ipLimit{0};
|
||||
|
||||
/** `true` if we want to verify endpoints in TMEndpoints messages */
|
||||
bool verifyEndpoints = false;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Create a configuration with default values. */
|
||||
@@ -83,6 +86,8 @@ struct Config
|
||||
* @param port server's listening port
|
||||
* @param validationPublicKey true if validation public key is not empty
|
||||
* @param ipLimit limit of incoming connections per IP
|
||||
* @param verifyEndpoints `true` if we want to verify endpoints in
|
||||
* TMEndpoints messages
|
||||
* @return PeerFinder::Config
|
||||
*/
|
||||
static Config
|
||||
@@ -90,10 +95,11 @@ struct Config
|
||||
xrpl::Config const& config,
|
||||
std::uint16_t port,
|
||||
bool validationPublicKey,
|
||||
int ipLimit);
|
||||
int ipLimit,
|
||||
bool verifyEndpoints);
|
||||
|
||||
friend bool
|
||||
operator==(Config const& lhs, Config const& rhs);
|
||||
operator==(Config const& lhs, Config const& rhs) = default;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -693,7 +693,7 @@ public:
|
||||
}
|
||||
|
||||
// Discard invalid addresses
|
||||
if (!is_valid_address(ep.address))
|
||||
if (!is_valid_address(ep.address) && config_.verifyEndpoints)
|
||||
{
|
||||
JLOG(m_journal.debug())
|
||||
<< beast::leftw(18) << "Endpoints drop " << ep.address << " as invalid";
|
||||
|
||||
@@ -11,16 +11,6 @@ Config::Config() : outPeers(calcOutPeers())
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(Config const& lhs, Config const& rhs)
|
||||
{
|
||||
return lhs.autoConnect == rhs.autoConnect && lhs.peerPrivate == rhs.peerPrivate &&
|
||||
lhs.wantIncoming == rhs.wantIncoming && lhs.inPeers == rhs.inPeers &&
|
||||
lhs.maxPeers == rhs.maxPeers && lhs.outPeers == rhs.outPeers &&
|
||||
lhs.features == rhs.features && lhs.ipLimit == rhs.ipLimit &&
|
||||
lhs.listeningPort == rhs.listeningPort;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
Config::calcOutPeers() const
|
||||
{
|
||||
@@ -56,6 +46,7 @@ Config::onWrite(beast::PropertyStream::Map& map) const
|
||||
map["port"] = listeningPort;
|
||||
map["features"] = features;
|
||||
map["ip_limit"] = ipLimit;
|
||||
map["verify_endpoints"] = verifyEndpoints;
|
||||
}
|
||||
|
||||
Config
|
||||
@@ -63,7 +54,8 @@ Config::makeConfig(
|
||||
xrpl::Config const& cfg,
|
||||
std::uint16_t port,
|
||||
bool validationPublicKey,
|
||||
int ipLimit)
|
||||
int ipLimit,
|
||||
bool verifyEndpoints)
|
||||
{
|
||||
PeerFinder::Config config;
|
||||
|
||||
@@ -116,6 +108,7 @@ Config::makeConfig(
|
||||
config.listeningPort = port;
|
||||
config.features = "";
|
||||
config.ipLimit = ipLimit;
|
||||
config.verifyEndpoints = verifyEndpoints;
|
||||
|
||||
// Enforce business rules
|
||||
config.applyTuning();
|
||||
|
||||
Reference in New Issue
Block a user