Skip to main content

Rules

Rules Files

Invariant will load and evaluate rules from YAML rules files found in your project directory. Rules can define traffic that should always be deliverable (critical flow rules) or never be deliverable (access policy rules) in your network.

Invariant rules files are YAML documents that conform to the specification on this page.

Overview

Invariant supports the following types of rules.

Rule typeDirectionDescription
ingress-critical-flowingressThis traffic should always be successfully delivered.
egress-critical-flowegress
ingress-denyingressThis traffic should never be successfully delivered.
egress-denyegress
ingress-deny-othersingressWithin a scope (e.g. TCP traffic), traffic should never be successfully delivered except where permitted.
egress-deny-othersegress

Invariant rules are organized into policies which target the same ‘ingress’ or ‘egress’ network.

Directory

Invariant expects rules files to be placed in the directory invariant/policies/ relative to your project directory.

Structure

File structure

Invariant rules files must contain a list of policy objects under the top-level key access-policy.

Policy structure

A policy is a named group of related rules which target the same ‘ingress’ or ‘egress’ network. Invariant rules must be placed inside a policy.

The following fields can appear in a policy.

FieldRequired?Description
nameYesAn identifier for this policy. Only characters -, _, A-Z, a-z, 0-9 are allowed.
commentNoA long description for this policy.
ownerNoAn email address or other identifier for the functional owner of this policy.
enforceNoA boolean which can mark the policy unenforced if set to false. Defaults to true. Rules in unenforced policies are still tested but any violations are reported in a separate list.
ingress-networkYes (exactly one)The target network for the rules in this policy. A policy must define ‘ingress-network’ or ‘egress-network’, never both.
egress-network
rulesYesThe list of rules in this policy.

Each policy has an inherent direction - ingress or egress - based on whether ingress-network or egress-network is specified. The rules in the policy must match it. So if the policy has ingress-network specified, only rules of type ‘ingress-critical-flow’, ‘ingress-deny’, and ‘ingress-deny-others’ should appear.

Network structure

A policy must have an ‘ingress-network’ or ‘egress-network’ and never both.

All rules in this policy must match the direction of the policy. A policy with ‘ingress-network’ defined may only contain ‘ingress’ rules. A policy with ‘egress-network’ defined may only contain ‘egress’ rules.

Both ‘ingress-network’ and ‘egress-network’ are typically specified as objects, but a shorthand version is available for both.

The following fields can appear in ‘ingress-network’.

FieldRequired?Description
destination-addressYes (at least one)Defines the ingress network IP space.
destination-excludeSubtracts from the ingress network IP space.

In shorthand mode, ‘ingress-network’ is specified as a CIDR, network name, or list of CIDRs and network names. This is exactly the same as providing destination-address. For example, the following policies are all identical.

access-policy:
- name: dmz-ingress
comment: example
owner: [email protected]
ingress-network:
destination-address: 195.1.1.160/27 195.1.1.192/26


access-policy:
- name: dmz-ingress
comment: example
owner: [email protected]
ingress-network: 195.1.1.160/27 195.1.1.192/26


access-policy:
- name: dmz-ingress
comment: example
owner: [email protected]
ingress-network:
- 195.1.1.160/27
- 195.1.1.192/26


### invariant/policies/dmz.yaml
access-policy:
- name: dmz-ingress
comment: example
owner: [email protected]
ingress-network: DMZ

### def/networks.yaml
networks:
DMZ:
values:
- address: 195.1.1.160/27
- address: 195.1.1.192/26

The following fields can appear in ‘egress-network’.

FieldRequired?Description
source-addressYes (at least one)Defines the network IP space.
source-excludeSubtracts from the network IP space.
enter-interfaceNoConsider traffic entering on these interfaces. Disables automatic interface selection.
source-interfaceNoConsider traffic originating from these interfaces. Disables automatic interface selection.

Similar to ‘ingress-network’, an ‘egress-network’ with only ‘source-address’ can be specified in shorthand mode.

