C模块(BGP路由控制).note
考核前的笔记:
一、交换网络:
1、配置 vlan 信息存储在 Flash: 中:

vtp file [名称]
vtp file vlandb.dat
# 查看:
do dir flash:
do dir flash:/vlandb.dat
2、启用二层隔离(在交换机接口上):
interface G1/1
switchport protected· 查看:
do show interfaces g1/1 switchport 
3、用户身份验证(使用 aaa):

(1)路由器、交换机:
aaa new-model //启用 aaa
aaa authentication login default local-case //使用 本地数据库进行 身份验证,并严格区分大小写(区分用户名大小写)
lin con 0
login authentication default //在 console 启用 aaa 身份验证
exit(2)防火墙:
aaa authentication enable console LOCAL 4、链路聚合:
二、ssh:
1、ASA 防火墙 SSH 连接:
crypto key generate rsa label ssh.key modulus 2048 //生成密钥
username Admin password Skills39! privilege 15 //创建一个用户
aaa authentication ssh console ssh console LOCAL //设置 ssh 使用本地用户数据库
ssh 0.0.0.0 0.0.0.0 INSIDE //在接口启用 ssh(输入要允许ssh访问该接口的网段)
# ssh [允许指定网段访问] [网段掩码] [接口区域号](未配置成功,防火墙ssh已经激活,端口起来了,但是Linux的ssh与其的密钥协议对不上,因为密钥协议所以连接失败)
三、(BGP路由控制)路由网络:
1、BGP 路由控制(修改weight值):
· 题目:

· 拓扑:

在 AS100(RT1、RT2)上使用 ACL 抓取 1.1.8.8 这条流量,然后使用route-map 修改其 weight值(weight值越大越优先),然后将该 route-map 应用在 BGP的 AS100的 in 方向,neighbor邻居为EF1(neighbor 133.99.80.6 route-map A in)
我们有两个邻居:1.1.1.2、29.77.156.6。我们想让 1.1.1.2 成为最优的路径,让 29.77.156.6 成为备份路径,那么我们就修改 1.1.1.2 的weight值,将1.1.1.2的weight值调大,将 29.77.156.6 的weight值调小
· BGP 选路比较原则:
1、最先比较weight值(weight值越大,越优先)[可以使用route-map修改]
2、weight值相同,则比较 LOCAL_PREF 值(值越大越优先)[可以使用route-map修改]
3、看该路由是否是由本地发起的(如果是由本地发起的[下一跳为0.0.0.0的路由],那么则本地为最优先)
4、最少的AS_PATH [可以使用route-map调整(只能添加不能减少,但是可以给as_path 少的路由添加几个as_path,使要修改的两条路由as_path 数量相同即可)]
5、最优先的Orighn类型(优先:IGP>EGP>Incomplete) [可以使用route-map修改类型为:IGP 或 Incomplete]
6、最低的metric值
....· 配置:
1、造假一条BGP路由:
# 因为我 EF1 没有从 ER1 上获取到 1.1.8.8 的路由条目(而考核时我时间又不太充足了,那么我就造假一条BGP路由条目)
## 前提:EF1 和 AS100(RT2) 建立起了邻居,且RT2能够获取到 EF1 通告的路由
EF1(config)# route INSIDE 1.1.8.8 255.255.255.255 172.16.31.6 //使用静态路由,让IGP路由表中有 1.1.8.8 的路由(因为是造假的路由,所以下一跳是无所谓的)
EF1(config)# router bgp 65002
EF1(config-router)# address-family ipv4 unicast
EF1(config-router-af)# network 1.1.8.8 mask 255.255.255.255 //将该路由通告出去此时 RT2就获取到了由 EF1 通告过来的 1.1.8.8 的路由了:

