How rules are evaluated

Exactly how a device decides whether to accept a packet — which rules it holds, what counts as a reply, and how to find out why a connection was dropped.

Updated · ·By Ivan Vyshniak

Nothing on this page changes with your selection.

This page describes the decision a device makes for every packet it receives from a peer. Read How access control works first for the overview.

Each device holds two views of the policy

The control plane doesn't send the whole policy to every device. It sends each device two subsets:

  • Inbound view: the rules whose destination matches the device. The device enforces these on packets it receives.
  • Outbound view: the rules whose source matches the device. These don't block anything. The device uses them to decide which peers to list in peerlify list peers, to answer peerlify ping and peerlify acls --query. Which exit points a device may use comes from Access → Exit points, not from rules.

Rule order is preserved in both views. Disabled rules are included but skipped.

Person-based selectors (email:, group:, role:) are expanded into the matching devices before the views are sent. A device only ever sees device IDs, overlay IPs and tags.

What the receiving device does

For each packet that arrives from a peer, in order:

  1. Drop invalid traffic. Non-IPv4 packets, broadcast and multicast packets, and packets from outside the network's subnet are dropped. (Clients from 2.7.1 and earlier treat the subnet as a /24; see Network settings.)
  2. Check the sender. The packet's source address must belong to a current peer, and the packet must have arrived over that peer's encrypted session. A packet claiming another device's address is dropped.
  3. Let replies through. Packets that belong to a connection already allowed are accepted without checking rules. See Replies.
  4. Evaluate the rules. The device walks its inbound rules top to bottom, skipping disabled ones. A rule matches when the sender matches its source, and the packet's protocol and destination port match its protocol and ports. The first match decides: accept (or allow) admits the packet; any other action drops it.
  5. Deny by default. If no rule matches, the packet is dropped. A device that hasn't received any policy yet also drops everything.

Replies

Rules describe who may open a connection. Return traffic is handled as follows:

ProtocolWhat is admitted without a rule
TCPEvery segment except a connection request (a SYN without ACK). Only new connections are checked against rules.
UDP, SCTPPackets that answer a packet this device sent earlier: same protocol, with the source and destination addresses and ports reversed. The device remembers the most recent 512 such flows per network, and forgets them all whenever the rules change, or a peer joins, leaves, or changes its tags or address.
ICMPEcho replies and error messages (destination unreachable, time exceeded, parameter problem).

Two consequences:

  • An open TCP connection survives a policy change. Removing a rule stops new connections, not existing ones.
  • To be pinged, a device needs an inbound rule. An ICMP echo request is a new packet, not a reply. It matches a rule only if the rule's protocols include icmp (or *) and its ports are *.

How each field matches

  • Source: matched against the sender's overlay IP, device ID and tags. * matches any peer.
  • Protocol: tcp, udp and icmp by name, any protocol number from 1 to 255, or *. Names are case-insensitive. SCTP has no name: write "132".
  • Ports: compared with the destination port of TCP, UDP and SCTP packets. An entry can be a single port ("443"), an inclusive range ("8000-8999") or "*". Protocols without ports, such as ICMP, only match a rule whose ports include "*". A malformed entry, such as a reversed range or a value above 65535, matches nothing.
  • Omitted fields: an omitted or empty ports or protocol list means *. An omitted or empty source or destination list means the rule matches nothing.

Fragments after the first fragment of a packet carry no port information and are always dropped.

Example

rulesjson
[
  { "name": "Admins SSH anywhere", "action": "accept",
    "source": ["group:admins"], "destination": ["*"],
    "ports": ["22"], "protocol": ["tcp"] },

  { "name": "Block the scanner", "action": "drop",
    "source": ["tag:scanner"], "destination": ["*"],
    "ports": ["*"], "protocol": ["*"] },

  { "name": "Everyone reaches the web tier", "action": "accept",
    "source": ["*"], "destination": ["tag:web"],
    "ports": ["80", "443"], "protocol": ["tcp"] }
]
  • A laptop signed in by someone in group:admins opening SSH to a web server matches rule 1 and is accepted.
  • A device tagged scanner opening port 443 on a web server matches rule 2 and is dropped. Rule 3 is never reached.
  • Any other device opening port 443 on a web server matches rule 3 and is accepted.
  • Anything else, for example a web server opening SSH to an admin's laptop, matches nothing and is dropped.

If rule 3 were above rule 2, the scanner would be accepted on ports 80 and 443. Place narrow drop rules above the broad accept rules they carve out of.

Why was a connection dropped?

  1. Check the receiving device's log. The receiving device makes the decision. It logs each drop (throttled) with a line containing Dropped inbound packet by ACL and a reason, for example no_matching_rule_default_deny, or Deny:<rule name> for an explicit drop rule. See Troubleshooting the client for where logs are kept.
  2. Look at what each device holds. peerlify acls prints the device's inbound and outbound views exactly as it received them.
  3. Ask the sending device. peerlify acls --query=<peer> evaluates the sending device's outbound view. Treat its answer as a hint: it currently ignores the device's own tags and port ranges. Confirm by attempting the connection.
  4. Check that the policy arrived. Until the device has its policy, peerlify status shows a Policy: line reading not received yet, and the device accepts nothing.

Next steps

Was this page helpful?