access-policy:
- name: dmz-egress
comment: example
owner: [email protected]
egress-network:
source-address: DMZ


# Shorthand
access-policy:
- name: dmz-egress
comment: example
owner: [email protected]
egress-network: DMZ

Rule structure

Rules define testable statements about traffic that should always be deliverable (critical flow rules) or never be deliverable (access policy rules) in your network.

The permitted fields vary by the type of rule.

The following fields can appear in any rule.

FieldRequired?Description
typeYesThe type of this rule. Must be a valid Invariant rule type.
commentNoA long description for this rule.

The following fields can appear in rules with type ingress-critical-flow, egress-critical-flow, ingress-deny, egress-deny.

FieldRequired?Description
protocolNoThe space of possible protocol values for this traffic.
destination-addressNoThe space of possible IP address values for the destination-address field of this traffic.
destination-excludeNoExcludes IPs from the space of possible IP address values for the destination-address field of this traffic.
destination-portNoThe space of possible destination-port values for this traffic.
source-addressNoThe space of possible IP address values for the source-address field of this traffic.
source-excludeNoExcludes IPs from the space of possible IP address values for the source-address field of this traffic.
source-portNoThe space of possible source-port values for this traffic.
enter-interfaceNoConsider traffic entering on these interfaces. Disables automatic interface selection.
source-interfaceNoConsider traffic originating from these interfaces. Disables automatic interface selection.

Deny-others rules assert that no traffic should be deliverable to the target network except as permitted in the rule. These rules can be narrowed down using the ‘within’ section (typically these rules are narrowed by protocol at least).

The following fields can appear in rules with type ingress-deny-others, egress-deny-others.

FieldRequired?Description
withinNoNarrow the scope of this rule to within this traffic.
deny-all-exceptYesTraffic to or from the network should never be deliverable except as permitted in this section.

Inside of a deny-others rule the ‘deny-all-except’ section can contain exactly one field:

FieldRequired?Description
flowsYesTraffic that is permitted for this rule.

The ‘within’ field and ‘flows’ field both contain a list of traffic flows. Those flows are defined using the same fields as critical-flow and deny rules above. This includes fields like ‘destination-address’, ‘destination-exclude’, ‘source-address’, and so on.

access-policy:
- name: dmz-ingress
comment: example
owner: [email protected]
ingress-network: DMZ
rules:
- type: ingress-deny-others
comment: Limit SSH access to only from bastion network
within:
- protocol: TCP
destination-port: SSH
deny-all-except:
flows:
- comment: Internal SSH access
source-address: BASTION
destination-port: SSH
protocol: TCP

Field reference

Policy fields

The following fields can appear in a policy object.

name

Names the current policy. Only characters  -, _, A-Z, a-z, 0-9 are allowed.

comment

Describes the current policy.

Some best practices for the comment field:

  • All policies should use the comment field.
  • Include ticket references in the comment field if this policy was created or modified in response to a tracking ticket. This allows future users to understand the justification for the policy and confidently make changes to the network.

owner

Identifies the current owner of this policy.

Some best practices for the owner field:

  • The owner should be a primary contact who can comment on proposed changes to this policy.
  • Value should be an email address or other kind of identifier.

enforce

Mark the policy unenforced if set to false. Defaults to true.

Rules in unenforced policies are still tested but any violations are reported in a separate list.

ingress-network

Constrains the destination IP space the rules in this policy will apply to.

egress-network

Defines the source interfaces and source IP space the rules in this policy will apply to.

rules

The list of rules in this policy.

Rule fields

These fields can appear inside rules objects.

type

The type of this rule. Can be one of the following values.

  • ingress-critical-flow
  • egress-critical-flow
  • ingress-deny
  • egress-deny
  • ingress-deny-others
  • egress-deny-others

See Rule type reference for more information about each rule type.

within

