Guide: deny rules
Invariant deny
rules are a powerful tool for enforcing your network security policy. They allow you to assert that specific types of traffic should never be successfully delivered between defined source and destination networks or locations.
Purpose of deny rules:
- Explicitly block unwanted or high-risk traffic flows.
- Enforce network segmentation and isolation between different security zones.
- Verify that decommissioned services are no longer accessible.
- Complement
critical-flow
rules (which assert reachability) anddeny-others
rules (which define an allow-list) by explicitly defining what must be forbidden.
How Invariant evaluates deny rules:
When Invariant evaluates a deny
rule, it exhaustively searches your network model for any possible path that would allow the specified traffic to be successfully delivered. If even one such path exists, Invariant flags a violation. This comprehensive check ensures that there are no unintended backdoors or misconfigurations that could compromise your security posture.
When to use deny rules:
- Broad Security Postures: To block all access from an untrusted zone (e.g., Guest Wi-Fi) to a sensitive internal zone (e.g., PCI Data).
- Specific Micro-segmentation: To prevent a particular server from communicating with another specific server on a certain port.
- Blocking Known Bad Traffic: To deny traffic to or from known malicious IP addresses or services.
- Validating Decommissions: After removing a service, use a deny rule to confirm it's truly inaccessible.
Execution Model
Understanding how Invariant processes deny rules involves several key steps:
-
Snapshot Processing: You begin by providing Invariant with a snapshot of your network. This includes:
- Device configurations (e.g., routers, switches, firewalls).
- Network and service definitions (typically in YAML files within the
def/
directory). - Your Invariant policy files, including deny rules (in
invariant/policies/
). Invariant uses this information, leveraging the underlying Batfish analysis engine, to build a comprehensive digital twin of your network.
-
Definition Resolution: Invariant resolves all named entities used in your rules:
- Network Names: (e.g.,
INTERNAL_DB_SUBNET
,UNTRUSTED_NETWORK
) are translated into specific IP addresses or CIDR blocks based on yourdef/networks.yaml
files. - Service Names: (e.g.,
SSH
,HTTPS
) are resolved to their corresponding protocols and port numbers fromdef/services.yaml
. - Location Names: (e.g.,
EXTERNAL_BOUNDARY_INTERFACES
) are mapped to specific device interfaces defined ininvariant/locations/
.
The resolution follows a precedence: definitions local to a rule (if applicable) > snapshot-local definitions (
def/
) > definitions installed with Invariant > built-in definitions (likeRFC1918
,ANY
). - Network Names: (e.g.,
-
Start Location Inference (for Egress Deny Rules): For
egress-deny
rules, Invariant needs to determine where the traffic originates:- If
source-interface
orenter-interface
is specified in the rule, Invariant uses those exact interfaces. - Otherwise, Invariant infers start locations based on the
source-address
. It identifies all interfaces whose configured IP addresses fall within thesource-address
range or whose primary network overlaps with it. The rule is then evaluated for traffic originating from these inferred interfaces.
For
ingress-deny
rules, theingress-network
policy field (specifically itsdestination-address
) defines the target network being protected. Invariant then considers traffic from the specifiedsource-address
(orANY
if unspecified) attempting to reach thisingress-network
. - If
-
Flow Search: This is the core of the evaluation. Invariant performs an exhaustive search across the digital twin. For a
deny
rule, it looks for any instance where a packet matching the rule's criteria (source/destination IP, port, protocol) successfully reaches its destination. -
Evidence Compilation & Output:
- Violation Found: If Invariant finds any successful path for the traffic defined in the
deny
rule, it's a violation.- The
policy_violations
report will list the failing rule. - The
policy_details
report will provide crucial evidence:- The specific violating flow (e.g., exact source/destination IPs and ports).
- A detailed virtual traceroute showing the successful path the packet took, including all hops, ACL decisions, and routing choices.
- The
- No Violation (Rule Passes): If the exhaustive search finds no way for the specified traffic to be delivered, the
deny
rule passes.- The rule will be listed in the
policy_ok
report.
- The rule will be listed in the
- Violation Found: If Invariant finds any successful path for the traffic defined in the
Writing Deny Rules
Deny rules are defined in YAML files within your invariant/policies/
directory, as part of an access-policy
.
Basic Structure:
access-policy:
- name: block-untrusted-to-internal-db
comment: "Prevent untrusted networks from accessing internal databases"
owner: security-team@example.com
# For an ingress-deny rule, ingress-network is the target being protected
ingress-network: INTERNAL_DB_SUBNET
rules:
- type: ingress-deny
comment: "Block any access from UNTRUSTED_NETWORK to internal DBs"
source-address: UNTRUSTED_NETWORK
# destination-address is implicitly INTERNAL_DB_SUBNET from the policy's ingress-network
# protocol and destination-port can be added for more specificity, e.g.:
# protocol: tcp
# destination-port: MYSQL_PORT
Ingress vs. Egress Deny Rules:
-
ingress-deny
: Use this to protect a destination network (defined in the policy'singress-network
) from unwanted incoming traffic.- Example: Deny any external traffic (e.g., from
EXTERNAL_LOCATION
) from reaching internal management interfaces (MGMT_SUBNET
).access-policy:
- name: protect-management-interfaces
ingress-network: MGMT_SUBNET
rules:
- type: ingress-deny
comment: "Block external access to management interfaces"
enter-interface: EXTERNAL_BOUNDARY_INTERFACES # Explicitly define entry point
# source-address defaults to ANY if not specified from external location
# destination-address is implicitly MGMT_SUBNET
- Example: Deny any external traffic (e.g., from
-
egress-deny
: Use this to prevent a source network (defined in the policy'segress-network
) from sending traffic to undesirable destinations.- Example: Deny internal servers (
INTERNAL_SERVERS_VLAN
) from initiating any connections to known malicious IP ranges (KNOWN_MALICIOUS_IPS
).access-policy:
- name: block-outbound-to-malicious
egress-network: INTERNAL_SERVERS_VLAN
rules:
- type: egress-deny
comment: "Prevent servers from contacting known malicious IPs"
# source-address is implicitly INTERNAL_SERVERS_VLAN
destination-address: KNOWN_MALICIOUS_IPS
- Example: Deny internal servers (
Specificity: Broad vs. Narrow Rules:
The granularity of your deny rules depends on your security objectives.
-
Broad Rules: Define general security boundaries and are excellent for establishing a baseline security posture.
- Example: Deny all traffic from the
GUEST_VLAN
to theCORP_NETWORK
.Or, equivalently, in a policy with# In a policy with ingress-network: CORP_NETWORK
- type: ingress-deny
comment: "Isolate Guest VLAN from Corporate Network"
source-address: GUEST_VLANegress-network: GUEST_VLAN
:# In a policy with egress-network: GUEST_VLAN
- type: egress-deny
comment: "Isolate Guest VLAN from Corporate Network"
destination-address: CORP_NETWORK
- Example: Deny all traffic from the
-
Narrow Rules: Target very specific protocols, ports, or subnets. Useful for highly targeted restrictions or blocking specific known vulnerabilities.
- Example: Deny Telnet access from any RFC1918 address to a group of
SENSITIVE_SERVERS
.# In a policy with ingress-network: SENSITIVE_SERVERS
- type: ingress-deny
comment: "Block Telnet to sensitive servers from internal networks"
source-address: RFC1918 # Built-in name for private IP space
destination-port: TELNET # Built-in service name for TCP/23
protocol: tcp
- Example: Deny Telnet access from any RFC1918 address to a group of
Choosing the right level of specificity is key. Start broad to establish major zone boundaries, then add narrower rules for specific risks or compliance requirements.
Understanding Violation Traceroutes
When a deny
rule is violated, Invariant provides a virtual traceroute in the policy_details
report. This traceroute is crucial because it shows exactly how the supposedly denied traffic managed to successfully reach its destination.
Accessing Traceroutes:
Use the Invariant CLI to view the details:
invariant show policy_details --json --snapshot <YOUR_SNAPSHOT_ID>
You'll then need to parse the JSON output, filtering for the specific rule that failed (e.g., by its policy.name
and rule.comment
).
Key JSON Fields in a Violation Traceroute:
-
flow
: This object describes the specific packet that constituted the violation. It includes:srcIp
,dstIp
: Source and Destination IP addresses.srcPort
,dstPort
: Source and Destination ports (for TCP/UDP).ipProtocol
: The IP protocol (e.g.,TCP
,UDP
,ICMP
).- Example:
"flow": {
"dscp": 0,
"dstIp": "10.1.1.5", // IP in INTERNAL_DB_SUBNET
"dstPort": 3306, // MYSQL_PORT
"ipProtocol": "TCP",
"srcIp": "192.168.100.20", // IP in UNTRUSTED_NETWORK
"srcPort": 54321,
"tcpFlagsSyn": 1, // Indicates a TCP SYN packet (connection initiation)
// ... other fields like icmpCode, icmpVar, packetLength etc.
}
-
start
: Indicates where this violating flow originated within the network model. This could be an interface on a device (e.g.,@enter(edge-router-01[GigabitEthernet0/0])
) or a modeled host. -
traces
: An array containing one or more paths the violating flow took. Often, there's just one trace, but multiple traces can appear if Equal-Cost Multi-Path (ECMP) routing is involved.disposition
: For adeny
rule violation, the disposition of the trace will beACCEPTED
(or another success-indicating status likeDELIVERED_TO_SUBNET
orEXITS_NETWORK
), signifying the traffic reached its destination.hops
: An array detailing each network device (hop) the packet traversed.node
: The hostname of the device.steps
: An array of processing steps the packet underwent on thisnode
. Each step has anaction
anddetail
:action: "RECEIVED"
: Packet arrived at an interface.detail.inputInterface
shows which one.action: "PERMITTED"
: Packet was allowed by a filter (ACL/firewall rule).detail.filter
gives the filter name.action: "FORWARDED"
: Packet was routed.detail.outputInterface
shows the egress interface,detail.resolvedNexthopIp
the next-hop IP, anddetail.routes
the routing table entry used.action: "TRANSFORMED"
: Packet was modified (e.g., by NAT).detail.transformationType
anddetail.flowDiffs
describe the change.action: "ACCEPTED"
(on the final hop): Packet delivered to an IP on the device itself or an attached host.
Interpreting the Path:
The traceroute allows you to pinpoint the misconfiguration:
- Permissive ACLs: Look for
PERMITTED
steps through ACLs or firewall policies that should have blocked the traffic. Thedetail.filter
field will name the culprit ACL. - Unexpected Routing: If the traffic takes an unusual path, bypassing intended security controls, examine the
FORWARDED
steps and thedetail.routes
to understand why that path was chosen. - NAT Issues: If NAT is involved (
TRANSFORMED
steps), ensure it's behaving as expected and not inadvertently allowing access.
Troubleshooting Deny Rule Violations
When a deny rule fails, follow these steps:
-
Verify Definitions:
- Are
source-address
,destination-address
,destination-port
, etc., in your rule resolving to the IP addresses, subnets, and services you intend? - Use
def/networks.yaml
anddef/services.yaml
to confirm. - The
resolved_as
field in thepolicy_details
output for the failing rule shows how Invariant interpreted your named definitions.
- Are
-
Analyze the Traceroute(s):
- Carefully examine each hop and step in the
traces
provided inpolicy_details
. - Identify any ACLs that
PERMITTED
the flow unexpectedly. - Note the routing decisions (
FORWARDED
steps) that led the packet along the violating path.
- Carefully examine each hop and step in the
-
Check Network Configurations:
- Based on the traceroute, inspect the actual configurations of the involved devices (routers, firewalls).
- Look for overly permissive ACL entries, incorrect routing policies, or NAT rules that might be causing the issue.
-
Refine the Invariant Rule:
- Too Broad? Is your deny rule so general that it's catching legitimate traffic that is correctly allowed by your network (and thus showing as a "violation" of your overly strict deny rule)? If so, make your deny rule more specific.
- Too Narrow? Is your deny rule too specific, missing the actual pattern of traffic that's getting through? Broaden its scope or add more specific deny rules.
- Adjust
source-address
,destination-address
,protocol
,destination-port
,enter-interface
etc., as needed to accurately reflect the traffic you intend to block.
-
Adjust Network Device Configuration:
- Modify the ACLs, routing policies, or firewall rules on the actual network devices to enforce the intended denial.
- Upload a new snapshot with these changes to Invariant and re-run the analysis to confirm the violation is resolved and no new issues have been introduced.
Next Steps
- Combine
deny
rules withcritical-flow
rules to ensure that while you block unwanted traffic, essential services remain accessible. - For a more comprehensive "default-deny" or "allow-list" security posture, explore using
deny-others
rules.
Potential Improvements (Self-Correction):
- The "Start Location Inference" section could be slightly more explicit for
ingress-deny
rules, emphasizing that theingress-network
defines the destination being protected, and Invariant considers sources defined bysource-address
(orANY
) orenter-interface
. Correction made in the generated MDX above. - A small, concrete example of a
def/networks.yaml
anddef/services.yaml
snippet alongside the basic rule structure could further clarify definition resolution. Added implicitly by using named definitions likeINTERNAL_DB_SUBNET
andSSH
which imply they come fromdef/
files. - The traceroute JSON example could be slightly more complete to show a few hops, but the current snippets are focused and serve their purpose.