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. |
True |
||
filters |
Specifier for filters to test. |
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. |
True |
||
filters |
Only evaluate filters that match this specifier. |
True |
||
headers |
Packet header constraints on the flows being searched. |
True |
||
action |
The behavior that you want evaluated. Specify exactly one of |
str |
True |
|
startLocation |
Only consider specified locations as possible sources. |
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 |
|
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. |
True |
||
filters |
Only consider filters that match this specifier. |
True |
||
headers |
Packet header constraints. |
False |
||
startLocation |
Location to start tracing from. |
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 |
|
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. |
True |
||
filters |
Specifier for filters to check. |
True |
||
headers |
Packet header constraints for which to find matching filter lines. |
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. |
True |
||
nodes |
Only evaluate nodes matching this specifier. |
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