Allowed only in deny-other rules. This constrains the scope of a deny-other rule using a list of traffic flows.

A simple way to think about ‘within’ is to look at a deny-other rule as a boolean expression.

IF traffic matches the network section

AND traffic matches the ‘within’ section

AND traffic is NOT in the ‘deny-all-except’ list

THEN the traffic is in violation of the rule.

Entries listed in the ‘within’ block are ‘OR’-ed together during rule evaluation.

deny-all-except

Allowed only in deny-other rules. This will define the only traffic that should be permitted for the target network (and within the scope of the ‘within’ section if provided).

It must contain an object with a single key, ‘flows’, which must contain a list of permitted traffic flows.

A simple way to think about deny-other rules is as a boolean expression.

IF traffic matches the network section

AND traffic matches the ‘within’ section

AND traffic is NOT in the ‘deny-all-except’ list

THEN the traffic is in violation of the rule.

Traffic flow fields

These fields can appear in several places:

  • Inside a critical-flow or deny rule.
  • Inside the ‘within’ section of a deny-other rule.
  • Inside the ‘deny-all-except’ section of a deny-other rule.
  • Inside the ‘ingress-network’ or ‘egress-network’ section of a policy (only certain fields are permitted in this case - see Network structure above).

Taken together these fields define traffic flows or classes of traffic.

Invariant thinks about traffic flows as a combination of the following:

  • Constraints on which interfaces to consider as points of ingress for the traffic.
  • Constraints on the packet field values.

We can categorize all of the fields in this section by whether they represent a constraint on packet field values (e.g. protocol) or a constraint on which interfaces to consider as points of ingress (enter-interface). Source-address / source-exclude and source-interface have the special property that they can create constraints on both.

These fields constrain packet field values only:

  • destination-address
  • destination-exclude
  • destination-port
  • source-port
  • protocol

These fields constrain which interfaces to consider as points of ingress only:

  • enter-interface

These fields can constrain both, depending on the situation:

  • source-address
  • source-exclude
  • source-interface

destination-address

Defines the space of possible IP address values for the destination-address field of this traffic.

If destination-exclude is also specified it will be subtracted from this IP space.

Acceptable values for destination-address are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

The following examples show different but equal ways to define destination-address as a list containing a /27 and a /26.

destination-address: 195.1.1.160/27 195.1.1.192/26


destination-address:
- 195.1.1.160/27
- 195.1.1.192/26


### invariant/policies/dmz.yaml
destination-address: DMZ

### def/networks.yaml
networks:
DMZ:
values:
- address: 195.1.1.160/27
- address: 195.1.1.192/26

destination-exclude

Excludes IPs from the space of possible IP address values for the destination-address field of this traffic.

If destination-address is not specified, destination-exclude is subtracted from the space of all IP addresses (0.0.0.0-255.255.255.255).

Acceptable values for destination-exclude are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

destination-port

Defines the space of possible values for the destination-port field of this traffic.

Acceptable values for destination-port are:

  • A string listing service names separated by a space (or a single service name).
  • A list of service names.

The destination-port field must agree with the protocol field. There are two agreement requirements:

  • All of the IP protocols specified must support the concept of a destination port if destination-port is specified.
  • All service names must be defined for all of the IP protocols specified.

To clarify this last point, it would be an error to create a rule that applies to MYSQL / UDP because the MYSQL service is defined only for TCP.

Invariant includes default definitions for many well-known ports. You can override these definitions or add your own custom service names. See well-known ports for a listing of default definitions and their values.

destination-port: HTTP HTTPS
protocol: tcp udp


destination-port:
- HTTP
- HTTPS
protocol: tcp udp


### invariant/policies/dmz.yaml
destination-port: HTTP
protocol: tcp udp

### def/services.yaml
services:
HTTP:
- port: 80
protocol: tcp
- port: 80
protocol: udp

source-port

Defines the space of possible values for the source-port field of this traffic.

See destination-port above for details.

protocol

Defines the possible IP protocol values for this traffic.

The protocol field must agree with the destination-port and source-port fields. There are two agreement requirements:

  • All of the IP protocols specified must support the concept of a port if destination-port or source-port is specified.
  • All service names must be defined for all of the IP protocols specified.

A list of all acceptable IP protocol names is given on the Batfish documentation site here: https://batfish.readthedocs.io/en/latest/specifiers.html#ip-protocol-names.

source-address

Defines the space of possible source-address IP address values for this traffic. Also defines the interfaces to use as points of ingress for this traffic if source-interface and enter-interface are not specified.

This field follows the same conventions as the destination-address field described above.

If source-exclude is specified it will be subtracted from this IP space.

Acceptable values for source-address are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

Invariant must decide on interfaces to use as points of ingress for each rule. Source-address is used to identify good points of ingress when source-interface and enter-interface are not specified. The procedure for ingress interface selection is this:

  • First subtract source-exclude from source-address if specified.
  • Locate all network interfaces where the assigned IP address falls inside the source address space.
  • Locate all network interfaces where the primary IP network intersects the source address space.

The rule evaluation proceeds with an appropriate subset of the source address space considered for the matched interface.

  • For an interface where the assigned IP address falls inside the source address space, the question will be evaluated for traffic exiting this interface with source-address restricted to the assigned IP.
  • For an interface where the primary IP network intersects the source address space, the question will be evaluated for traffic entering this interface with source-address restricted to the intersection of the primary network and original source address space.
  • An interface can be evaluated twice if it matches both categories.

If enter-interface is specified for this traffic, Invariant will look at traffic entering those interfaces. The entire source address space will be considered as possible for all interfaces. No dynamic ingress selection will occur.

Source-address and source-exclude are not allowed if source-interface is specified.

source-exclude

Excludes IPs from the space of possible IP address values for the source-address field of this traffic.

If source-address is not specified, source-exclude is subtracted from the space of all IP addresses (0.0.0.0-255.255.255.255).

Acceptable values for source-exclude are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

enter-interface

Consider traffic entering these interfaces.

All possible IP address values for source-address will be considered for each interface.

Enter-interface is useful for looking at spoofed, reflected, or one-way traffic. For example, if you have a part of your network that is especially untrusted (e.g. guest network, vendor network), you may want to write a rule that says traffic entering from certain interfaces should not be permitted to reach sensitive resources, even if the source of the traffic is a device generating malicious packets with spoofed source IP addresses.

Acceptable values are:

  • A string listing one or more location names separated by spaces.
  • A list of location names.

Location names are names that can resolve to specific interfaces. They are defined by placing a YAML file in the ‘invariant/locations/’ folder.

An example location which selects the GigabitEthernet0/1 interface on all edge routers might look like this.

### In invariant/locations/edge.yaml
locations:
EDGE_TO_INTERNET:
- devices: border-.*
interfaces: GigabitEthernet0/0

The following example shows two cases where enter-interface can be useful. Both cases use a scenario where we want our egress policy for the client VLANs to consider spoofed source addresses. The first policy approaches the problem by asserting that it applies to all traffic entering from the client network - regardless of source address. The second policy approaches the problem by creating a stand-alone policy which asserts that spoofed source IPs are always dropped, so that other policies do not need to worry about spoofed traffic.

access-policy:
- name: client-egress
comment: |
This policy asserts that traffic entering the CLIENT_BORDER interfaces can reach
only necessary resources on the network. It targets the CLIENT_BORDER interfaces
directly to ensure the policy applies even to spoofed source addresses.
owner: [email protected]
egress-network:
enter-interface: CLIENT_BORDER
rules:
- type: ingress-deny-others
comment: Limit TCP/UDP access to DMZ network, external only
within:
- protocol: TCP UDP
deny-all-except:
flows:
- comment: Client - DMZ
destination-address: DMZ
destination-port: HTTP HTTPS SSH
- comment: Client - NTP
destination-address: NTP
destination-port: NTP
- comment: Client - DNS
destination-address: DNS
destination-port: DNS
- comment: Client - External
destination-exclude: RFC1918 DMZ

