Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add P2P security options #1764

Merged
merged 87 commits into from
Sep 12, 2022
Merged

Add P2P security options #1764

merged 87 commits into from
Sep 12, 2022

Conversation

jmjatlanta
Copy link
Contributor

@jmjatlanta jmjatlanta commented May 17, 2019

Fixes #659

This PR adds startup options (available via both command line and the config.ini configuration file) to witness_node:

  1. p2p-accept-incoming-connections will allow peers to request a connection to your node (default is true). Set to false, your node will not listen for incoming connections. The "accept-incoming-connections" is an existing field in the node configuration file (p2p/node_config.json), now accessible from the command line and the config.ini configuration file.
  2. p2p-inbound-endpoint, used to specify the node's "external" IP address and listening port when it is behind DNAT or a reverse proxy.
  3. p2p-connect-to-new-peers will allow the node to connect to new peers advertised by other peers (default is true). Set to false, the node will ignore all peer advertisements.
  4. p2p-advertise-peer-algorithm determines how peers are selected to be advertised.
  5. p2p-advertise-peer-endpoint and p2p-exclude-peer-endpoint work in conjunction with some of the peer algorithms.

The peer algorithms that can be used are:

  1. nothing which will respond to the requesting peer with an empty list
  2. list which will respond with a list of connected peers which are also in the list provided by p2p-advertise-peer-endpoint
  3. exclude_list which will respond with a list of connected peers which are not in the list provided by p2p-exclude-peer-endpoint
  4. all, or any other value, or if no peer algorithm is provided, all connected peers are advertised as they were before this enhancement.

Other changes and improvements:

  • Node will listen to the default port (1776) by default, rather than a random port. If p2p-endpoint option is not specified, when the default port is unavailable, the node will listen on a random port.
  • Node no longer performs firewall check requested by other peers, nor ask other peers to perform firewall check for itself or another peer. The node will perform firewall check / detection on its own on incoming peers.
  • Node will only accept an address_message if it has just requested one
  • Node only handles at most 200 addresses for each address_message
  • Added some gate-keeping code, to disconnect or ignore when received unexpected messages
  • Node will advertise other peers' inbound endpoints but not necessarily the remote endpoints of the current connections. If a peer's inbound port is 0, its address will still be advertised.
  • If node is not connected to any peer, it rechecks its seed node list every 5 minutes; otherwise it rechecks the seed node list every 1 hour (was always recheck every 3 hours)
  • Node will try to guess and verify the inbound peers' inbound (listening) endpoints
  • Peer's number_of_failed_connection_attempts will be halved on successful outbound connection
  • Refactored & optimized the network_mapper program
  • Added fc::ip::address::is_loopback_address() (127.*.*.*), fixed is_public_address() to detect loopback addresses

Copy link
Contributor

@pmconrad pmconrad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICS this resolves only the second point in #659 .
The first point (connect only to trusted peers) should be addressed, too.

libraries/app/application.cpp Outdated Show resolved Hide resolved
@jmjatlanta
Copy link
Contributor Author

jmjatlanta commented May 20, 2019

The first point (connect only to trusted peers) should be addressed, too.

I was thinking that listing seed_nodes, along with turning off accept_incoming_connections would keep you from connecting to others. But I forgot about the (possibly) existing connection database. So I will have to do something about that. Perhaps a parameter "clear-connection-db"

Other than the connection database, is there another way that connections are built? Do peers automatically ask each other for peers and attempt to connect? Or must they be prompted? I haven't looked, but will do so.

@abitmore
Copy link
Member

Do peers automatically ask each other for peers and attempt to connect? Or must they be prompted?

Peers do talk to each other about possible new peers and try to connect to each other. I don't remember whether one peer will ask other peers for more peers though.

@jmjatlanta
Copy link
Contributor Author

I can either add code to clear the database, or add code to not use it. Any opinion on which is better? I am thinking clearing the database is better. Who wants a stale database sitting around?

Or perhaps someone has a better idea to allow a node operator to only connect to the nodes he wants to.

@abitmore
Copy link
Member

The program will add new entries to the in-memory database when running, but not only load data when starting, so only clearing on start doesn't make much sense.

Actually we're digging into the details now. I think you can find more from the code.