2、配置BGP路由控制:
# 首先,因为路由条目是从 eBGP 传入 iBGP的([1.1.8.8]]RT1从ER1获取条目传给RT2,RT2从EF1获取条目传给RT1)因此需要配置:next-hop-self
RT1(config-router)#neighbor 1.1.1.2 next-hop-self
RT2(config-router)#neighbor 1.1.1.1 next-hop-self
# 配置 route-map + ACL(匹配1.1.8.8这条路由,并将其weight值修改【因为此时的默认的weight值都为0,因此我们就可以将备份链路的weight值不变(默认为0),而我们想要配置为最优先的链路的metric值则调大】)
RT1(config)#access-list 1 permit 1.1.8.8 //使用ACL进行匹配流量
RT1(config)#route-map BGP1 permit 10 //配置route-map
RT1(config-route-map)#match ip address 1 //引用刚刚创建的ACL
RT1(config-route-map)#set weight 100 //将其weight值调大
RT1(config)#router bgp 100 //进入BGP中应用这条route-map
(我们有两个邻居:1.1.1.2、29.77.156.6。我们想让 1.1.1.2 成为最优的路径,让 29.77.156.6 成为备份路径,那么我们就不修改 29.77.156.6 的weight值,我们将 1.1.1.2 的weight值调大)
RT1(config-router)#neighbor 1.1.1.2 route-map BGP1 in //在 in 方向应用这条route-map
(因为我们是要控制自己的路由,in方向更改自己的路由,out方向更改别人设备的路由)
# 修改路由条目需要时间,可以稍微等待1-2分钟· 配置成功,此时我们对比一下:
修改weight前:

修改weight后:

关于 RT2 的配置这里就省略,与上面的 RT1 一样,也是修改 weight 值,将 1.1.1.1(RT1)邻居的weight值不变,将 邻居 133.99.80.6(EF1)的 weight 值调大即可
· 问题:
但是我此时发现一个问题(不知是环境的因素还是本身的原因),我们的路由控制做成功了,但是,修改路由的weight值后,RT1却直接不将该路由推送给RT2了,而RT2这里没有接收到来自 RT1 的 通往 1.1.8.8 的路由,因此 此时对于 RT2 来说,通往 1.1.8.8 就只剩下一条路径(EF1)了:

此时确实符合题目要求的“对于1.1.8.8的路由,优先通过133.99.80.6”,但是RT2 却不再存在两条路径,此时只存在一条路径了,我们将 RT1上修改weight值的操作 no 掉 看看:


此时两条路径就出现了,这是不完美的效果,那么我开始尝试修改其 LOCAL_PREF 值 或 metric 值:
1、修改 LOCAL_PREF 值(越大越优先):
RT1(config-router)#neighbor 1.1.1.2 next-hop-self
RT2(config-router)#neighbor 1.1.1.1 next-hop-self
# 使用ACL抓取流量
RT1(config)#access-list 1 permit 1.1.8.8
# 配置 route-map 修改 LOCAL_PREF值
RT1(config)#route-map BGP1 permit 10
RT1(config-route-map)#match ip address 1
RT1(config-route-map)#set local-preference 100 //设置local值为100
RT1(config-route-map)#set weight 0 //设置weight值为0(保证其不被weight值影响)
RT1(config)#route-map BGP2 permit 10
RT1(config-route-map)#match ip address 1
RT1(config-route-map)#set local-preference 0 //设置local值为0
RT1(config-route-map)#set weight 0 //设置weight值为0(保证其不被weight值影响)
(route-map的配置 目前来看,BGP1 更优先于 BGP2,而我们的两条路径:1.1.1.2,29.77.156.6。1.1.1.2应该引入BGP1,成为最优的路径,29.77.156.6引入BGP2,成为备份链路)
# 在 BGP中引入该 route-map:
RT1(config-router)#neighbor 1.1.1.2 route-map BGP1 in
RT1(config-router)#neighbor 29.77.156.6 route-map BGP2 in
· 配置成功,此时我们再查看一下:
修改 LOCAL_PREF 之前:
默认都是100,这里因为都是100,所以省略了

