Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ To detect the error before deploying the buggy configuration to the network, the
```
batfish> get bgpAdvertisements differential=true

+ EBGP\_SENT dstIp:192.168.51.2 **srcNode:as65000\_R1** srcIp:192.168.51.1 **net:10.1.1.0/24** nhip:192.168.51.1 origin:INCOMPLETE asPath:\[65000, 65001\] communities:\[4259840002, 4259840010\] orIp:192.168.51.1
+ EBGP_SENT dstIp:192.168.51.2 **srcNode:as65000_R1** srcIp:192.168.51.1 **net:10.1.1.0/24** nhip:192.168.51.1 origin:INCOMPLETE asPath:[65000, 65001] communities:[4259840002, 4259840010] orIp:192.168.51.1

+ EBGP\_SENT dstIp:192.168.51.2 **srcNode:as65000\_R1** srcIp:192.168.51.1 **net:10.1.2.0/24** nhip:192.168.51.1 origin:INCOMPLETE asPath:\[65000, 65001\] communities:\[4259840002, 4259840010\] orIp:192.168.51.1
+ EBGP_SENT dstIp:192.168.51.2 **srcNode:as65000_R1** srcIp:192.168.51.1 **net:10.1.2.0/24** nhip:192.168.51.1 origin:INCOMPLETE asPath:[65000, 65001] communities:[4259840002, 4259840010] orIp:192.168.51.1
```

The output shows that **R1** announces two /24 routes only in the second configuration (indicated by ‘+’), a red flag if the change was never intended to leak such routes. Had it shown no routes, or only routes expected due to the change, the configuration can be deemed safe to deploy (assuming other correctness checks pass too).

- To confirm if these additional prefixes are part of a less specific route that is already being advertised, one can run the following command

```
batfish> get bgpAdvertisements prefixSpace=\["10.1.1.0/24:0-23"\]
batfish> get bgpAdvertisements prefixSpace=["10.1.1.0/24:0-23"]

EBGP\_SENT dstIp:192.168.51.2 **srcNode:as65000\_R1** srcIp:192.168.51.1 **net:10.1.0.0/16** nhip:192.168.51.1 origin:INCOMPLETE asPath:\[65000, 65001\] communities:\[4259840002\] orIp:192.168.51.1
EBGP_SENT dstIp:192.168.51.2 **srcNode:as65000_R1** srcIp:192.168.51.1 **net:10.1.0.0/16** nhip:192.168.51.1 origin:INCOMPLETE asPath:[65000, 65001] communities:[4259840002] orIp:192.168.51.1
```

The output shows that there is indeed a less specific route (10.1.0.0/16) covering the more specifics.
Expand Down
6 changes: 3 additions & 3 deletions _posts/2019-06-14-announcing-batfish-ansible.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ To extract “facts” (config settings) from configuration files, one can simpl
- name: Setup connection to Batfish service
bf_session:
host: localhost
name: local\_batfish
name: local_batfish

- name: Initialize the example network
bf_init_snapshot:
Expand Down Expand Up @@ -108,7 +108,7 @@ Those advantages aside, the real power of Batfish is in being able to _validate_

## Use case II: Fact validation

Validating that facts in device configs match what is expected is easy with the  **_bf\_validate\_facts_** module.
Validating that facts in device configs match what is expected is easy with the  **_bf_validate_facts_** module.

```
- name: Validate facts gathered by Batfish
Expand Down Expand Up @@ -150,7 +150,7 @@ Beyond parsing configs, Batfish builds a full model of device configurations and
name: Confirm that there are NO undefined references on any network device
```

The task above includes four example assertions from our assertion library. The _**bf\_assert**_ module includes more, and based on community feedback, we’ll continue to make more of Batfish’s capabilities available this manner.
The task above includes four example assertions from our assertion library. The _**bf_assert**_ module includes more, and based on community feedback, we’ll continue to make more of Batfish’s capabilities available this manner.

Today’s release makes network validating broadly accessible, furthering our commitment to helping network engineers build secure and reliable networks.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,22 @@ The _testRoutePolicies_ question enables you to test the behavior of a route pol

For example, to test the "_deny all incoming routes with private addresses_" intent you would run _testRoutePolicies_ on routes with prefixes in the private address space and check that all of them are denied.

Let’s take a look at an example route-policy from\_customer and evaluate its behavior with testRoutePolicies.
Let’s take a look at an example route-policy from_customer and evaluate its behavior with testRoutePolicies.