IIRC, according to the p2p protocol, your connected peers may

  • tell you that there is a new peer, so you can connect to it when you want,
    • in this case your node should ignore it (don't add the new peer to internal db);
  • ask you to connect to another peer to detect if it's firewalled,
    • in this case, if you only connected to trusted nodes, I think the trusted nodes should not ask you to do such job;
  • ask you to send them a peer list,
    • trusted nodes should not do this as well.

@jmjatlanta
Copy link
Contributor Author

jmjatlanta commented May 20, 2019

IIRC, according to the p2p protocol, your connected peers may

* tell you that there is a new peer, so you can connect to it when you want,

I will add code to not connect if accept-incoming-connections is false.

* ask you to connect to another peer to detect if it's firewalled,

I will have to research if a response is required, or if I can simply ignore the request without consequences.

* ask you to send them a peer list,

That can now be controlled by the advertise-peer-list parameter.

ToDo:

  • Unit testing of on_address_message
  • Add logic to optionally ignore previous db

@abitmore
Copy link
Member

IIRC, according to the p2p protocol, your connected peers may

* tell you that there is a new peer, so you can connect to it when you want,

I will add code to not connect if accept-incoming-connections is false.

IMHO, these are outgoing connections but not incoming connections.

@pmconrad
Copy link
Contributor

I will add code to not connect if accept-incoming-connections is false.

Please use a different flag. These should be two distinct settings. (A node operator might want to have his own internal network of interconnected nodes that only connect to each other, and to some trusted public nodes.)

@jmjatlanta
Copy link
Contributor Author

jmjatlanta commented May 21, 2019

I will add code to not connect if accept-incoming-connections is false.

Please use a different flag. These should be two distinct settings. (A node operator might want to have his own internal network of interconnected nodes that only connect to each other, and to some trusted public nodes.)

How about a new parameter:

accept-connection-suggestions connect to nodes suggested by other nodes. Defaults to true.

@jmjatlanta
Copy link
Contributor Author

jmjatlanta commented May 21, 2019

I began to think about dropped connections to nodes. As it stands now, the parameters could be set up to where they will not get reconnected. I believe that if seed nodes are passed, and allow_incoming_connections is false, and accept-connection-suggestions is false, a reconnect cannot happen.

I believe that in such a situation, we must store the seed nodes (in memory?), and sort-of "replace" the currently implemented database of addresses with that list. That way reconnects (or perhaps initial connections) can happen if they are on the list.

As often happens, the implementation goes deeper than I expected. To make things clear, I will attempt to spec-out the parameters as I see how they should work, and let others review and adjust.

@jmjatlanta
Copy link
Contributor Author

Posted a spec here: #659 (comment)

Please comment there, we'll hammer out the details, and then I'll attempt to implement. Thanks all for the input!

Copy link
Member

@abitmore abitmore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a glance the code looks good. However the coding style is not the best, sometime indentation is 2, sometimes it's 3, sometimes it's 4.

tests/common/genesis_file_util.hpp Outdated Show resolved Hide resolved
libraries/net/node_impl.hxx Outdated Show resolved Hide resolved
libraries/net/node_impl.hxx Outdated Show resolved Hide resolved
libraries/net/node_impl.hxx Outdated Show resolved Hide resolved
@jmjatlanta
Copy link
Contributor Author

@abitmore thank you for the critiques. My apologies for the sloppy spacing. I believe I have corrected that and improved the readability of the code. No real functionality changes, the biggest change here is the moving of the node utility functions into its own file. Please scrutinize.

@jmjatlanta jmjatlanta requested a review from pmconrad July 5, 2019 14:43
libraries/net/include/graphene/net/node.hpp Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
libraries/net/include/graphene/net/node.hpp Outdated Show resolved Hide resolved
libraries/net/include/graphene/net/node.hpp Outdated Show resolved Hide resolved
libraries/net/include/graphene/net/node.hpp Outdated Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
libraries/net/include/graphene/net/node.hpp Outdated Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
tests/common/genesis_file_util.hpp Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
@jmjatlanta jmjatlanta added the 2d Developing Status indicating currently designing and developing a solution label Jul 8, 2019
libraries/app/application.cpp Outdated Show resolved Hide resolved
libraries/app/application.cpp Outdated Show resolved Hide resolved
libraries/net/include/graphene/net/node.hpp Outdated Show resolved Hide resolved
libraries/net/node.cpp Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
libraries/net/node.cpp Show resolved Hide resolved
libraries/net/node_impl.hxx Outdated Show resolved Hide resolved
libraries/net/include/graphene/net/node.hpp Outdated Show resolved Hide resolved
libraries/net/node_impl.hxx Outdated Show resolved Hide resolved
libraries/net/node.cpp Outdated Show resolved Hide resolved
@abitmore
Copy link
Member

I just noticed a thing: if a peer is in our exclude list, we shouldn't ask another peer to check this peer's firewall status, otherwise we'll expose this peer's address. Is this the current behavior?

@sonarcloud
Copy link

sonarcloud bot commented Sep 12, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 10 Code Smells

68.1% 68.1% Coverage
0.0% 0.0% Duplication

@abitmore abitmore merged commit 576bb78 into develop Sep 12, 2022
@abitmore abitmore deleted the jmj_659c branch September 12, 2022 05:49
@abitmore abitmore removed the 2d Developing Status indicating currently designing and developing a solution label Sep 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants