Thursday, 2 October 2025

Ansible Cisco

 ansible.cfg

[defaults]

timeout= 60
host_key_checking=False
deprecation_warnings=False
interpreter_python=/usr/local/bin/python3

[paramiko_connection]
look_for_keys = False

==========================================================

hosts

[iosxe:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_user=<username>
ansible_password=<password>
ansible_become=yes
ansible_become_method=enable
ansible_network_os=cisco.ios.ios
subnet_id=1

[iosxe]

<device-ip>

==========================================================

show-commands.yaml

---

- name: Sample IOS playbook to run show commands

  hosts: iosxe

  gather_facts: no


  tasks:

  - name: run show ip int brief

    cisco.ios.ios_command:

      commands: show ip interface brief

    register: myinterfaces


  - name: display value of "myinterfaces" variable

    debug:

      var: myinterfaces["stdout_lines"][0]


  - name: run show users

    cisco.ios.ios_command:

      commands: show users

    register: myusers


  - name: display value of "myusers" variable

    debug:

      var: myusers["stdout_lines"][0]

==========================================================

ansible-playbook -i hosts show_commands.yaml

==========================================================

Monday, 19 February 2024

netmiko - show command

import netmiko
import re

ip = 'sbx-nxos-mgmt.cisco.com'
username = 'admin'
password = '<removed>'
device_type = 'cisco_xe'
port = '22'

net_connect = netmiko.ConnectHandler(ip=ip, device_type=device_type, username=username, password=password, port=port)

show_run = net_connect.send_command('show run')
show_ip_route = net_connect.send_command('show ip route')
print(show_run)
print('*'*100,)
print(show_ip_route)

Thursday, 19 May 2022

Ansible and ACI

These are some ansible playbooks to do basic configuration on Cisco ACI using ansible.
Information taken from here:

https://github.com/CiscoDevNet/aci_ansible_learning_labs_code_samples/

"inventory" should look like this:

[apic:vars]

username=admin
password=<removed>
ansible_python_interpreter="/home/username/ansible/aci_ansible_learning_labs_code_samples/venv/bin/python"

[apic]

sandboxapicdc.cisco.com

1. Create Tenant:

---
- name: ENSURE APPLICATION CONFIGURATION EXISTS
  hosts: apic
  connection: local
  gather_facts: False
  vars_prompt:
    - name: "tenant"
      prompt: "What would you like to name your Tenant?"
      private: no

  tasks:
    - name: ENSURE APPLICATIONS TENANT EXISTS
      aci_tenant:
        host: "{{ ansible_host }}"
        username: "{{ username }}"
        password: "{{ password }}"
        state: "present"
        validate_certs: False
        tenant: "{{ tenant }}"
        description: "Tenant Created Using Ansible"


ansible-playbook -i inventory 01_aci_tenant_pb.yml


What would you like to name your Tenant?: test-tenant

PLAY [ENSURE APPLICATION CONFIGURATION EXISTS] *********************************************************************

TASK [ENSURE APPLICATIONS TENANT EXISTS] ***************************************************************************
changed: [sandboxapicdc.cisco.com]

PLAY RECAP *********************************************************************************************************
sandboxapicdc.cisco.com    : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

2. Create Tenant, VRF and Bridge Domain:

! This is a modified version of the playbook which assumes that the tenant does not exists and prompts for both the tenant and VRF name to be created.

---
- name: ENSURE APPLICATION CONFIGURATION EXISTS
  hosts: apic
  connection: local
  gather_facts: False
  vars_prompt:
    - name: "tenant"
      prompt: "What would you like to name your Tenant?"
      private: no
    - name: "vrf"
      prompt: "What would you like to name your VRF?"
      private: no

  tasks:
    - name: ENSURE APPLICATIONS TENANT EXISTS
      aci_tenant:
        host: "{{ ansible_host }}"
        username: "{{ username }}"
        password: "{{ password }}"
        state: "present"
        validate_certs: False
        tenant: "{{ tenant }}"
        description: "Tenant Created Using Ansible"

    - name: ENSURE TENANT VRF EXISTS
      aci_vrf:
        host: "{{ ansible_host }}"
        username: "{{ username }}"
        password: "{{ password }}"
        state: "present"
        validate_certs: False
        tenant: "{{ tenant }}"
        vrf: "{{ vrf }}"
        description: "VRF Created Using Ansible"

    - name: ENSURE TENANT BRIDGE DOMAIN EXISTS
      aci_bd:
        host: "{{ ansible_host }}"
        username: "{{ username }}"
        password: "{{ password }}"
        state: "present"
        validate_certs: False
        tenant: "{{ tenant }}"
        bd: "{{ bd | default('prod_bd') }}"
        vrf: "{{ vrf }}"
        description: "BD Created Using Ansible"

    - name: ENSURE BRIDGE DOMAIN SUBNET EXISTS
      aci_bd_subnet:
        host: "{{ ansible_host }}"
        username: "{{ username }}"
        password: "{{ password }}"
        state: "present"
        validate_certs: False
        tenant: "{{ tenant }}"
        bd: "{{ bd | default('prod_bd') }}"
        gateway: "10.10.101.1"
        mask: 24
        description: "Subnet Created Using Ansible"


ansible-playbook 02_aci_tenant_network_pb.yml -i inventory

What would you like to name your Tenant?: test-tenant
What would you like to name your VRF?: test-VRF

PLAY [ENSURE APPLICATION CONFIGURATION EXISTS] *******************************************************************************

TASK [ENSURE APPLICATIONS TENANT EXISTS] *************************************************************************************
changed: [sandboxapicdc.cisco.com]

TASK [ENSURE TENANT VRF EXISTS] **********************************************************************************************
changed: [sandboxapicdc.cisco.com]

TASK [ENSURE TENANT BRIDGE DOMAIN EXISTS] ************************************************************************************
changed: [sandboxapicdc.cisco.com]

TASK [ENSURE BRIDGE DOMAIN SUBNET EXISTS] ************************************************************************************
changed: [sandboxapicdc.cisco.com]

PLAY RECAP *******************************************************************************************************************
sandboxapicdc.cisco.com    : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Paramiko - config grab with Cisco IOS

import time
import paramiko
import getpass
from datetime import datetime

routers = ["192.168.0.1"]
username = raw_input("Please enter your username: ")
password = getpass.getpass("Please enter your password: ")

now_time = datetime.now()
str_now_time = str(now_time)

sshcon = paramiko.SSHClient()
sshcon.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for target in routers:
f = open("{0}-{1}-txt".format(target,str_now_time) , "w")
print ('Attempting to connect to {0}'.format(target))
sshcon.connect(hostname=target,username=username,password=password,look_for_keys=False)
remote_connection = sshcon.invoke_shell()
remote_connection.send("ter len 0\n")
time.sleep(5)
remote_connection.send("show run\n")
time.sleep(5)
output = remote_connection.recv(65535)
# print(output)
print ('Writing config to file')
f.write(output)
sshcon.close
print("Job completed successfully")

Friday, 19 November 2021

Making a Raspberrypi Stop Motion Video

This guide explains how to make a stop motion video using a raspberrypi with the camera module. As part of this exercise I also wanted to transfer the file over to another remote PC in an automated fashion.
The reason I wanted to do this was the using video made the filesize umanageable. With stop motion you can alter the interval, duration of process etc.

High level steps:

1. pi1 takes a picture every 10 seconds 
2. pi1 copies the picture to pi2
3. pi1 deletes the local copy and takes another picture and repeats the process.
4. On pi2 there is a scheduled cronjob that creates a video from the still images and then deletes the images files.

On pi1:

Create a folder to store our images:
mkdir /home/pi/camera

Create a script to capture the images:

sudo nano /home/pi/camera.sh

Add the following to the camera.sh shell script. The script itself runs through a for loop, you can see in this example it runs through 3600 iterations.  Within the loop the script takes a picture and outputs it to a file with a filename called picture-i (where i is the number where we are in the loop). The script then pauses for 10 seconds. This means that this script would take roughly 10 hours to work through the loop until it stops - you can obviously modify the values to suit your needs.  The script then writes the file to pi2 using scp - you need to have already setup ssh login without password for this to work. The script then deletes the local file and returns to the start of the loop. The deletion of the local file is purely to save space - it is not compulsory:

#!/bin/bash

#DATE=$(date +"%Y-%m-%d_%H%M%S")

for ((i=1; i<=3600; i++))

do

        DATE=$(date +"%Y-%m-%d_%H-%M-%S")

        echo "*** Taking Picture $i ***" 

        raspistill -o /home/pi/camera/picture-$i.jpg

        sleep 10


        echo "*** Writing file $i to remote server ***"

        scp /home/pi/camera/*.jpg pi@pi2:/home/pi/camera

        rm /home/pi/camera/*.jpg

done

Press CTRL + X, followed by Y to close the file and save it:

Make the script executable:
sudo chmod +x camera.sh

Now we move to pi2

Create a folder to store our images:
mkdir /home/pi/camera

Back on pi1 if we execute the script we should the .jpg files appearing in our folder on pi2.
cd /home/pi/camera
./camera.sh

We now need a method to create the video from the still images and delete the images to save space.

Create a script to make the video:
sudo nano /home/pi/make-video.sh

Add the following:
!/bin/bash

#DATE=$(date +"%Y-%m-%d_%H%M%S")

ffmpeg -framerate 25 -i /home/pi/camera/picture-%d.jpg /home/pi/Video-$(date +%d-%m-%Y-%H-%M).mp4

rm /home/pi/camera/*.jpg


Press CTRL + X, followed by Y to close the file and save it:

Make the script executable:
sudo chmod +x make-video.sh

Executing this script uses ffmpeg to create a video file at 25fps using the current date and time in the filename. It then removes all .jpg files from the folder.

Finally we create a cronjob to create the video periodically:

crontab -e

Add the following:
0 8 * * * sh /home/pi/camera/make-video.sh

This will run the script at 8am every day.

You can also create a cronjob on p1 to automate the other script.

crontab -e

Add the following:

15 8 * * * sh /home/pi/camera/camera.sh

Thursday, 18 February 2021

BIG-IP

! Load factory default cofig
tmsh load /sys config default

! Run management interface setup utility
config# config



Tuesday, 2 February 2021

F5 BIGIP Ansible

See here for more info:

https://github.com/F5Networks/f5-ansible/blob/devel/examples/0000-getting-started/playbook.yaml

Directory structure looks like this:

├── inventory

│   └── hosts

└── playbook.yaml

"hosts" file contains a single entry "localhost" (the F5 IP address is defined within the script).


<save the below to playbook.yaml>

 ---


- name: Create a VIP, pool and pool members

  hosts: all

  connection: local


  vars:

    provider:

      password: admin

      server: 192.168.1.245

      user: admin

      validate_certs: no

      server_port: 443


  tasks:

    - name: Create a pool

      bigip_pool:

        provider: "{{ provider }}"

        lb_method: ratio-member

        name: web

        slow_ramp_time: 120

      delegate_to: localhost


    - name: Add members to pool

      bigip_pool_member:

        provider: "{{ provider }}"

        description: "webserver {{ item.name }}"

        host: "{{ item.host }}"

        name: "{{ item.name }}"

        pool: web

        port: 80

      with_items:

        - host: 10.10.10.10

          name: web01

        - host: 10.10.10.20

          name: web02

      delegate_to: localhost


    - name: Create a VIP

      bigip_virtual_server:

        provider: "{{ provider }}"

        description: foo-vip

        destination: 172.16.10.108

        name: vip-1

        pool: web

        port: 80

        snat: Automap

        profiles:

          - http

          - clientssl

      delegate_to: localhost


Friday, 9 November 2018

Script to create tenant / app profile / EPG

#   Note that this script expects HTTP port 80 on the APIC, which is off by default.
# To enable HTTP in the APIC, navigate to FABRIC, FABRIC POLICIES Pod Policies     Policies   Management Acces    default  then enable HTTP
import requests
import json

def get_cookies(apic):
    username = 'admin'
    password = 'ciscoapic'
    url = apic + '/api/aaaLogin.json'
    auth = dict(aaaUser=dict(attributes=dict(name=username, pwd=password)))
    authenticate = requests.post(url, data=json.dumps(auth), verify=False)
    return authenticate.cookies

def add_tenant(apic,cookies):
    jsondata = {"fvTenant":{"attributes":{"dn":"uni/tn-acme","name":"acme","rn":"tn-acme","status":"created"},"children":[]}}
    result = requests.post('{0}://{1}/api/node/mo/uni/tn-acme.json'.format(protocol,host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

def get_tenants(apic,cookies):
    uri = '/api/class/fvTenant.json'
    url = apic + uri
    req = requests.get(url, cookies=cookies, verify=False)
    response = req.text
    return response

def add_application_profile(apic,cookies):
    jsondata = {"fvAp":{"attributes":{"dn":"uni/tn-acme/ap-Accounting","name":"Accounting","rn":"ap-Accounting","status":"created"},"children":[]}}
    result = requests.post("{0}://{1}/api/node/mo/uni/tn-acme/ap-Accounting.json".format(protocol, host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

def add_EPG1(apic,cookies):
    jsondata = {"fvAEPg":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Payroll","name":"Payroll","rn":"epg-Payroll","status":"created"},"children":[{"fvCrtrn":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Payroll/crtrn","name":"default","rn":"crtrn","status":"created,modified"},"children":[]}}]}}
    result = requests.post("{0}://{1}/api/node/mo/uni/tn-acme/ap-Accounting/epg-Payroll.json".format(protocol, host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

def add_EPG2(apic,cookies):
    jsondata = {"fvAEPg":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Bills","name":"Bills","rn":"epg-Bills","status":"created"},"children":[{"fvCrtrn":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Bills/crtrn","name":"default","rn":"crtrn","status":"created,modified"},"children":[]}}]}}
    result = requests.post("{0}://{1}/api/node/mo/uni/tn-acme/ap-Accounting/epg-Bills.json".format(protocol, host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

if __name__ == "__main__":
    protocol = 'http'
    host = '192.168.10.1'
    apic = '{0}://{1}'.format(protocol, host)
    cookies = get_cookies(apic)
    add_tenant(apic,cookies)
    add_application_profile(apic,cookies)
    add_EPG1(apic,cookies)
    add_EPG2(apic,cookies)
    rsp = get_tenants(apic,cookies)

rsp_dict = json.loads(rsp)
tenants = rsp_dict['imdata']

for tenant in tenants:
    print tenant['fvTenant']['attributes']['name']

Monday, 5 November 2018

Python

Integers and Floats

Integer = number
int (pi) ==3
Float = decimal number
float(answer) == 42.0

Strings

String = text

"Hello World"

"hello" .capitalize() == "Hello"

"hello" .replace("e" ,"a" ) == "hallo"
"hello" .isalpha() == True
"123" .isdigit() == True 
"some,csv,values" .split(",") == ["some", "csv", "values"]


name = "Martin"machine = "Hal"print ("Nice to meet you {0}. I am {1}".format(name,machine))

Boolean and None

python_course = True
int (python_course) == 1

If Statements

number = 5
if number == 5:
      print ("Number is 5")
else:
      print ("Number is NOT 5")

Lists (mutable, ordered)

student_names = ["John", "Paul", "George","Ringo"]
student_names[0] == "John"
! List values start at 1
student_names[-1] == "Ringo"
! Minus sign reads values from the right of the list
len(student_names) == 4
del student_names[2]
! Remove George from list

Dictionaries (mutable, associative array)

Device = {"hostname":"router1","OS":"v15.5,"location":"London")

Tuple (sequence of immutable objects)

Credentials = ("hostname","username","password")

Sets (unordered collection of unique and immutable objects) 

Loops

for name in student_names
     print ("Student name is {0}" .format(name))

For Loop

student_names = ["John", "Paul", "George","Ringo"]
for name in student_names:
  if name == "John":
  print("Found him! " + name)
  break 



Challenges:

Challenge 1:

#!/usr/bin/env python2.7

def devices():
 routers = ["router1","router2","router3"]
 print routers

def security():
 credentials = {"router1":"passw0rd1","router2":"passw0rd1","router3":"passw0rd1"}
 print credentials

def combined():
 devices()
 security()

if __name__ == "__main__":
 print "The routers are:"
 devices()
 
 print "The credentials are:"
 security()

 print "All data is:"
 combined()

Wednesday, 27 June 2018

ACI Deep Dive


  • TEP address pool should not overlap with internal address space
  • /16 address space is default for TEP pool

Switch discovery
  • LLDP between switch and APIC
  • DHCP request from switch for lo0
  • ISIS between leaf and spine
  • IFM = inter fabric messaging (secured with x.509 certificates) 
  • VXLAN tunnels built for connectivity to all other leaf / spine switches


Useful Commands

! Show switches in fabric
#acidiag fnvread
#acidiag verifyapic
#acidiag avread

! NXOS like interface
#vsh
#vsh_lc
#show cli list

! overlay-1 is the "underlay"

#show ip interface vrf overlay-1
#show ip route vrf overlay-1

https://<apic-ip>/visore

#moquery

! query faults - uses http port 777
#icurl


#show system internal epm endpoint mac aaaa.bbbb.cccc

! Leaf command to ping (vrf aware unlike native linux)
#iping

! TCPDUMP can be used for control plane traffic only
#tcpdump -i eth0 

ELAM - data plane traffic capture

! See denied packet between EPGs
#show logging ip access-list internal packet-log deny
#show logging ip access-list cache deny

vzAny - contract for an EPG to consume everything in a VRF

! Like BGP debug
#show bgp event-history events


Friday, 15 February 2013

My Five Most Annoying IOS Features

That is Cisco IOS by the way - if you think this is anything to do with iphones I suggest you run along because Cisco have been calling it IOS since Apple was just a sapling.
I like Cisco IOS but there are just a few annoying "features" than continually annoy / baffle me. There are probably legitimate reasons for their existence but to me they just seem like little flaws that could be easily ironed out but we have all just learned to live with.

  1. Context sensitive help and autocomplete do not work in configuration mode
    Being lazy by nature I always type as little as I need to which is why autocomplete is great. I can type "sh int" and I get a list of the interfaces on the router. If I am not sure if that is the command I want I can hit tab and it will show me the autocomplete entry for what I have typed so far:

    R1#sh int <Press TAB>
    R1#sh interfaces


    If there are multiple autocomplete entries for what I have typed so far tab does nothing but a question mark will show me what my options are:

    R1#sh in <Press TAB>
    R1#sh in <Press TAB again, slightly harder while frowning>
    R1#sh in?
    interfaces  inventory

    That's all great. Now let's go into configuration mode. We can use the "do" command to enter exec level commands when in configuration mode:

    R1#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    R1(config)#do sh int

    This works, but only because "show interfaces" is the only autocomplete option for "sh int". Forgotten the command? Hard luck:

    R1(config)#do sh in <Press TAB>
    R1(config)#do sh in? <Press ENTER>
    LINE    <cr>
    <Bang head on keyboard - what the hell does LINE mean???>

    So you are stuck in a weird situation where, if you know the full command or the only viable autocomplete option then you can enter it, otherwise you get no help. This seems very obtuse to me - it is like IOS knows what you want but will only help you when it feels like it. Would it really be so hard to fix this?
  2. You must write the full interface name in the extended ping
    Not a huge labour but a bit irksome. When you run an extended ping and specify the source interface in the shortened form IOS gets all sniffy and makes you write the whole thing. It takes me about 4 hours for me to type "gigabitethernet"

    Protocol [ip]:
    Target IP address: 1.2.3.4
    Repeat count [5]:
    Datagram size [100]:
    Timeout in seconds [2]:
    Extended commands [n]: y
    Source address or interface: fa0/0
    Translating "fa0/0
    % Invalid source. Must use IP address or full interface name without spaces (e.g. Serial0/1)Source address or interface: fastethernet0/0
  3. Sometimes you have to add a parameter when it should really be done automatically
    Some commands only take one keyword as a parameter but IOS forces you to put it there even though there are no other options than having it - so why not put it there automatically?

    An example:

    R1(config-if)#ip nbar ?
      protocol-discovery  Enable NBAR protocol discovery

    R1(config-if)#ip nbar
    % Incomplete command.

    R1(config-if)#ip nbar ?
      protocol-discovery  Enable NBAR protocol discovery

    R1(config-if)#ip nbar protocol-discovery ?
      <cr>

    Here we have the command "ip nbar" which only takes the parameter "protocol-discovery". You can't leave it off and it is the only parameter it can take. So why not just fill it in? Like I haven't got enough to do in my busy day...
  4. Going in to configuration mode and not making changes is still logged as you making changes
    I am sure there is a good reason for this one but I can't put my finger on it. If you go in to configuration mode and then just exit out again without making any changes it is logged in the log as you having made a change. Watch this:

    R1#sh clock
    *07:11:35.710 UTC Fri Mar 1 2002
    R1#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    R1(config)#^Z
    R1#
    *Mar  1 07:11:38.986: %SYS-5-CONFIG_I: Configured from console by bob on console
    R1#sh log
    *Mar  1 07:11:38.986: %SYS-5-CONFIG_I: Configured from console by bob on console

    This is written to the log file and also added to the top of the running config. In a multi user environment this can lead to much finger pointing when things go wrong:
    dim-witted non-technical management type: Bob, it says you changed the config yesterday a few hours before that network meltdown we had.
    bob: No, I did not change anything.
    dim-witted non-technical management type: Well it says here that you were the last person to change the config
    bob: No honestly I did not change anything. I just entered configuration mode and then exited it.
    dim-witted non-technical management type: Clear your desk bob
  5. Pipe include sometimes lies
    You can use the pipe command to filter the results of a command to make it easier to read. The pipe include command says only shows the lines including a certain string except sometimes it lies. Consider this:

    R1#sh ip route | inc .1.0
    C    192.168.11.0/24 is directly connected, FastEthernet0/0
    C    192.168.1.0/24 is directly connected, FastEthernet0/0


    The string here is ".1.0" which is in the second line but not in the first. I don't know why this happens - I assume it must be ignoring the trailing . for some reason. 

Wednesday, 7 November 2012

Cisco Default Values

HSRP

Hello = 3 seconds

Dead = 10 seconds

#interface fa0
#standby <group> timers x y

Where x is a value between <1-254> seconds

Where y is a value between <2-255> seconds

#show standby


=========================

EIGRP

Hello = 5 seconds

Dead = 15 seconds 

#interface fa0

#ip hello-interval eigrp <AS> x
#ip hold-time eigrp <AS> x

Where x is a value between <1-65535> seconds


#show ip eigrp interfaces detail fa0


=========================

OSPF

Ethernet:

Hello = 10 seconds
Dead = 40 seconds
Wait = 40 seconds
Retransmit = 5 seconds
(Dead time is automatically set to 4 x the hello interval)

Non-broadcast:
Hello = 30 seconds
Dead = 120 seconds

#interface fa0

#ip ospf hello-interval x
#ip ospf dead-interval x
#ip ospf retransmit-interval x

Where x is a value between <1-65535> seconds



=========================
BGP Route Selection Criteria

1 Weight
2 Local Preference
3 Network or Aggregate
4 Shortest AS_PATH
5 Lowest origin type
6 Lowest multi-exit discriminator (MED)
7 eBGP over iBGP
8 Lowest IGP metric
9 Multiple paths
10 External paths
11 Lowest router ID
12 Minimum cluster list
13 Lowest neighbor address

=========================
Routing Administrative Distance

Connected interface0
Static route1
Enhanced Interior Gateway Routing Protocol (EIGRP) summary route5
External Border Gateway Protocol (BGP)20
Internal EIGRP90
IGRP100
OSPF110
Intermediate System-to-Intermediate System (IS-IS)115
Routing Information Protocol (RIP)120
Exterior Gateway Protocol (EGP)140
On Demand Routing (ODR)160
External EIGRP170
Internal BGP200
Unknown*255

Friday, 26 October 2012

Retrieve Cisco Config with wget

On the router or switch:

#conf t
#ip http server
#ip http authentication local
#username cisco priv 15 pass cisco

Then on your PC:

wget --user cisco --password cisco http://192.168.0.1/level/15/exec/show/running-config/view/full  -O cisco-config.txt

(substitute your IP address for 192.168.0.1). 


Show Tech-support:

wget --user cisco --password cisco http://192.168.0.1/level/15/exec/show/tech-support/CR  -O show-tech.txt

PPP Multilink


username R2 password 0 cisco
! Configure a user account with the hostname of the peer and a matching password
interface Multilink1
 ip address 1.1.1.1 255.255.255.252
 ppp multilink
 ppp multilink group 1
!
interface Serial0/1
 no ip address
 encapsulation ppp
 clock rate 2000000
 ppp authentication chap
 ppp multilink
 ppp multilink group 1
!
interface Serial0/2
 no ip address
 encapsulation ppp
 clock rate 2000000
 ppp authentication chap
 ppp multilink
 ppp multilink group 1

=====================

username R1 password 0 cisco
!
interface Multilink1
 ip address 1.1.1.2 255.255.255.252
 ppp multilink
 ppp multilink group 1
!
interface Serial0/1
 no ip address
 encapsulation ppp
 clock rate 2000000
 ppp authentication chap
 ppp multilink
 ppp multilink group 1
!
interface Serial0/2
 no ip address
 encapsulation ppp
 clock rate 2000000
 ppp authentication chap
 ppp multilink
 ppp multilink group 1

=====================


R1#show ppp multilink

Multilink1, bundle name is R2
  Username is R2
  Endpoint discriminator is R2
  Bundle up for 00:01:29, total bandwidth 4632, load 1/255
  Receive buffer limit 36000 bytes, frag timeout 1000 ms
    0/0 fragments/bytes in reassembly list
    0 lost fragments, 0 reordered
    0/0 discarded fragments/bytes, 0 lost received
    0x4 received sequence, 0x9 sent sequence
  Member links: 2 active, 0 inactive (max not set, min not set)
    Se0/1, since 00:01:29
    Se0/2, since 00:01:29
No inactive multilink interfaces


R2#show interface multilink1
Multilink1 is up, line protocol is up
  Hardware is multilink group interface
  Internet address is 1.1.1.2/30
  MTU 1500 bytes, BW 3088 Kbit/sec, DLY 100000 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  Encapsulation PPP, LCP Open, multilink Open
  Open: IPCP, CDPCP, loopback not set
  Keepalive set (10 sec)
  DTR is pulsed for 2 seconds on reset
  Last input 00:00:52, output never, output hang never
  Last clearing of "show interface" counters 00:36:36
  Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
  Queueing strategy: fifo
  Output queue: 0/40 (size/max)
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     1071 packets input, 117686 bytes, 0 no buffer
     Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
     1078 packets output, 132324 bytes, 0 underruns
     0 output errors, 0 collisions, 5 interface resets
     0 unknown protocol drops
     0 output buffer failures, 0 output buffers swapped out

#debug ppp authentication

Thursday, 25 October 2012

Switch Based Access Control

  • Control access to and from devices in the same VLAN using MAC address:
#conf t
#vlan access-map MAC_DENY 10
#action drop
#match mac address MAC_DENY_ACL

#mac access-list extended MAC_DENY_ACL

#permit host 0000.0000.0001 host 0000.0000.0002

#vlan filter MAC_DENY vlan-list 100


This means traffic from 0000.0000.0001 to 0000.0000.0002 will be dropped in VLAN 100



  • Control access to and from devices in the same VLAN using IP address:
#conf t

#vlan access-map IP_DENY 10
#action drop
#match ip address 150

#access-list 150 permit ip host 192.168.199.1 host 192.168.199.2

#vlan filter IP_DENY vlan-list 100

This means traffic from 192.168.199.1 to  192.168.199.2 will be dropped in VLAN 100

Thursday, 2 August 2012

RIP over GRE Tunnel with QoS Configuration

In this configuration I have 4 routers R1, R2, R3 and R4. R2 and R3 run External BGP. There is also a GRE tunnel running between R2 and R3 over which we run RIP. R1 and R4 also run RIP. QoS configuration is applied to the tunnel interface via a service policy which shapes the traffic based on which access list it matches. 
This configuration was made on GNS3 with 2691 routers running C2691-ADVENTERPRISEK9-M. 
Irrelevant parts of the config below have been omitted for brevity.


=~=~=~=~=~=~=~=~=~=~=~= R1=~=~=~=~=~=~=~=~=~=~=~=
hostname R1
!
! Two loopback interfaces to allow us to differentiate the traffic for the class-maps
interface Loopback0
 ip address 1.1.1.1 255.255.255.255
!
interface Loopback1
 ip address 11.11.11.11 255.255.255.255
!
interface FastEthernet0/0
 ip address 192.168.1.1 255.255.255.0
 speed 100
 full-duplex
!
interface FastEthernet0/1
 ip address 192.168.0.1 255.255.255.0
 duplex auto
 speed auto
!
! We run RIP to learn routes from R2
router rip
 version 2
 network 1.0.0.0
 network 11.0.0.0
 network 192.168.0.0
 network 192.168.1.0
 no auto-summary
!

=~=~=~=~=~=~=~=~=~=~=~= R2=~=~=~=~=~=~=~=~=~=~=~=
hostname R2
We create two class-maps which match named access lists
class-map match-all CMAP_MATCH11
 match access-group name MATCH11
class-map match-all CMAP_MATCH1
 match access-group name MATCH1
!
We have a policy-map which assigns 8K and 512K to each respective class-map.
! The overall method of the policy maps says, if you match ACL MATCH1 then you 
! will be allocated 8K of bandwidth, if you match ACL MATCH11 then you will get 
! 512K of bandwidth
policy-map TUNNEL
 class CMAP_MATCH1
  shape average 8000
 class CMAP_MATCH11
  shape average 512000
 class class-default
!
interface Loopback0
 ip address 2.2.2.2 255.255.255.255
We have a tunnel interface with a service policy applied
interface Tunnel0
 ip address 10.0.0.1 255.255.255.0
 tunnel source Loopback0
 tunnel destination 3.3.3.3
 service-policy output TUNNEL
!
interface FastEthernet0/0
 ip address 192.168.1.254 255.255.255.0
 speed 100
 full-duplex
!
interface FastEthernet0/1
 ip address 192.168.2.1 255.255.255.0
 speed 100
 full-duplex
We run RIP over the LAN and tunnel interfaces only
router rip
 version 2
 passive-interface default
 no passive-interface FastEthernet0/0
 no passive-interface Tunnel0
 network 10.0.0.0
 network 192.168.1.0
 no auto-summary
! BGP to R3 to carry the tunnel
router bgp 1
 no synchronization
 bgp log-neighbor-changes
 redistribute connected
 neighbor 192.168.2.254 remote-as 2
 neighbor 192.168.2.254 next-hop-self
 no auto-summary
!
! ACLs to match the source and destination loopbacks
ip access-list extended MATCH1
 permit ip host 1.1.1.1 host 4.4.4.4
ip access-list extended MATCH11
 permit ip host 11.11.11.11 host 44.44.44.44
!
!
=~=~=~=~=~=~=~=~=~=~=~= R3 =~=~=~=~=~=~=~=~=~=~=~=
hostname R3
!
!
! Class-map, policy-map and ACLs are basically the reverse of R2
class-map match-all CMAP_MATCH44
 match access-group name MATCH44
class-map match-all CMAP_MATCH4
 match access-group name MATCH4
class-map match-all MyClass
!
!
policy-map TUNNEL
 class CMAP_MATCH4
  shape average 8000
 class CMAP_MATCH44
  shape average 512000
 class class-default
!
interface Loopback0
 ip address 3.3.3.3 255.255.255.255
!
interface Tunnel0
 ip address 10.0.0.2 255.255.255.0
 tunnel source Loopback0
 tunnel destination 2.2.2.2
 service-policy output TUNNEL
!
interface FastEthernet0/0
 ip address 192.168.2.254 255.255.255.0
 speed 100
 full-duplex
!
interface FastEthernet0/1
 ip address 192.168.3.1 255.255.255.0
 speed 100
 full-duplex
!
router rip
 version 2
 passive-interface default
 no passive-interface FastEthernet0/1
 no passive-interface Loopback0
 no passive-interface Tunnel0
 network 10.0.0.0
 network 192.168.3.0
 no auto-summary
!
router bgp 2
 no synchronization
 bgp log-neighbor-changes
 redistribute connected
 neighbor 192.168.2.1 remote-as 1
 neighbor 192.168.2.1 next-hop-self
 no auto-summary
!
ip access-list extended MATCH4
 permit ip host 4.4.4.4 host 1.1.1.1
ip access-list extended MATCH44
 permit ip host 44.44.44.44 host 11.11.11.11
!

=~=~=~=~=~=~=~=~=~=~=~= R4 =~=~=~=~=~=~=~=~=~=~=~=
hostname R4
Again, R4 is basically a mirror of R1
interface Loopback0
 ip address 4.4.4.4 255.255.255.255
!
interface Loopback1
 ip address 44.44.44.44 255.255.255.255
!
interface FastEthernet0/0
 ip address 192.168.3.254 255.255.255.0
 speed 100
 full-duplex
!
interface FastEthernet0/1
 ip address 192.168.4.1 255.255.255.0
 speed 100
 full-duplex
!
router eigrp 1
 network 0.0.0.0
 no auto-summary
!
router rip
 version 2
 network 44.0.0.0
 network 0.0.0.0
 no auto-summary
!

=~=~=~=~=~=~=~=~=~=~=~= Verification~=~=~=~=~=~=~=~=~=~=~=
A ping from R1 lo0 to R4 lo0 goes via the tunnel interface
R1#traceroute 4.4.4.4 source 1.1.1.1

Type escape sequence to abort.
Tracing the route to 4.4.4.4

  1 192.168.1.254 48 msec 24 msec 16 msec
  2 10.0.0.2 44 msec 44 msec 28 msec
  3 192.168.3.254 96 msec *  68 msec

An extended ping with a larger packet size - note the average RTT is 482ms
R1#ping 4.4.4.4 source 1.1.1.1 size 500 rep 50

Type escape sequence to abort.
Sending 50, 500-byte ICMP Echos to 4.4.4.4, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (50/50), round-trip min/avg/max = 40/482/1008 ms

An extended ping but this time we specify the other loopbacks as source and destination so we hit the QoS policy with a higher bandwidth - note the much better average RTT of 58ms
R1#ping 44.44.44.44 so 11.11.11.11 size 500 rep 50

Type escape sequence to abort.
Sending 50, 500-byte ICMP Echos to 44.44.44.44, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (50/50), round-trip min/avg/max = 20/58/92 ms

On R2 if we issue the policy map interface command we see the following. Note how we see delayed packets on the CMAP_MATCH1 class and none on the CMAP_MATCH11 class.
R2#sh policy-map interface
 Tunnel0

  Service-policy output: TUNNEL

    Class-map: CMAP_MATCH1 (match-all)
      361 packets, 184332 bytes
      5 minute offered rate 0 bps, drop rate 0 bps
      Match: access-group name MATCH1
      Traffic Shaping
           Target/Average   Byte   Sustain   Excess    Interval  Increment
             Rate           Limit  bits/int  bits/int  (ms)      (bytes)
             8000/8000      2000   8000      8000      1000      1000

        Adapt  Queue     Packets   Bytes     Packets   Bytes     Shaping
        Active Depth                         Delayed   Delayed   Active
        -      0         361       175776    174       87000     no

    Class-map: CMAP_MATCH11 (match-all)
      460 packets, 239040 bytes
      5 minute offered rate 0 bps, drop rate 0 bps
      Match: access-group name MATCH11
      Traffic Shaping
           Target/Average   Byte   Sustain   Excess    Interval  Increment
             Rate           Limit  bits/int  bits/int  (ms)      (bytes)
          5120000/5120000   32000  128000    128000    25        16000

        Adapt  Queue     Packets   Bytes     Packets   Bytes     Shaping
        Active Depth                         Delayed   Delayed   Active
        -      0         460       228000    0         0         no

    Class-map: class-default (match-any)
      139 packets, 15568 bytes
      5 minute offered rate 0 bps, drop rate 0 bps
      Match: any