```
route-map from\_customer deny 100
route-map from_customer deny 100
match ip address prefix-list private-ips
!
route-map from\_customer permit 200
route-map from_customer permit 200
match ip address prefix-list from44
match as-path origin44
set community 20:30
set local-preference 300
!
route-map from\_customer deny 300
route-map from_customer deny 300
match ip address prefix-list from44
!
route-map from\_customer permit 400
route-map from_customer permit 400
set community 20:30
set local-preference 300

Expand All @@ -76,19 +76,19 @@ ip prefix-list private-ips seq 15 permit 192.168.0.0/16
!
ip prefix-list from44 seq 10 permit 5.5.5.0/24 ge 24
!
ip as-path access-list origin44 permit \_44$
ip as-path access-list origin44 permit _44$
```

```
inRoute1 = BgpRoute(network="10.0.0.0/24", originatorIp="4.4.4.4", originType="egp",protocol="bgp")
result = bfq.testRoutePolicies(policies="from\_customer",direction="in",
inputRoutes=\[inRoute1\]).answer().frame()
result = bfq.testRoutePolicies(policies="from_customer",direction="in",
inputRoutes=[inRoute1]).answer().frame()
print(result)

Node    Policy\_Name    Input\_Route Action Output\_Route Difference
Node    Policy_Name    Input_Route Action Output_Route Difference

0  border1  from\_customer  BgpRoute(network='10.0.0.0/24', originatorIp='4.4.4.4', originType='egp', protocol='bgp', asPath=\[\], communities=\[\], localPreference=0, metric=0, sourceProtocol=None)  DENY   None         None
1  border2  from\_customer  BgpRoute(network='10.0.0.0/24', originatorIp='4.4.4.4', originType='egp', protocol='bgp', asPath=\[\], communities=\[\], localPreference=0, metric=0, sourceProtocol=None)  DENY   None         None
0  border1  from_customer  BgpRoute(network='10.0.0.0/24', originatorIp='4.4.4.4', originType='egp', protocol='bgp', asPath=[], communities=[], localPreference=0, metric=0, sourceProtocol=None)  DENY   None         None
1  border2  from_customer  BgpRoute(network='10.0.0.0/24', originatorIp='4.4.4.4', originType='egp', protocol='bgp', asPath=[], communities=[], localPreference=0, metric=0, sourceProtocol=None)  DENY   None         None
```

As you can see, Batfish correctly determines that the 10.0.0.0/24 route advertisement will get denied by the policy.
Expand All @@ -105,28 +105,28 @@ For example, to verify the "_deny all incoming routes with private addresse_s" i

```
\# Define the space of private addresses and route announcements
privateIps = \["10.0.0.0/8:8-32", "172.16.0.0/28:28-32", "192.168.0.0/16:16-32"\]
privateIps = ["10.0.0.0/8:8-32", "172.16.0.0/28:28-32", "192.168.0.0/16:16-32"]
inRoutes1 = BgpRouteConstraints(prefix=privateIps)

\# Verify that no such announcement is permitted by our policy
result = bfq.searchRoutePolicies(policies="from\_customer",
result = bfq.searchRoutePolicies(policies="from_customer",
inputConstraints=inRoutes1,
action="permit").answer().frame()

print(result.loc\[0\])
print(result.loc[0])

Node border2
Policy\_Name from\_customer
Input\_Route BgpRoute(network='192.168.0.0/32', originatorIp='0.0.0.0', originType='igp', protocol='bgp', asPath=\[\], communities=\[\], localPreference=0, metric=0, sourceProtocol=None)
Policy_Name from_customer
Input_Route BgpRoute(network='192.168.0.0/32', originatorIp='0.0.0.0', originType='igp', protocol='bgp', asPath=[], communities=[], localPreference=0, metric=0, sourceProtocol=None)
Action PERMIT
Output\_Route BgpRoute(network='192.168.0.0/32', originatorIp='0.0.0.0', originType='igp', protocol='bgp', asPath=\[\], communities=\['20:30'\], localPreference=300, metric=0, sourceProtocol=None)
Difference BgpRouteDiffs(diffs=\[BgpRouteDiff(fieldName='communities', oldValue='\[\]', newValue='\[20:30\]'), BgpRouteDiff(fieldName='localPreference', oldValue='0', newValue='300')\])
Output_Route BgpRoute(network='192.168.0.0/32', originatorIp='0.0.0.0', originType='igp', protocol='bgp', asPath=[], communities=['20:30'], localPreference=300, metric=0, sourceProtocol=None)
Difference BgpRouteDiffs(diffs=[BgpRouteDiff(fieldName='communities', oldValue='[]', newValue='[20:30]'), BgpRouteDiff(fieldName='localPreference', oldValue='0', newValue='300')])
```