修改 LOCAL_PREF 之后:

这时我们再在 RT2 上查看,观察路由条目是否有正常传递:

这里和上面一样,能达成路由控制的效果,却还是只有一条路径
2、修改 metric 进行尝试(metric越小越优先):
RT1(config-router)#neighbor 1.1.1.2 next-hop-self
RT2(config-router)#neighbor 1.1.1.1 next-hop-self
# 使用ACL抓取流量:
RT1(config)#access-list 1 permit 1.1.8.8
# 配置 route-map:
RT1(config)#route-map BGP1 permit 10
RT1(config-route-map)#match ip address 1
# 设置weight值、local值、origin类型为相同的,使它们不会影响到路径选择
RT1(config-route-map)#set weight 0
RT1(config-route-map)#set local-preference 100
RT1(config-route-map)#set origin igp
# 设置 metric值:
RT1(config-route-map)#set metric 0
RT1(config)#route-map BGP2 permit 10
RT1(config-route-map)#match ip address 1
# 设置weight值、local值、origin类型为相同的,使它们不会影响到路径选择
RT1(config-route-map)#set weight 0
RT1(config-route-map)#set local-preference 100
RT1(config-route-map)#set origin igp
# 设置 metric值:
RT1(config-route-map)#set metric 10
# 在 BGP 中引入 route-map:
RT1(config-router)#neighbor 1.1.1.2 route-map BGP1 in
RT1(config-router)#neighbor 29.77.156.6 route-map BGP2 in四、Ansible:
这次考核时ansible做的并不理想,因为当时没有掌握Ansible内容的输出的同时保证可读性,使得输出全被输出成一行
我这次复盘时偶然发现,使用 shell模块,直接使用 echo 可以将其全部输出到指定的文件中
1、剧本一:

---
- name: Get switch Config
hosts: cisco_sw
gather_facts: False
tasks:
# 使用 ios_command 模块获取 配置文件
- name: Get switch Config
ios_command:
commands: show running-config
register: output
# 用于查看 output 的内容(output本身的内容比较杂乱,可以使用到 .stdout_lines 将 output 的内容每一行都输出成一个列表,如:var: output.stdout_lines[这里没有使用是因为发现下面可以不适用它])
- name: check output
debug:
var: output
# 将 output 的内容出书到指定的文件中
- name: Export output to file
shell: "echo {{ output }} > /backup/cisco/switch/{{ inventory_hostname }}.cfg"
- name: Get firewall Config
hosts: cisco_edge
gather_facts: False
tasks:
- name: Get firewall Config
ios_command:
commands: show running-config
register: output
- name: Export output to file
shell: "echo {{ output }} > /backup/cisco/edge/{{ inventory_hostname }}.cfg"
2、剧本二:

