Access-lists and firewall rules

This category of questions allows you to analyze the behavior of access control lists and firewall rules. It also allows you to comprehensively validate (aka verification) that some traffic is or is not allowed.

Filter Line Reachability

Returns unreachable lines in filters (ACLs and firewall rules).

Finds all lines in the specified filters that will not match any packet, either because of being shadowed by prior lines or because of its match condition being empty.

Inputs

Name

Description

Type

Optional

Default Value

nodes

Examine filters on nodes matching this specifier.

NodeSpec

True

filters

Specifier for filters to test.

FilterSpec

True

ignoreComposites

Whether to ignore filters that are composed of multiple filters defined in the configs.

bool

True

False

Invocation

[5]:
result = bf.q.filterLineReachability().answer().frame()

Return Value

Name

Description

Type

Sources

Filter sources

List of str

Unreachable_Line

Filter line that cannot be matched (i.e., unreachable)

str

Unreachable_Line_Action

Action performed by the unreachable line (e.g., PERMIT or DENY)

str

Blocking_Lines

Lines that, when combined, cover the unreachable line

List of str

Different_Action

Whether unreachable line has an action different from the blocking line(s)

bool

Reason

The reason a line is unreachable

str

Additional_Info

Additional information

str

Print the first 5 rows of the returned Dataframe

[6]:
result.head(5)
[6]:
Sources Unreachable_Line Unreachable_Line_Action Blocking_Lines Different_Action Reason Additional_Info
0 ['as2dept1: RESTRICT_HOST_TRAFFIC_OUT'] deny ip 1.128.0.0 0.0.255.255 2.128.0.0 0.0.255.255 DENY ['permit ip any 2.128.0.0 0.0.255.255'] True BLOCKING_LINES None
1 ['as2dept1: RESTRICT_HOST_TRAFFIC_IN'] permit icmp any any PERMIT ['deny ip any any'] True BLOCKING_LINES None

Print the first row of the returned Dataframe

[7]:
result.iloc[0]
[7]:
Sources                                  ['as2dept1: RESTRICT_HOST_TRAFFIC_OUT']
Unreachable_Line           deny   ip 1.128.0.0 0.0.255.255 2.128.0.0 0.0.255.255
Unreachable_Line_Action                                                     DENY
Blocking_Lines                           ['permit ip any 2.128.0.0 0.0.255.255']
Different_Action                                                            True
Reason                                                            BLOCKING_LINES
Additional_Info                                                             None
Name: 0, dtype: object

Search Filters

Finds flows for which a filter takes a particular behavior.

This question searches for flows for which a filter (access control list) has a particular behavior. The behaviors can be: that the filter permits the flow (permit), that it denies the flow (deny), or that the flow is matched by a particular line (matchLine <lineNumber>). Filters are selected using node and filter specifiers, which might match multiple filters. In this case, a (possibly different) flow will be found for each filter.

Inputs

Name

Description

Type

Optional

Default Value

nodes

Only evaluate filters present on nodes matching this specifier.

NodeSpec

True

filters

Only evaluate filters that match this specifier.

FilterSpec

True

headers

Packet header constraints on the flows being searched.

HeaderConstraints

True

action

The behavior that you want evaluated. Specify exactly one of permit, deny, or matchLine <line number>.

str

True

startLocation

Only consider specified locations as possible sources.

LocationSpec

True

invertSearch

Search for packet headers outside the specified headerspace, rather than inside the space.

bool

True

Invocation

[10]:
result = bf.q.searchFilters(headers=HeaderConstraints(srcIps='10.10.10.0/24', dstIps='218.8.104.58', applications = ['dns']), action='deny', filters='acl_in').answer().frame()

Return Value

Name

Description

Type

Node

Node

str

Filter_Name

Filter name

str

Flow

Evaluated flow

Flow

Action

Outcome

str

Line_Content

Line content

str

Trace

ACL trace

List of TraceTree

Print the first 5 rows of the returned Dataframe

[11]:
result.head(5)
[11]:
Node Filter_Name Flow Action Line_Content Trace
0 rtr-with-acl acl_in start=rtr-with-acl [10.10.10.42:49152->218.8.104.58:53 UDP] DENY 460 deny udp 10.10.10.42/32 218.8.104.58/32 eq domain - Matched line 460 deny udp 10.10.10.42/32 218.8.104.58/32 eq domain

Print the first row of the returned Dataframe

[12]:
result.iloc[0]
[12]:
Node                                                                    rtr-with-acl
Filter_Name                                                                   acl_in
Flow                     start=rtr-with-acl [10.10.10.42:49152->218.8.104.58:53 UDP]
Action                                                                          DENY
Line_Content                   460 deny udp 10.10.10.42/32 218.8.104.58/32 eq domain
Trace           - Matched line 460 deny udp 10.10.10.42/32 218.8.104.58/32 eq domain
Name: 0, dtype: object

Test Filters

Returns how a flow is processed by a filter (ACLs, firewall rules).

Shows how the specified flow is processed through the specified filters, returning its permit/deny status as well as the line(s) it matched.