- name: client-nospoof-egress
comment: |
This policy targets spoofed traffic entering the CLIENT_BORDER interfaces.
It asserts that spoofed traffic is always dropped. With this policy in place
we can safely create a normal egress policy that uses source-address: CLIENT_VLANS.
owner: [email protected]
egress-network:
enter-interface: CLIENT_BORDER
source-exclude: CLIENT_VLANS
rules:
- type: ingress-deny
comment: Assert all spoofed traffic is dropped
destination-address: ANY


### In invariant/locations/client.yaml
locations:
CLIENT_BORDER:
- devices: asa-1
interfaces: GigabitEthernet0/1 GigabitEthernet0/3

### def/networks.yaml
networks:
CLIENT_VLANS:
values:
- address: 192.172.0.0/14

source-interface

Consider traffic exiting these interfaces with source IP addresses matching each interface.

Source-interface cannot be used in combination with enter-interface or source-address (or source-exclude).

Acceptable values are:

  • A string listing one or more location names separated by spaces.
  • A list of location names.

Locations

The fields ‘enter-interface’ and ‘source-interface’ expect named locations. This section explains how named locations work and how to create them.

Overview

Named locations are essentially selectors for interfaces in your network.

Invariant will search for YAML files containing named location definitions in the ‘invariant/locations’ directory relative to the project root.

For example, CLIENT_BORDER here refers to two interfaces on device ‘asa-1’.

locations:
CLIENT_BORDER:
- devices: asa-1
interfaces: GigabitEthernet0/1 GigabitEthernet0/3

Locations can use wildcards. In this example, EDGE_TO_INTERNET addresses interface GigabitEthernet0/0 on all devices with name matching “border-.*”.

locations:
EDGE_TO_INTERNET:
- devices: border-.*
interfaces: GigabitEthernet0/0

Locations can be built up from other locations. We can define a new location, UNTRUSTED_INGRESS, to represent all boundary interfaces where high-risk traffic will enter the network. UNTRUSTED_INGRESS will use references to include all interfaces selected by CLIENT_BORDER or EDGE_TO_INTERNET.

locations:
UNTRUSTED_INGRESS:
- name: CLIENT_BORDER
- name: EDGE_TO_INTERNET
EDGE_TO_INTERNET:
- devices: border-.*
interfaces: GigabitEthernet0/0
CLIENT_BORDER:
- devices: asa-1
interfaces: GigabitEthernet0/1 GigabitEthernet0/3

It can be helpful to think about these selectors as a boolean expression. For example, UNTRUSTED_INGRESS would be defined as:

All interfaces with:

  • Device name matching “border-.*”some text
    • AND interface name equal to GigabitEthernet0/0
  • OR
  • Device name equal to “asa-1”some text
    • AND interface name equal tosome text
      • GigabitEthernet0/1
      • OR
      • GigabitEthernet0/3

Location file directory

Invariant expects named locations to be defined in YAML files located in the directory invariant/locations/ relative to your project directory.

Location file structure

Location definition files must contain a mapping from location names to location definitions under the top-level key locations.

Location definition structure

A named location is defined using a list of selector objects. The location includes all interfaces matched by any of its selector objects.

The following fields can appear in a selector object.

FieldRequired?Description
devicesNoThe device name must match. Can be an exact match or wildcard.
interfacesNoThe interface name must match. Can be an exact match or wildcard.
vrfsNoThe interface VRF name must match. Can be an exact match or wildcard. The default VRF is named “default”.
zonesNoThe interface must belong to a matching zone (for devices with zones). Can be an exact match or wildcard.
ipsNoThe interface primary assigned IP must fall inside this CIDR or named network.
nameNoInclude all interfaces in another named location.