Batfish has found a route advertisement 192.168.0.0/32 that will be allowed by the routing policy, despite our intent being for it to be denied. There may be multiple route advertisements that violate our intent, Batfish picks one as an example to highlight the error. If you look closely at the routing policy, the route-map from\_customer is going to deny routes that match the prefix-list private-ips. The last entry in that prefix-list is incorrect. It is missing the "ge 16" option. As defined, that entry only matches the exact route 192.168.0.0/16, which means any other prefix from that 192.168.0.0/16 space will not be matched and therefore not be denied by the route-map.
Batfish has found a route advertisement 192.168.0.0/32 that will be allowed by the routing policy, despite our intent being for it to be denied. There may be multiple route advertisements that violate our intent, Batfish picks one as an example to highlight the error. If you look closely at the routing policy, the route-map from_customer is going to deny routes that match the prefix-list private-ips. The last entry in that prefix-list is incorrect. It is missing the "ge 16" option. As defined, that entry only matches the exact route 192.168.0.0/16, which means any other prefix from that 192.168.0.0/16 space will not be matched and therefore not be denied by the route-map.

```
route-map from\_customer deny 100 match ip address prefix-list private-ips
route-map from_customer deny 100 match ip address prefix-list private-ips

ip prefix-list private-ips seq 5 permit 10.0.0.0/8 ge 8 ip prefix-list private-ips seq 10 permit 172.16.0.0/28 ge 28
ip prefix-list private-ips seq 15 permit 192.168.0.0/16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This category of bugs is as old as typewriters. Some entertaining examples off t

- Incorrectly assigned address (a public IP!) to a router interface: _100.x.y.z_ instead of _10.x.y.z_
- Mistyped prefix list name: **prefix-list PFX-LIST 10.1O0.10.128/25** (the letter ‘O’ instead of the number ‘0’ in the prefix)
- Mistyped access-list for a SNMP community: _SNMP-ACCESS-LIST_ instead of _SNMP\_ACCESS\_LIST_ (‘-’ vs ‘\_’)
- Mistyped access-list for a SNMP community: _SNMP-ACCESS-LIST_ instead of _SNMP_ACCESS_LIST_ (‘-’ vs ‘\_’)
- Mistyped route-map name: _BLEAD-TRAFFIC_ instead of _BLEED-TRAFFIC_
- Mistyped keyword: **no bgp defaults ipv4-unicast** instead of **no bgp default ipv4-unicast**
- Wrong BGP neighbor IP: **neighbor 169.254.127.3 activate** instead of **neighbor 169.54.127.1 activate**
Expand Down
6 changes: 3 additions & 3 deletions _posts/2020-12-18-validating-the-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ To appreciate the need to go beyond RFCs and docs, consider the following FRR co
2 ip community-list 14 permit 65001:4
3 ip community-list 24 permit 65002:4
4 !
5 route-map com\_update permit 10
5 route-map com_update permit 10
6 match community 14
7 on-match goto 20
8 set community 65002:4 additive
9 !
10 route-map com\_update permit 20
10 route-map com_update permit 20
11 match community 65002:4
12 set community 65002:5 additive
13 !
14 route-map com\_update permit 30
14 route-map com_update permit 30
15 match community 24
16 set community 65002:6 additive
17 !
Expand Down
10 changes: 5 additions & 5 deletions _posts/2021-05-18-automating-the-long-pole-of-network-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ Let us illustrate how they work via an example: Allowing access to a new service

Your change generation script will use the request parameters to generate the configuration commands for one or more devices. For example, it may generate the following change to the Palo Alto firewall at the edge of the network:

set service S\_TCP\_80 protocol tcp port 80
set service-group SG\_NEWSERVICE members S\_TCP\_80
set service S\_TCP\_8080 protocol tcp port 8080
set service-group SG\_NEWSERVICE members S\_TCP\_8080
set service S_TCP_80 protocol tcp port 80
set service-group SG_NEWSERVICE members S_TCP_80
set service S_TCP_8080 protocol tcp port 8080
set service-group SG_NEWSERVICE members S_TCP_8080

set address tkt123-dst1 ip-netmask 10.100.40.0/24
set address-group tkt123-dst static tkt123-dst1
Expand All @@ -54,7 +54,7 @@ set rulebase security rules tkt123 to INSIDE
set rulebase security rules tkt123 source any
set rulebase security rules tkt123 destination tkt123-dst
set rulebase security rules tkt123 application any
set rulebase security rules tkt123 service SG\_NEWSERVICE
set rulebase security rules tkt123 service SG_NEWSERVICE
set rulebase security rules tkt123 action allow

This change may be generated using Jinja2 templates, an internal source-of-truth like Netbox, or the Palo Alto Ansible module. Regardless of how it is generated, you can submit it to Batfish Enterprise and analyze it using three criteria.
Expand Down
Loading