summaryrefslogtreecommitdiff
path: root/net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch
diff options
context:
space:
mode:
authorBertrand Jacquin <bertrand@jacquin.bzh>2024-04-09 22:47:23 +0100
committerBertrand Jacquin <bertrand@jacquin.bzh>2024-04-09 23:05:23 +0100
commitab4f187397accc65b0f5fedf5d01f0412415dd27 (patch)
tree8c7f2d5425ab20ecd7384898fc7f5c914d5670b2 /net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch
parentnet-p2p/monero: add 9999 (diff)
downloadportage-ab4f187397accc65b0f5fedf5d01f0412415dd27.tar.xz
net-p2p/monero: enable ipv6 by default
Diffstat (limited to '')
-rw-r--r--net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch496
1 files changed, 496 insertions, 0 deletions
diff --git a/net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch b/net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch
new file mode 100644
index 00000000..73841edc
--- /dev/null
+++ b/net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch
@@ -0,0 +1,496 @@
+From 8fa4962ae12329fa0965e80b5f945eb2ada63b0e Mon Sep 17 00:00:00 2001
+From: Bertrand Jacquin <bertrand@jacquin.bzh>
+Date: Sun, 17 Jul 2022 23:52:34 +0100
+Subject: [PATCH] net: enable IPv6 by default
+
+As of 2024-04-01, IPv6 represents ~43% of traffic entering Google with
+up to 75% is some country, and in generally more available when IPv6 was
+introduced in Monero in 2019 as part of 155475d97196 ("Add IPv6
+support").
+
+Monero overall has a very low presence over IPv6 which in part can be
+explained from the fact that IPv6 need to be specifically enabled before
+it is used and often requires nodes to be manually added in
+configuration.
+
+This commit enabled IPv6 by default for both RPC and P2P as an attempt
+to improve Monero network mesh diversity.
+
+The change has been tested in a lot of different scenario: IPv4 only,
+IPv6 only, IPv4+IPv6, IPv4+IPv6 with broken/invalid IPv4 system
+configuration, IPv4+IPv6 with broken/invalid IPv6 system configuration.
+
+* --p2p-use-ipv6 is now deprecated and has no effect
+* --p2p-ignore-ipv6 is introduced to ignore unsuccessful IPv6 P2P binding
+* --rpc-use-ipv6 is now deprecated and has no effect
+* --rpc-ignore-ipv6 is introduced to ignore unsuccessful IPv6 RPC binding
+
+See: https://github.com/monero-project/monero/issues/8818
+See: https://www.google.com/intl/en/ipv6/statistics.html
+See: https://www.vyncke.org/ipv6status/
+---
+ .../epee/include/net/abstract_tcp_server2.h | 8 +-
+ .../epee/include/net/abstract_tcp_server2.inl | 78 ++++++++++---------
+ .../epee/include/net/http_server_impl_base.h | 6 +-
+ src/p2p/net_node.cpp | 3 +-
+ src/p2p/net_node.h | 11 +--
+ src/p2p/net_node.inl | 18 +++--
+ src/rpc/core_rpc_server.cpp | 2 +-
+ src/rpc/rpc_args.cpp | 13 +++-
+ src/rpc/rpc_args.h | 5 +-
+ src/wallet/wallet_rpc_server.cpp | 2 +-
+ utils/fish/monero-wallet-rpc.fish | 2 +-
+ utils/fish/monerod.fish | 4 +-
+ 12 files changed, 85 insertions(+), 67 deletions(-)
+
+diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h
+index ece9c1d1337f..1858df9e9064 100644
+--- a/contrib/epee/include/net/abstract_tcp_server2.h
++++ b/contrib/epee/include/net/abstract_tcp_server2.h
+@@ -343,10 +343,10 @@ namespace net_utils
+ void create_server_type_map();
+
+ bool init_server(uint32_t port_ipv4, const std::string& address_ipv4 = "0.0.0.0",
+- uint32_t port_ipv6 = 0, const std::string& address_ipv6 = "::", bool use_ipv6 = false, bool require_ipv4 = true,
++ uint32_t port_ipv6 = 0, const std::string& address_ipv6 = "::", bool require_ipv6 = true, bool require_ipv4 = true,
+ ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect);
+ bool init_server(const std::string port_ipv4, const std::string& address_ipv4 = "0.0.0.0",
+- const std::string port_ipv6 = "", const std::string address_ipv6 = "::", bool use_ipv6 = false, bool require_ipv4 = true,
++ const std::string port_ipv6 = "", const std::string address_ipv6 = "::", bool require_ipv6 = true, bool require_ipv4 = true,
+ ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect);
+
+ /// Run the server's io_service loop.
+@@ -473,7 +473,7 @@ namespace net_utils
+ /// Handle completion of an asynchronous accept operation.
+ void handle_accept_ipv4(const boost::system::error_code& e);
+ void handle_accept_ipv6(const boost::system::error_code& e);
+- void handle_accept(const boost::system::error_code& e, bool ipv6 = false);
++ void handle_accept(const boost::system::error_code& e, bool ipv6 = true);
+
+ bool is_thread_worker();
+
+@@ -502,7 +502,7 @@ namespace net_utils
+ uint32_t m_port_ipv6;
+ std::string m_address_ipv4;
+ std::string m_address_ipv6;
+- bool m_use_ipv6;
++ bool m_require_ipv6;
+ bool m_require_ipv4;
+ std::string m_thread_name_prefix; //TODO: change to enum server_type, now used
+ size_t m_threads_count;
+diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
+index a9409baf5ae1..cb25d1eb25b0 100644
+--- a/contrib/epee/include/net/abstract_tcp_server2.inl
++++ b/contrib/epee/include/net/abstract_tcp_server2.inl
+@@ -1179,7 +1179,7 @@ namespace net_utils
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
+ bool boosted_tcp_server<t_protocol_handler>::init_server(uint32_t port_ipv4, const std::string& address_ipv4,
+- uint32_t port_ipv6, const std::string& address_ipv6, bool use_ipv6, bool require_ipv4,
++ uint32_t port_ipv6, const std::string& address_ipv6, bool require_ipv6, bool require_ipv4,
+ ssl_options_t ssl_options)
+ {
+ TRY_ENTRY();
+@@ -1188,7 +1188,7 @@ namespace net_utils
+ m_port_ipv6 = port_ipv6;
+ m_address_ipv4 = address_ipv4;
+ m_address_ipv6 = address_ipv6;
+- m_use_ipv6 = use_ipv6;
++ m_require_ipv6 = require_ipv6;
+ m_require_ipv4 = require_ipv4;
+
+ if (ssl_options)
+@@ -1229,43 +1229,45 @@ namespace net_utils
+ }
+ }
+
+- if (use_ipv6)
++ try
+ {
+- try
+- {
+- if (port_ipv6 == 0) port_ipv6 = port_ipv4; // default arg means bind to same port as ipv4
+- boost::asio::ip::tcp::resolver resolver(io_service_);
+- boost::asio::ip::tcp::resolver::query query(address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::query::canonical_name);
+- boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
+- acceptor_ipv6.open(endpoint.protocol());
++ if (port_ipv6 == 0) port_ipv6 = port_ipv4; // default arg means bind to same port as ipv4
++ boost::asio::ip::tcp::resolver resolver(io_service_);
++ boost::asio::ip::tcp::resolver::query query(address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::query::canonical_name);
++ boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
++ acceptor_ipv6.open(endpoint.protocol());
+ #if !defined(_WIN32)
+- acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
++ acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ #endif
+- acceptor_ipv6.set_option(boost::asio::ip::v6_only(true));
+- acceptor_ipv6.bind(endpoint);
+- acceptor_ipv6.listen();
+- boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_ipv6.local_endpoint();
+- m_port_ipv6 = binded_endpoint.port();
+- MDEBUG("start accept (IPv6)");
+- new_connection_ipv6.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, m_state->ssl_options().support));
+- acceptor_ipv6.async_accept(new_connection_ipv6->socket(),
+- boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
+- boost::asio::placeholders::error));
+- }
+- catch (const std::exception &e)
+- {
+- ipv6_failed = e.what();
+- }
++ acceptor_ipv6.set_option(boost::asio::ip::v6_only(true));
++ acceptor_ipv6.bind(endpoint);
++ acceptor_ipv6.listen();
++ boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_ipv6.local_endpoint();
++ m_port_ipv6 = binded_endpoint.port();
++ MDEBUG("start accept (IPv6)");
++ new_connection_ipv6.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, m_state->ssl_options().support));
++ acceptor_ipv6.async_accept(new_connection_ipv6->socket(),
++ boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
++ boost::asio::placeholders::error));
++ }
++ catch (const std::exception &e)
++ {
++ ipv6_failed = e.what();
+ }
+
+- if (use_ipv6 && ipv6_failed != "")
++ if (ipv6_failed != "")
++ {
++ MERROR("Failed to bind IPv6: " << ipv6_failed);
++ if (require_ipv6)
+ {
+- MERROR("Failed to bind IPv6: " << ipv6_failed);
+- if (ipv4_failed != "")
+- {
+- throw std::runtime_error("Failed to bind IPv4 and IPv6");
+- }
++ throw std::runtime_error("Failed to bind IPv6 (set to required)");
+ }
++ }
++
++ if (ipv4_failed != "" && ipv6_failed != "")
++ {
++ throw std::runtime_error("Failed to bind IPv4 and IPv6");
++ }
+
+ return true;
+ }
+@@ -1283,7 +1285,7 @@ namespace net_utils
+ //-----------------------------------------------------------------------------
+ template<class t_protocol_handler>
+ bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port_ipv4, const std::string& address_ipv4,
+- const std::string port_ipv6, const std::string address_ipv6, bool use_ipv6, bool require_ipv4,
++ const std::string port_ipv6, const std::string address_ipv6, bool require_ipv6, bool require_ipv4,
+ ssl_options_t ssl_options)
+ {
+ uint32_t p_ipv4 = 0;
+@@ -1298,7 +1300,7 @@ namespace net_utils
+ MERROR("Failed to convert port no = " << port_ipv6);
+ return false;
+ }
+- return this->init_server(p_ipv4, address_ipv4, p_ipv6, address_ipv6, use_ipv6, require_ipv4, std::move(ssl_options));
++ return this->init_server(p_ipv4, address_ipv4, p_ipv6, address_ipv6, require_ipv6, require_ipv4, std::move(ssl_options));
+ }
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
+@@ -1389,7 +1391,7 @@ namespace net_utils
+ {
+ //some problems with the listening socket ?..
+ _dbg1("Net service stopped without stop request, restarting...");
+- if(!this->init_server(m_port_ipv4, m_address_ipv4, m_port_ipv6, m_address_ipv6, m_use_ipv6, m_require_ipv4))
++ if(!this->init_server(m_port_ipv4, m_address_ipv4, m_port_ipv6, m_address_ipv6, m_require_ipv6, m_require_ipv4))
+ {
+ _dbg1("Reiniting service failed, exit.");
+ return false;
+@@ -1682,7 +1684,7 @@ namespace net_utils
+ }
+ catch (const boost::system::system_error& e)
+ {
+- if (!m_use_ipv6 || (resolve_error != boost::asio::error::host_not_found &&
++ if (!m_require_ipv6 || (resolve_error != boost::asio::error::host_not_found &&
+ resolve_error != boost::asio::error::host_not_found_try_again))
+ {
+ throw;
+@@ -1699,7 +1701,7 @@ namespace net_utils
+ boost::asio::ip::tcp::resolver::iterator end;
+ if(iterator == end)
+ {
+- if (!m_use_ipv6)
++ if (!m_require_ipv6)
+ {
+ _erro("Failed to resolve " << adr);
+ return false;
+@@ -1807,7 +1809,7 @@ namespace net_utils
+ }
+ catch (const boost::system::system_error& e)
+ {
+- if (!m_use_ipv6 || (resolve_error != boost::asio::error::host_not_found &&
++ if (!m_require_ipv6 || (resolve_error != boost::asio::error::host_not_found &&
+ resolve_error != boost::asio::error::host_not_found_try_again))
+ {
+ throw;
+diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h
+index 94d519716918..b617952f3846 100644
+--- a/contrib/epee/include/net/http_server_impl_base.h
++++ b/contrib/epee/include/net/http_server_impl_base.h
+@@ -57,7 +57,7 @@ namespace epee
+ {}
+
+ bool init(std::function<void(size_t, uint8_t*)> rng, const std::string& bind_port = "0", const std::string& bind_address_ipv4 = "0.0.0.0",
+- const std::string& bind_address_ipv6 = "::", bool use_ipv6 = false, bool require_ipv4 = true,
++ const std::string& bind_address_ipv6 = "::", bool require_ipv6 = true, bool require_ipv4 = true,
+ std::vector<std::string> access_control_origins = std::vector<std::string>(),
+ boost::optional<net_utils::http::login> user = boost::none,
+ net_utils::ssl_options_t ssl_options = net_utils::ssl_support_t::e_ssl_support_autodetect)
+@@ -77,11 +77,11 @@ namespace epee
+ m_net_server.get_config_object().m_user = std::move(user);
+
+ MGINFO("Binding on " << bind_address_ipv4 << " (IPv4):" << bind_port);
+- if (use_ipv6)
++ if (require_ipv6)
+ {
+ MGINFO("Binding on " << bind_address_ipv6 << " (IPv6):" << bind_port);
+ }
+- bool res = m_net_server.init_server(bind_port, bind_address_ipv4, bind_port, bind_address_ipv6, use_ipv6, require_ipv4, std::move(ssl_options));
++ bool res = m_net_server.init_server(bind_port, bind_address_ipv4, bind_port, bind_address_ipv6, require_ipv6, require_ipv4, std::move(ssl_options));
+ if(!res)
+ {
+ LOG_ERROR("Failed to bind server");
+diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp
+index 4d5ba6e38268..5ac484ea7b77 100644
+--- a/src/p2p/net_node.cpp
++++ b/src/p2p/net_node.cpp
+@@ -159,7 +159,8 @@ namespace nodetool
+
+ const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
+ const command_line::arg_descriptor<std::string> arg_igd = {"igd", "UPnP port mapping (disabled, enabled, delayed)", "delayed"};
+- const command_line::arg_descriptor<bool> arg_p2p_use_ipv6 = {"p2p-use-ipv6", "Enable IPv6 for p2p", false};
++ const command_line::arg_descriptor<bool> arg_p2p_use_ipv6 = {"p2p-use-ipv6", "DEPRECATED, ignored", false};
++ const command_line::arg_descriptor<bool> arg_p2p_ignore_ipv6 = {"p2p-ignore-ipv6", "Ignore unsuccessful IPv6 bind for p2p", false};
+ const command_line::arg_descriptor<bool> arg_p2p_ignore_ipv4 = {"p2p-ignore-ipv4", "Ignore unsuccessful IPv4 bind for p2p", false};
+ const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max number of out peers", -1};
+ const command_line::arg_descriptor<int64_t> arg_in_peers = {"in-peers", "set max number of in peers", -1};
+diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
+index 4db6a107ca0a..b0218baf1b73 100644
+--- a/src/p2p/net_node.h
++++ b/src/p2p/net_node.h
+@@ -375,11 +375,11 @@ namespace nodetool
+ bool is_peer_used(const peerlist_entry& peer);
+ bool is_peer_used(const anchor_peerlist_entry& peer);
+ bool is_addr_connected(const epee::net_utils::network_address& peer);
+- void add_upnp_port_mapping_impl(uint32_t port, bool ipv6=false);
++ void add_upnp_port_mapping_impl(uint32_t port, bool ipv6=true);
+ void add_upnp_port_mapping_v4(uint32_t port);
+ void add_upnp_port_mapping_v6(uint32_t port);
+- void add_upnp_port_mapping(uint32_t port, bool ipv4=true, bool ipv6=false);
+- void delete_upnp_port_mapping_impl(uint32_t port, bool ipv6=false);
++ void add_upnp_port_mapping(uint32_t port, bool ipv4=true, bool ipv6=true);
++ void delete_upnp_port_mapping_impl(uint32_t port, bool ipv6=true);
+ void delete_upnp_port_mapping_v4(uint32_t port);
+ void delete_upnp_port_mapping_v6(uint32_t port);
+ void delete_upnp_port_mapping(uint32_t port);
+@@ -457,7 +457,7 @@ namespace nodetool
+ bool m_hide_my_port;
+ igd_t m_igd;
+ bool m_offline;
+- bool m_use_ipv6;
++ bool m_require_ipv6;
+ bool m_require_ipv4;
+ std::atomic<bool> is_closing;
+ std::unique_ptr<boost::thread> mPeersLoggerThread;
+@@ -527,7 +527,8 @@ namespace nodetool
+ extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_ipv6_port;
+ extern const command_line::arg_descriptor<std::string> arg_p2p_bind_port; // DEPRECATED
+ extern const command_line::arg_descriptor<std::string> arg_p2p_bind_port_ipv6; // DEPRECATED
+- extern const command_line::arg_descriptor<bool> arg_p2p_use_ipv6;
++ extern const command_line::arg_descriptor<bool> arg_p2p_use_ipv6; // DEPRECATED
++ extern const command_line::arg_descriptor<bool> arg_p2p_ignore_ipv6;
+ extern const command_line::arg_descriptor<bool> arg_p2p_ignore_ipv4;
+ extern const command_line::arg_descriptor<uint32_t> arg_p2p_external_port;
+ extern const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip;
+diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
+index f357c6037800..09dead8a7691 100644
+--- a/src/p2p/net_node.inl
++++ b/src/p2p/net_node.inl
+@@ -106,7 +106,8 @@ namespace nodetool
+ command_line::add_arg(desc, arg_p2p_bind_ipv6_port, false);
+ command_line::add_arg(desc, arg_p2p_bind_port, false); // DEPRECATED
+ command_line::add_arg(desc, arg_p2p_bind_port_ipv6, false); // DEPRECATED
+- command_line::add_arg(desc, arg_p2p_use_ipv6);
++ command_line::add_arg(desc, arg_p2p_use_ipv6); // DEPRECATED
++ command_line::add_arg(desc, arg_p2p_ignore_ipv6);
+ command_line::add_arg(desc, arg_p2p_ignore_ipv4);
+ command_line::add_arg(desc, arg_p2p_external_port);
+ command_line::add_arg(desc, arg_p2p_allow_local_ip);
+@@ -471,8 +472,13 @@ namespace nodetool
+ return false;
+ }
+ m_offline = command_line::get_arg(vm, cryptonote::arg_offline);
+- m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
++ m_require_ipv6 = !command_line::get_arg(vm, arg_p2p_ignore_ipv6);
+ m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4);
++
++ // DEPRECATED --p2p-use-ipv6
++ if (command_line::get_arg(vm, arg_p2p_use_ipv6))
++ MWARNING("--p2p-use-ipv6 is now DEPRECATED and has no effect");
++
+ public_zone.m_notifier = cryptonote::levin::notify{
+ public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core()
+ };
+@@ -1012,20 +1018,20 @@ namespace nodetool
+ std::string ipv6_port = "";
+ zone.second.m_net_server.set_connection_filter(this);
+ MINFO("Binding (IPv4) on " << zone.second.m_bind_ipv4_address << ":" << zone.second.m_port_ipv4);
+- if (!zone.second.m_bind_ipv6_address.empty() && m_use_ipv6)
++ if (!zone.second.m_bind_ipv6_address.empty() && m_require_ipv6)
+ {
+ ipv6_addr = zone.second.m_bind_ipv6_address;
+ ipv6_port = zone.second.m_port_ipv6;
+ MINFO("Binding (IPv6) on " << zone.second.m_bind_ipv6_address << ":" << zone.second.m_port_ipv6);
+ }
+- res = zone.second.m_net_server.init_server(zone.second.m_port_ipv4, zone.second.m_bind_ipv4_address, ipv6_port, ipv6_addr, m_use_ipv6, m_require_ipv4, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
++ res = zone.second.m_net_server.init_server(zone.second.m_port_ipv4, zone.second.m_bind_ipv4_address, ipv6_port, ipv6_addr, m_require_ipv6, m_require_ipv4, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
+ CHECK_AND_ASSERT_MES(res, false, "Failed to bind server");
+ }
+ }
+
+ m_listening_port_ipv4 = public_zone.m_net_server.get_binded_port_ipv4();
+ MLOG_GREEN(el::Level::Info, "Net service bound (IPv4) to " << public_zone.m_bind_ipv4_address << ":" << m_listening_port_ipv4);
+- if (m_use_ipv6)
++ if (m_require_ipv6)
+ {
+ m_listening_port_ipv6 = public_zone.m_net_server.get_binded_port_ipv6();
+ MLOG_GREEN(el::Level::Info, "Net service bound (IPv6) to " << public_zone.m_bind_ipv6_address << ":" << m_listening_port_ipv6);
+@@ -1037,7 +1043,7 @@ namespace nodetool
+ if(m_igd == igd)
+ {
+ add_upnp_port_mapping_v4(m_listening_port_ipv4);
+- if (m_use_ipv6)
++ if (m_require_ipv6)
+ {
+ add_upnp_port_mapping_v6(m_listening_port_ipv6);
+ }
+diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
+index 0ce1346cc49d..642c8a790562 100644
+--- a/src/rpc/core_rpc_server.cpp
++++ b/src/rpc/core_rpc_server.cpp
+@@ -399,7 +399,7 @@ namespace cryptonote
+ auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
+ const bool inited = epee::http_server_impl_base<core_rpc_server, connection_context>::init(
+ rng, std::move(port), std::move(bind_ipv4_str),
+- std::move(bind_ipv6_str), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4),
++ std::move(bind_ipv6_str), std::move(rpc_config->require_ipv6), std::move(rpc_config->require_ipv4),
+ std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options)
+ );
+
+diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
+index 4d0411b503d5..8ca7e5c7ad9f 100644
+--- a/src/rpc/rpc_args.cpp
++++ b/src/rpc/rpc_args.cpp
+@@ -95,7 +95,8 @@ namespace cryptonote
+ , rpc_restricted_bind_ipv4_address({"rpc-restricted-bind-ipv4-address", rpc_args::tr("Specify IPv4 address to bind restricted RPC server"), "127.0.0.1"})
+ , rpc_restricted_bind_ipv6_address({"rpc-restricted-bind-ipv6-address", rpc_args::tr("Specify IPv6 address to bind restricted RPC server"), "::1"})
+ , rpc_restricted_bind_ip({"rpc-restricted-bind-ip", rpc_args::tr("DEPRECATED: replaced with --rpc-restricted-bind-ipv4-address"), ""})
+- , rpc_use_ipv6({"rpc-use-ipv6", rpc_args::tr("Allow IPv6 for RPC"), false})
++ , rpc_use_ipv6({"rpc-use-ipv6", rpc_args::tr("DEPRECATED, ignored"), false})
++ , rpc_ignore_ipv6({"rpc-ignore-ipv6", rpc_args::tr("Ignore unsuccessful IPv6 bind for RPC"), false})
+ , rpc_ignore_ipv4({"rpc-ignore-ipv4", rpc_args::tr("Ignore unsuccessful IPv4 bind for RPC"), false})
+ , rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
+ , confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ipv4-address value is NOT a loopback (local) IP")})
+@@ -121,7 +122,8 @@ namespace cryptonote
+ command_line::add_arg(desc, arg.rpc_restricted_bind_ipv4_address);
+ command_line::add_arg(desc, arg.rpc_restricted_bind_ipv6_address);
+ command_line::add_arg(desc, arg.rpc_restricted_bind_ip); // DEPRECATED
+- command_line::add_arg(desc, arg.rpc_use_ipv6);
++ command_line::add_arg(desc, arg.rpc_use_ipv6); // DEPRECATED
++ command_line::add_arg(desc, arg.rpc_ignore_ipv6);
+ command_line::add_arg(desc, arg.rpc_ignore_ipv4);
+ command_line::add_arg(desc, arg.rpc_login);
+ command_line::add_arg(desc, arg.confirm_external_bind);
+@@ -159,8 +161,13 @@ namespace cryptonote
+ if (config.restricted_bind_ipv4_address.empty())
+ config.restricted_bind_ipv4_address = command_line::get_arg(vm, arg.rpc_restricted_bind_ip);
+
+- config.use_ipv6 = command_line::get_arg(vm, arg.rpc_use_ipv6);
++ config.require_ipv6 = !command_line::get_arg(vm, arg.rpc_ignore_ipv6);
+ config.require_ipv4 = !command_line::get_arg(vm, arg.rpc_ignore_ipv4);
++
++ // DEPRECATED --rpc-use-ipv6
++ if (command_line::get_arg(vm, arg.rpc_use_ipv6))
++ MWARNING("--rpc-use-ipv6 is now DEPRECATED and has no effect");
++
+ config.disable_rpc_ban = command_line::get_arg(vm, arg.disable_rpc_ban);
+ if (!config.bind_ipv4_address.empty())
+ {
+diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h
+index 392e78703839..ea3cad8b3381 100644
+--- a/src/rpc/rpc_args.h
++++ b/src/rpc/rpc_args.h
+@@ -57,7 +57,8 @@ namespace cryptonote
+ const command_line::arg_descriptor<std::string> rpc_restricted_bind_ipv4_address;
+ const command_line::arg_descriptor<std::string> rpc_restricted_bind_ipv6_address;
+ const command_line::arg_descriptor<std::string> rpc_restricted_bind_ip; // DEPRECATED
+- const command_line::arg_descriptor<bool> rpc_use_ipv6;
++ const command_line::arg_descriptor<bool> rpc_use_ipv6; // DEPRECATED
++ const command_line::arg_descriptor<bool> rpc_ignore_ipv6;
+ const command_line::arg_descriptor<bool> rpc_ignore_ipv4;
+ const command_line::arg_descriptor<std::string> rpc_login;
+ const command_line::arg_descriptor<bool> confirm_external_bind;
+@@ -87,7 +88,7 @@ namespace cryptonote
+ std::string bind_ipv6_address;
+ std::string restricted_bind_ipv4_address;
+ std::string restricted_bind_ipv6_address;
+- bool use_ipv6;
++ bool require_ipv6;
+ bool require_ipv4;
+ std::vector<std::string> access_control_origins;
+ boost::optional<tools::login> login; // currently `boost::none` if unspecified by user
+diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
+index f5e3c4b4e861..616930421ec3 100644
+--- a/src/wallet/wallet_rpc_server.cpp
++++ b/src/wallet/wallet_rpc_server.cpp
+@@ -281,7 +281,7 @@ namespace tools
+ auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); };
+ return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(
+ rng, std::move(bind_port), std::move(rpc_config->bind_ipv4_address),
+- std::move(rpc_config->bind_ipv6_address), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4),
++ std::move(rpc_config->bind_ipv6_address), std::move(rpc_config->require_ipv6), std::move(rpc_config->require_ipv4),
+ std::move(rpc_config->access_control_origins), std::move(http_login),
+ std::move(rpc_config->ssl_options)
+ );
+diff --git a/utils/fish/monero-wallet-rpc.fish b/utils/fish/monero-wallet-rpc.fish
+index c06f01b0352a..5633de534e0b 100644
+--- a/utils/fish/monero-wallet-rpc.fish
++++ b/utils/fish/monero-wallet-rpc.fish
+@@ -38,7 +38,7 @@ complete -c monero-wallet-rpc -l rpc-bind-ipv4-address -r -d "Specify IPv4 addre
+ complete -c monero-wallet-rpc -l rpc-bind-ipv6-address -r -d "Specify IPv6 address to bind RPC server. Default: ::1"
+ complete -c monero-wallet-rpc -l rpc-restricted-bind-ipv4-address -r -d "Specify IPv4 address to bind restricted RPC server. Default: 127.0.0.1"
+ complete -c monero-wallet-rpc -l rpc-restricted-bind-ipv6-address -r -d "Specify IPv6 address to bind restricted RPC server. Default: ::1"
+-complete -c monero-wallet-rpc -l rpc-use-ipv6 -d "Allow IPv6 for RPC"
++complete -c monero-wallet-rpc -l rpc-ignore-ipv6 -d "Ignore unsuccessful IPv6 bind for RPC"
+ complete -c monero-wallet-rpc -l rpc-ignore-ipv4 -d "Ignore unsuccessful IPv4 bind for RPC"
+ complete -c monero-wallet-rpc -l rpc-login -r -d "Specify username[:password] required for RPC server"
+ complete -c monero-wallet-rpc -l confirm-external-bind -d "Confirm rpc-bind-ipv4-address value is NOT a loopback (local) IP"
+diff --git a/utils/fish/monerod.fish b/utils/fish/monerod.fish
+index 9080d47b3636..2a0ff04628f0 100644
+--- a/utils/fish/monerod.fish
++++ b/utils/fish/monerod.fish
+@@ -58,7 +58,7 @@ complete -c monerod -l p2p-bind-ipv4-address -r -d "Interface for p2p network pr
+ complete -c monerod -l p2p-bind-ipv6-address -r -d "Interface for p2p network protocol (IPv6). Default: ::"
+ complete -c monerod -l p2p-bind-ipv4-port -r -d "Port for p2p network protocol (IPv4). Default: 18080, 28080 if 'testnet', 38080 if 'stagenet'"
+ complete -c monerod -l p2p-bind-ipv6-port -d "Port for p2p network protocol (IPv6). Default: 18080, 28080 if 'testnet', 38080 if 'stagenet'"
+-complete -c monerod -l p2p-use-ipv6 -d "Enable IPv6 for p2p"
++complete -c monerod -l p2p-ignore-ipv6 -d "Ignore unsuccessful IPv6 bind for p2p"
+ complete -c monerod -l p2p-ignore-ipv4 -d "Ignore unsuccessful IPv4 bind for p2p"
+ complete -c monerod -l p2p-external-port -r -d "External port for p2p network protocol (if port forwarding used with NAT). Default: 0"
+ complete -c monerod -l allow-local-ip -d "Allow local ip add to peer list, mostly in debug purposes"
+@@ -92,7 +92,7 @@ complete -c monerod -l rpc-bind-ipv4-address -r -d "Specify IPv4 address to bind
+ complete -c monerod -l rpc-bind-ipv6-address -r -d "Specify IPv6 address to bind RPC server. Default: ::1"
+ complete -c monerod -l rpc-restricted-bind-ipv4-address -r -d "Specify IPv4 address to bind restricted RPC server. Default: 127.0.0.1"
+ complete -c monerod -l rpc-restricted-bind-ipv6-address -r -d "Specify IPv6 address to bind restricted RPC server. Default: ::1"
+-complete -c monerod -l rpc-use-ipv6 -d "Allow IPv6 for RPC"
++complete -c monerod -l rpc-ignore-ipv6 -d "Ignore unsuccessful IPv6 bind for RPC"
+ complete -c monerod -l rpc-ignore-ipv4 -d "Ignore unsuccessful IPv4 bind for RPC"
+ complete -c monerod -l rpc-login -d "Specify username[:password] required for RPC server"
+ complete -c monerod -l confirm-external-bind -d "Confirm rpc-bind-ipv4-address value is NOT a loopback (local) IP"