Location selector field reference

devices

Selects within devices (nodes) with matching names.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. ., [a-z][a-z] .

interfaces

Selects within interfaces with matching names.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. ., [a-z][a-z] .

vrfs

Selects within interfaces with matching VRF name.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. ., [a-z][a-z] .

You may wish to examine the ‘interface_properties’ report in Invariant to get a sense of what VRF name is assigned to what interface. Interfaces are typically assigned to a VRF named ‘default’ when no VRF is explicitly associated.

zones

Selects within interfaces belonging to a zone with matching name.

This applies only to devices and nodes that support zones.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. ., [a-z][a-z] .

ips

Selects within interfaces where the primary assigned IP is inside this CIDR or named network.

For example, if we have the primary address of the interfaces pointed towards the internet on our edge routers tagged in our IPAM as “EDGE_TO_INTERNET” we can import that tag as a network name and use it here.

We might write a small python script to generate (or re-generate) network names from IPAM tags.

# In scripts/regenerate_ipam_networks.py
import sys
import yaml

def regenerate_networks_from_ipam_tags():
ipam_tags = fetch_all_ipam_tags()
# ipam_tags is like [{"name": "EDGE_TO_INTERNET", "ips": ["195.24.14.185", "195.24.14.187"]}]
ipam_defs = {}
for tag in ipam_tags:
ipam_defs[tag.name] = {
"values": [{"address": ip} for ip in tag.ips]
}
yaml.safe_dump(ipam_defs, sys.stdout)

if __name__ == "__main__":
regenerate_networks_from_ipam_tags()

Then we can run the script periodically.

python scripts/regenerate_ipam_networks.py > def/generated_ipam_networks.yaml

Now we can create a policy which looks at traffic entering from the internet based on that IPAM label.

### In invariant/locations/edge.yaml
locations:
EDGE_TO_INTERNET:
- ips: EDGE_TO_INTERNET

### In invariant/policies/edge.yaml
access-policy:
- name: internet-ingress
comment: |
This policy asserts that traffic entering the EDGE_TO_INTERNET interfaces can reach
only necessary resources on the network. It targets the EDGE_TO_INTERNET interfaces
directly to ensure the policy applies even to spoofed source addresses.
owner: [email protected]
ingress-network:
enter-interface: EDGE_TO_INTERNET
rules:
- type: ingress-deny-others
comment: Limit from-internet TCP/UDP access to specific DMZ services
within:
- protocol: TCP UDP
deny-all-except:
flows:
- comment: Internet - DMZ web servers
destination-address: DMZ_WEB_SERVERS
destination-port: HTTP HTTPS

name

Include all interfaces that match another named location.

A selector containing the name field must be its own list item.

locations:
UNTRUSTED_INGRESS:
- name: CLIENT_BORDER
- name: EDGE_TO_INTERNET

Rule type reference

ingress-critical-flow

Asserts that a traffic flow will always be delivered. Specifically this rule looks for any possible way a packet could be rejected, dropped, or fail to route within this class of traffic.

Example:

access-policy:
- name: dmz-ingress
comment: |
This policy asserts that the DMZ network makes some services available to the internet.
owner: [email protected]
ingress-network: DMZ
rules:
- type: ingress-critical-flow
comment: Ensure public HTTP/HTTPS access to DMZ resources
protocol: TCP UDP
destination-port: HTTP HTTPS

egress-critical-flow

Identical to ingress-critical-flow. Asserts that a traffic flow will always be delivered. Specifically this rule looks for any possible way a packet could be rejected, dropped, or fail to route within this class of traffic.

Examples:

access-policy:
- name: basic-internet-access
comment: |
This policy asserts that some basic internet access (egress) is expected for the target networks.
owner: [email protected]
egress-network:
- DMZ
- VLAN30
- CLIENT_VLANS
rules:
- type: egress-critical-flow
comment: Ensure access to 1.1.1.1, 8.8.8.8 etc
protocol: TCP UDP
destination-address: GOOGLE_DNS CLOUDFLARE_DNS LEVEL3_DNS
destination-port: DNS

- name: dmz-access-needed
comment: |
This policy encodes critical dependencies for the DMZ network
owner: [email protected]
egress-network: DMZ
rules:
- type: egress-critical-flow
comment: Ensure DMZ servers can send telemetry into the protected SEC_LOGS network
protocol: TCP UDP
destination-address: SEC_LOGS
destination-port: HTTPS

ingress-deny

Asserts that a traffic flow can never be successfully delivered. Specifically this rule looks for any possible way a packet could be successfully delivered within this class of traffic.

Example:

access-policy:
- name: ingress-no-ssh
comment: |
This blanket policy asserts SSH access is denied for any traffic entering from the internet.
owner: [email protected]
ingress-network: RFC1918 DMZ
rules:
- type: ingress-deny
comment: Ensure public SSH access is denied
protocol: TCP UDP
enter-interface: EDGE_FROM_INTERNET
destination-port: SSH

egress-deny

Identical to ingress-deny. Asserts that a traffic flow can never be successfully delivered. Specifically this rule looks for any possible way a packet could be successfully delivered within this class of traffic.

Example:

access-policy:
- name: egress-malicious-nets
comment: |
This blanket policy asserts outbound access is denied to certain malicious networks.
owner: [email protected]
egress-network: RFC1918
rules:
- type: egress-deny
comment: Ensure outbound access to malicious networks is not allowed
protocol: TCP UDP
destination-address: MALICIOUS_PUBLIC_IPS

ingress-deny-others

Asserts that traffic can never be successfully delivered to the target network except for specific permitted flows. This rule looks for any possible way a forbidden packet could be successfully delivered.

The optional ‘within’ field restricts the scope of the rule. Although the field is optional, almost all deny-others rules will need to be restricted by protocol. There are two reasons for this:

  • Not all IP protocols support the concept of ports. Rules that use destination-port or source-port need to use ‘within’ to restrict the rule scope to IP protocols that support ports (e.g. TCP, UDP).
  • Many users are focused on TCP, UDP access policy and are not prepared to establish policy for other IP protocols.

When reasoning about deny-others rules it can be helpful to treat the rule as a boolean expression:

IF traffic matches the network section

AND traffic matches the ‘within’ section

AND traffic is NOT in the ‘deny-all-except’ list

THEN the traffic is in violation of the rule.

Example:

access-policy:
- name: dmz-ingress
comment: example
owner: [email protected]
ingress-network: DMZ
rules:
- type: ingress-deny-others
comment: Limit SSH access to only from bastion network
within:
- protocol: TCP
destination-port: SSH
deny-all-except:
flows:
- comment: Internal SSH access
source-address: BASTION
destination-port: SSH
protocol: TCP

egress-deny-others

Identical to ingress-deny-others. Asserts that traffic can never be successfully delivered to the target network except for specific permitted flows. This rule looks for any possible way a forbidden packet could be successfully delivered.

See ingress-deny-others for more information.

Example:

access-policy:
- name: client-egress
comment: |
This policy asserts that traffic entering the CLIENT_BORDER interfaces can reach
only necessary resources on the network. It targets the CLIENT_BORDER interfaces
directly to ensure the policy applies even to spoofed source addresses.
owner: [email protected]
egress-network:
enter-interface: CLIENT_BORDER
rules:
- type: ingress-deny-others
comment: Limit TCP/UDP access to DMZ network, external only
within:
- protocol: TCP UDP
deny-all-except:
flows:
- comment: Client - DMZ
destination-address: DMZ
destination-port: HTTP HTTPS SSH
- comment: Client - NTP
destination-address: NTP
destination-port: NTP
- comment: Client - DNS
destination-address: DNS
destination-port: DNS
- comment: Client - External
destination-exclude: RFC1918 DMZ