Incoming Handshake filtering based on firewall rules #1357
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request introduces a new feature to filter incoming handshakes on a node based on the configured firewall rules. When a node attempts to establish a handshake with another node, the receiving node will first utilize the newly implemented HandshakeFilter class to verify whether the initiating host has permission to access any of the ports permitted by the firewall. If the host does not have the necessary access, the handshake will be rejected. This mechanism effectively prevents nodes from establishing tunnels to other nodes without the appropriate resource access.
By implementing this feature, we reduce the potential resource consumption on both nodes that would otherwise be required to maintain unnecessary tunnels. Furthermore, this adds an additional security layer in front of the firewall, proactively blocking unauthorized access. It also mitigates the risk of compromised nodes attempting to overload other nodes in the network with packets that would ultimately be discarded by the firewall.
If enabled on a lighthouse, this feature restricts access to lighthouse functionality based on firewall rules. To limit access to the lighthouse, the feature must be enabled, and appropriate firewall rules must be added for the nodes that should have access. To allow access without opening any actual ports, I've added a new special port "nebula", similar to the fragment implementation. Equivalent considerations should be made before enabling the feature on relay nodes, as it can be used to restrict access to certain nodes. If enabled on a relay node, firewall rules must allow traffic for both ends of the relayed tunnel.
Config changes:
A new configuration value has been added within the Lighthouse section to enable this feature:
Example rule to allow only nebula access:
Implementation details:
When reading the firewall rules, the AddRule function of the HandshakeFilter class is invoked. This class stores a flattened representation of the firewall rules in hashmaps, allowing for faster lookups. During the processing of an incoming handshake in handshake_ix.go:ixHandshakeStage1, after verifying the usable addresses in the certificate, the method HandshakeFilter:IsHandshakeAllowed is called to validate the handshake.
If a node without access attempts to send packets, the receiving node's dropped packets metric will no longer increment, as the connection is blocked earlier. To address this, a new metric, "handshakes.filtered", has been introduced to track these incidents.
Additional notes:
I have opened an additional pull request titled "Lighthouse Host Query Filtering" which builds upon this PR. This new feature enables a node to send the flattened firewall rules to its lighthouses, allowing them to proactively prevent unauthorized nodes from obtaining connection details. This enhancement adds another layer of security, effectively mitigating the risks of IP address leaks and node enumeration attacks.