Inputs

Name

Description

Type

Optional

Default Value

nodes

Only examine filters on nodes matching this specifier.

NodeSpec

True

filters

Only consider filters that match this specifier.

FilterSpec

True

headers

Packet header constraints.

HeaderConstraints

False

startLocation

Location to start tracing from.

LocationSpec

True

Invocation

[15]:
result = bf.q.testFilters(headers=HeaderConstraints(srcIps='10.10.10.1', dstIps='218.8.104.58', applications = ['dns']), nodes='rtr-with-acl', filters='acl_in').answer().frame()

Return Value

Name

Description

Type

Node

Node

str

Filter_Name

Filter name

str

Flow

Evaluated flow

Flow

Action

Outcome

str

Line_Content

Line content

str

Trace

ACL trace

List of TraceTree

Print the first 5 rows of the returned Dataframe

[16]:
result.head(5)
[16]:
Node Filter_Name Flow Action Line_Content Trace
0 rtr-with-acl acl_in start=rtr-with-acl [10.10.10.1:49152->218.8.104.58:53 UDP] PERMIT 660 permit udp 10.10.10.0/24 218.8.104.58/32 eq domain - Matched line 660 permit udp 10.10.10.0/24 218.8.104.58/32 eq domain

Print the first row of the returned Dataframe

[17]:
result.iloc[0]
[17]:
Node                                                                     rtr-with-acl
Filter_Name                                                                    acl_in
Flow                       start=rtr-with-acl [10.10.10.1:49152->218.8.104.58:53 UDP]
Action                                                                         PERMIT
Line_Content                   660 permit udp 10.10.10.0/24 218.8.104.58/32 eq domain
Trace           - Matched line 660 permit udp 10.10.10.0/24 218.8.104.58/32 eq domain
Name: 0, dtype: object

Find Matching Filter Lines

Returns lines in filters (ACLs and firewall rules) that match any packet within the specified header constraints.

Finds all lines in the specified filters that match any packet within the specified header constraints.

Inputs

Name

Description

Type

Optional

Default Value

nodes

Examine filters on nodes matching this specifier.

NodeSpec

True

filters

Specifier for filters to check.

FilterSpec

True

headers

Packet header constraints for which to find matching filter lines.

HeaderConstraints

True

action

Show filter lines with this action. By default returns lines with either action.

str

True

ignoreComposites

Whether to ignore filters that are composed of multiple filters defined in the configs.

bool

True

False

Invocation

[20]:
result = bf.q.findMatchingFilterLines(headers=HeaderConstraints(applications='DNS')).answer().frame()

Return Value

Name

Description

Type

Node

Node

str

Filter

Filter name

str

Line

Line text

str

Line_Index

Index of line

int

Action

Action performed by the line (e.g., PERMIT or DENY)

str

Print the first 5 rows of the returned Dataframe

[21]:
result.head(5)
[21]:
Node Filter Line Line_Index Action
0 as1border1 101 permit ip host 1.0.1.0 host 255.255.255.0 0 PERMIT
1 as1border1 101 permit ip host 1.0.2.0 host 255.255.255.0 1 PERMIT
2 as1border1 102 permit ip host 2.0.0.0 host 255.0.0.0 0 PERMIT
3 as1border1 102 permit ip host 2.128.0.0 host 255.255.0.0 1 PERMIT
4 as1border1 103 permit ip host 3.0.1.0 host 255.255.255.0 0 PERMIT

Print the first row of the returned Dataframe

[22]:
result.iloc[0]
[22]:
Node                                         as1border1
Filter                                              101
Line          permit ip host 1.0.1.0 host 255.255.255.0
Line_Index                                            0
Action                                           PERMIT
Name: 0, dtype: object

Check SNMP Community Clients

Checks if an SNMP community permits specified client IPs.

This question checks if the specified SNMP community permits the specified client IPs on specified devices. It reports if any device does not have the community or the set of permitted client IPs by the community does not match those specified in the question. If the community exists and permits exactly the specified client IPs, the device is not included in the output. The question currently only supports Arista, Cisco-NXOS, and Juniper devices. For all others, it will report an UNSUPPORTED_DEVICE status in the output.

Inputs

Name

Description

Type

Optional

Default Value

community

The SNMP community to consider.

str

False

clients

Client IPs expected to be permitted.

IpSpec

True

nodes

Only evaluate nodes matching this specifier.

NodeSpec

True

Invocation

[25]:
result = bf.q.snmpCommunityClients(community='COMM', clients='1.2.3.4/32').answer().frame()

Return Value

Name

Description

Type

Node

Hostname.

str

Community

The community name.

str

Reason

Result of the test.

str

Print the first 5 rows of the returned Dataframe

[26]:
result.head(5)
[26]:
Node Community Reason
0 arista COMM UNEXPECTED_CLIENTS
1 ios COMM UNSUPPORTED_DEVICE

Print the first row of the returned Dataframe

[27]:
result.iloc[0]
[27]:
Node                     arista
Community                  COMM
Reason       UNEXPECTED_CLIENTS
Name: 0, dtype: object