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

Incoming Handshake filtering based on firewall rules #1357

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jampe
Copy link
Contributor

@jampe jampe commented Mar 19, 2025

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:

# This feature allows handshakes only from hosts whose hostname, groups, or IP address are specified in
# any inbound firewall rule. By doing so, it prevents unauthorized nodes from establishing a tunnel, conserving
# resources on the host and adding an additional security layer that reduces the potential attack surface.
# - If enabled on a lighthouse, this will prevent nodes from accessing lighthouse features unless there is an
#   incoming rule allowing access. Use allow rules with `port: nebula` to grant access to nodes.
# - Similar considerations should be made before enabling the feature on relay nodes, as it can restrict
#   access to certain nodes only. Both ends of the relayed tunnel must be allowed to communicate with this node
#   for relaying to function.
#incoming_handshake_filtering: false

Example rule to allow only nebula access:

  inbound:
    # Allow lighthouse access for all nodes in EU datacenter
    - port: nebula
      proto: any
      groups:
        - datacenter-eu
        - webservers

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.

@jampe jampe changed the title implement incoming handshake filtering Incoming Handshake filtering based on firewall rules Mar 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant