Batfish使

此篇文章在github可以找到英文版的,此篇文章目的是提炼Batfish的用法

一、执行简单的Batfish命令

1.初始化网络和快照

# Import packages and load questions
%run startup.py
load_questions()

# Assign a friendly name to your network and snapshot
NETWORK_NAME = "example_network"
SNAPSHOT_NAME = "example_snapshot"
SNAPSHOT_PATH = "networks/example"

# Now create the network and initialize the snapshot
bf_set_network(NETWORK_NAME)
bf_init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)

2.执行询问模型

# Load all questions
load_questions()

# To see available questions, you can use
# list_questions()
# You can also use tab-completion on the Batfish question module - bfq. -> press TAB key,
# uncomment and try on the following line
# bfq.
# In IPython and Jupyter you can use the "?" shorthand to get help on a question
?bfq.nodeProperties
# help(bfq.nodeProperties) # in standard Python console

3.开始解析文件的状态

parse_status = bfq.fileParseStatus().answer().frame()

# An example: use a filter on the returned dataframe to see which files failed to parse completely
parse_status[parse_status['Status'] != 'PASSED']  # change '!=' to '==' to get the files which passed

# View details if some of the files were not parsed completely
parse_warning = bfq.parseWarning().answer().frame()
parse_warning

4.提取网络实体的属性

# Extract the properties of all nodes whose names contain 'border'
node_properties = bfq.nodeProperties(nodes="/border/").answer().frame()

# View what columns (properties) are present in the answer
node_properties.columns

# To extract only a subset of properties, use the properties parameter
node_properties_trunc = bfq.nodeProperties(nodes="/border/", properties="Domain_Name|NTP_Servers|Interfaces").answer().frame()
node_properties_trunc

# Let's remove the interfaces column from our result
node_properties_trunc = node_properties_trunc[["Node", "Domain_Name", "NTP_Servers"]]
node_properties_trunc

# View only nodes with **23.23.23.23** as one of the configured ntp-servers
node_properties_trunc[node_properties_trunc['NTP_Servers'].apply(lambda x:'23.23.23.23' in x)]

interface_properties = bfq.interfaceProperties(nodes="/border/", properties="Interface_Type|Bandwidth|VRF|Primary_Address").answer().frame()
interface_properties[interface_properties['Primary_Address'].str.match("10.12", na=False)]

5.检视配置文件结构的引用完整性

# List references to undefined structures
bfq.undefinedReferences().answer().frame()

6.简视物理和逻辑的结构

# Get edges of type layer 3 (IP layer)
bfq.edges(nodes="as1border1", edgeType="layer3").answer().frame()

7.探测路由表和转发表

# Do a traceroute from host1 to 1.0.2.2
tr_frame = bfq.traceroute(startLocation="host1", headers=HeaderConstraints(dstIps="1.0.2.2")).answer().frame()

# Display results using customizations to handle large string values
show(tr_frame)

# Fetch the routing table of all VRFs on all nodes in the snapshot
routes_df = bfq.routes().answer().frame()

# View all routes for the network 90.90.90.0/24 with an AdminDistance of 0
routes_df[(routes_df['Network'] == "90.90.90.0/24") & (routes_df["Admin_Distance"] == 0)]

二、使用Batfish验证网络配置

1.初始化网络配置和快照

# Import packages and load questions
%run startup.py
load_questions()

# Initialize a network and snapshot
NETWORK_NAME = "example_network"
SNAPSHOT_NAME = "example_snapshot"
SNAPSHOT_PATH = "networks/example"
bf_set_network(NETWORK_NAME)
bf_init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)

2.提取NTP服务器配置

# Set the property that we want to extract
COL_NAME = "NTP_Servers"

# Extract NTP servers for all routers with 'border' in their name
node_props = bfq.nodeProperties(
    nodes="/border/", 
    properties=COL_NAME).answer().frame()
node_props

3.验证NTP服务器配置

(1)每个节点至少配置一个NTP服务

# Find nodes that have no NTP servers configured
ns_violators = node_props[node_props[COL_NAME].apply(
    lambda x: len(x) == 0)]
ns_violators

(2)每个节点至少配置一个从引用集来的NTP服务

# Define the reference set of NTP servers
ref_ntp_servers = set(["23.23.23.23"])

# Find nodes that have no NTP server in common with the reference set
ns_violators = node_props[node_props[COL_NAME].apply(
    lambda x: len(ref_ntp_servers.intersection(set(x))) == 0)]
ns_violators

(3)每个节点有NTP服务配置的引用集

# Find violating nodes whose configured NTP servers do not match the reference set
ns_violators = node_props[node_props[COL_NAME].apply(
    lambda x: ref_ntp_servers != set(x))]
ns_violators

# Find extra and missing servers at each node
ns_extra = node_props[COL_NAME].map(lambda x: set(x) - ref_ntp_servers)
ns_missing = node_props[COL_NAME].map(lambda x: ref_ntp_servers - set(x))

# Join these columns up with the node columns for a complete view
diff_df = pd.concat([node_props["Node"],
                     ns_extra.rename('extra-{}'.format(COL_NAME)),
                     ns_missing.rename('missing-{}'.format(COL_NAME))],
                    axis=1)
diff_df

(4)每个节点都有匹配每一个节点数据库的NTP服务

# Transpose database data so each node has its own row
database_df = pd.DataFrame(data=database).transpose()

# Index on node for easier comparison
df_node_props = node_props.set_index('Node')

# Select only columns present in node_props (get rid of the extra dns-servers column)
df_db_node_props = database_df[df_node_props.columns].copy()

# Convert server lists into sets to support arithmetic below
df_node_props[COL_NAME] = df_node_props[COL_NAME].apply(set)
df_db_node_props[COL_NAME] = df_db_node_props[COL_NAME].apply(set)

# Figure out what servers are in the configs but not the database and vice versa
missing_servers = (df_db_node_props - df_node_props).rename(
    columns={COL_NAME: 'missing-{}'.format(COL_NAME)})
extra_servers = (df_node_props - df_db_node_props).rename(
    columns={COL_NAME: 'extra-{}'.format(COL_NAME)})
result = pd.concat([missing_servers, extra_servers], axis=1, sort=False)
# removing the index name for clearer output
del result.index.name
result

4.探索其它的功能

# Extract interface MTU for Ethernet0/0 interfaces on border routers
interface_mtu = bfq.interfaceProperties(
    interfaces="/border/[Ethernet0/0]",
    properties="MTU").answer().frame()
interface_mtu

三、分析ACL和防火墙规则

  1. Test how filters in the network treat a flow "testFilters"

  2. Verify how filters treat a large space of flows "searchFilters"

  3. Find filter lines that will never match any packet "filterLineReachability"

1.初始化网络

# Import packages and load questions
%run startup.py
load_questions()

# Initialize a network and a snapshot
bf_set_network("network-example-filters")
SNAPSHOT_NAME = "current"
SNAPSHOT_PATH = "networks/example-filters/current"
bf_init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)

2.TestFilters测试过滤器怎样处理一个流

实例1:测试是否子网里的主机能够到到DNS服务器

# Check if a representative host can reach the DNS server
dns_flow = HeaderConstraints(srcIps="10.10.10.1",
                             dstIps="218.8.104.58",
                             applications=["dns"])
answer = bfq.testFilters(headers=dns_flow,
                         nodes="rtr-with-acl",
                         filters="acl_in").answer()
show(answer.frame())

实例2:测试HTTP流不能从一个区域到另一个区域

# Test if a host can reach the DNS server
http_flow = HeaderConstraints(srcIps="10.114.64.1",
                              dstIps="10.114.60.10",
                              applications=["http"])
answer = bfq.testFilters(headers=http_flow,
                         startLocation="@enter(firewall[GigabitEthernet0/0/2])",
                         filters="@out(GigabitEthernet0/0/3)").answer()
show(answer.frame())

3.searchFilters验证过滤器如何处理一个(非常大)空间上的流

Example1:searchFilters: Verifying how filters treat a (very large) space of flows

# Check if the subnet can reach the DNS server
dns_traffic = HeaderConstraints(srcIps="10.10.10.0/24",
                                dstIps="218.8.104.58",
                                applications=["dns"])
answer = bfq.searchFilters(headers=dns_traffic,
                           action="deny",
                           filters="acl_in").answer()
show(answer.frame())

Example 2: Verify that the only TCP traffic that can go from one zone to another is NFS traffic

# Check if any non-NFS, TCP flow can go from one zone to another
non_nsf_tcp_traffic = HeaderConstraints(srcIps="101.164.101.231",
                                        dstIps="101.164.9.0/24",
                                        ipProtocols=["tcp"],
                                        dstPorts="!2049")  # exclude NFS port (2049)
answer = bfq.searchFilters(headers=non_nsf_tcp_traffic,
                           startLocation="@enter(firewall[GigabitEthernet0/0/2])",
                           filters="@out(GigabitEthernet0/0/3)",
                           action="permit").answer()
show(answer.frame())

4.filterLineReachability分析过滤行的可达性

# Find unreachable lines in filters of rtr-with-acl
aclAns = bfq.filterLineReachability(nodes="rtr-with-acl").answer()
show(aclAns.frame())

 

你可能感兴趣的:(Batfish网络配置验证工具)