· 使用 set_fact 模块能够生成一个新的变量,或对 旧的变量进行修改(转换为字符串、分割字符串为列表等操作)
· 使用 shell 模块 直接 echo ,能够将变量的内容完整的输出到指定的文件中
---
- name: Check Device
hosts: cisco_sw
gather_facts: False
tasks:
# 获取 CPU 的使用情况(并在命令行先进行一次过滤,尽可能过滤掉无关内容)
- name: Check CPU
ios_command:
commands: show processes cpu | include CPU utilization
register: cpu
# 将输出的变量转换为字符串,并使用字符串方法 split() 进行分割成列表,每隔一个空格,就分割成一个列表
- name: read CPU
set_fact:
cpu1: "{{ cpu | string | split(' ') }}"
# 使用列表下标进行截取,截取列表下标为[8]的内容(它是我们需要的CPU使用率),而此时其中还有一些其他我们不需要的杂乱内容,因此需要再进行过滤,以'/'进行分割
- name: set fact1
set_fact:
cpu2: "{{ cpu1[8] | split('/') }}"
# 使用列表下标进行截取,截取列表下标为[0]的内容,再进行过滤,以'%'进行分割
- name: set fact2
set_fact:
cpu3: "{{ cpu2[0] | split('%') }}"
# 此时我们已经将我们想要的数据成功过滤出来了,接下来将它转换成整数(题目要的是空闲的CPU的数据,我们现在过滤出来的是CPU的使用率)
- name: set fact3
set_fact:
cpu4: "{{ 100 | int - cpu3[0] | int }}"
# 用于给 内存使用率作为输出(没有真正成功获取,这里是家的内存使用率)
- name: set fact4
set_fact:
cpu5: "{{ cpu3[0] | int - 4 | int }}"
# 这时我们只需要将变量按照题目要求输出即可
- name: shell
# 这条是为了让剧本能够多次执行(清空里面文件的内容,因为后面使用的都是重定向符的追加)
shell: echo > /monitor/cisco/cisco_sw/cpu_mem.info
- name: Export CPU_Free
shell: "echo '{{ inventory_hostname }} Cpu_free: {{ cpu4 }}%' >> /monitor/cisco/cisco_sw/cpu_mem.info"
# 因为没有找到哪条命令能够将内存使用率以百分比的形式输出,这里就使用上面过滤出的内容,伪装成 内存使用率
- name: Export Memory Free
raw: "echo '{{ inventory_hostname }} Mem_free: {{ cpu5 }}%' >> /monitor/cisco/cisco_sw/cpu_mem.info"3、剧本三:
· 附件:

这一题考察的是读取文件的内容
可以使用 include_vars 模块进行读取
虽然下面这个不是上面的剧本,但是作用类似:
---
- name: read
# hosts: LEAF-SW-03,LEAF-SW-04,SPINE-SW-01
hosts: all:!LEAF-SW-01:!LEAF-SW-02
# hosts为“all”,但是排除“LEAF-SW-01” 和 “LEAF-SW-02”
gather_facts: False
tasks:
- name:
include_vars:
file: /etc/ansible/data/interfaces_info.yml
name: yaml
- name: Set fact
# 先使用 with_dict 遍历字典,再使用set_fact注册变量,将结果保存至“fact”中
## 这里使用的 set_fact 是关键
set_fact:
fact: "{{ item.value }}"
with_dict: "{{ yaml }}"
when: item.key == inventory_hostname
- name: Enable Switch Interface
ios_config:
lines:
- no shutdown
- no switchport
parents: "interface {{ item.name }}"
when:
# 使用 when 排除“Loopback”接口 and “inventory_hostname”必须等同于指定的交换机
- item.name != "Loopback0"
- inventory_hostname == "LEAF-SW-03" or inventory_hostname == "LEAF-SW-04" or inventory_hostname == "SPINE-SW-01" or inventory_hostname == "SPINE-SW-02"
with_items:
# 使用 with_items 遍历列表,然后进行操作
- "{{ fact.interface }}"
- name: Config other Interfaces
# 再配置IP地址
ios_config:
lines:
- no shutdown
- "description {{ item.description }}"
- "ip address {{ item.ipv4.address }} {{ item.ipv4.subnet_mask }}"
parents: "interface {{ item.name }}"
when: '"ipv4" in item'
# 当遍历的变量中存在"IPv4"时,才运行该剧本
with_items:
- "{{ fact.interface }}"
- name: Config SPINE Vlan
# 进行创建 vlan
ios_config:
lines:
- no shutdown
- "description {{ item.description }}"
- switchport mode access
- "switchport access vlan {{ item.vlan }}"
parents: "interface {{ item.name }}"
before:
# 在 所有操作之前,先将接口恢复至默认,并且创建 vlan
- "default interface {{ item.name }}"
- "vlan {{ item.vlan }}"
when: "'vlan' in item"
# 当遍历的变量中存在"vlan"时,才运行该剧本
with_items:
- "{{ fact.interface }}"