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
destinationmatches the device. The device enforces these on packets it receives. - Outbound view: the rules whose
sourcematches the device. These don't block anything. The device uses them to decide which peers to list inpeerlify list peers, to answerpeerlify pingandpeerlify 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:
- 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.)
- 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.
- Let replies through. Packets that belong to a connection already allowed are accepted without checking rules. See Replies.
- 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 itsprotocolandports. The first match decides:accept(orallow) admits the packet; any other action drops it. - 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:
| Protocol | What is admitted without a rule |
|---|---|
| TCP | Every segment except a connection request (a SYN without ACK). Only new connections are checked against rules. |
| UDP, SCTP | Packets 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. |
| ICMP | Echo 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,udpandicmpby name, any protocol number from1to255, 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
portsorprotocollist means*. An omitted or emptysourceordestinationlist means the rule matches nothing.
Fragments after the first fragment of a packet carry no port information and are always dropped.
Example
[
{ "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:adminsopening SSH to a web server matches rule 1 and is accepted. - A device tagged
scanneropening 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?
- 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 ACLand areason, for exampleno_matching_rule_default_deny, orDeny:<rule name>for an explicitdroprule. See Troubleshooting the client for where logs are kept. - Look at what each device holds.
peerlify aclsprints the device's inbound and outbound views exactly as it received them. - 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. - Check that the policy arrived. Until the device has its policy,
peerlify statusshows aPolicy:line readingnot received yet, and the device accepts nothing.