summaryrefslogtreecommitdiff
path: root/net-p2p/monero/files/monero-9999-net-enable-IPv6-by-default.patch
blob: 73841edc0ec1f8ddcff831e2b28661bfd3f638cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
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"