Cisco IOS: Vorbereitung einer DAI (Dynamic ARP Inspection) Implementierung
Dynamic ARP Inspection (DAI) ist ein Mechanismus in Cisco-Switchen (ab Catalyst 2960), der ARP-Pakete auf Fälschungen untersucht. Dadurch sollen beispielsweise ARP-Spoofing-Attacken verhindert werden, bei denen ein Angreifer ARP-Antworten sendet, in denen er eine fremde IP mit der eigenen MAC-Adresse verbindet, um sich in die Kommunikation einzuklinken.
Wenn DAI auf einem Cisco-Switch aktiviert wird, vergleicht der Switch bei den ARP-Paketen, ob die MAC-Adresse auch zu der IP-Adresse passt. Für diesen Vergleich muss der Switch natürlich die korrekte Zuordnung kennen. Diese lernt er normalerweise über DHCP-Snooping, bei dem die DHCP-Kommunikation beobachtet wird und der Switch “sieht”, welche IP einem Gerät mit einer bestimmten MAC-Adresse zugeordnet wurde.
Weitere Erklärungen zu DAI:
Cisco.com: Configuring Dynamic ARP Inspection
LAN Switch Security: What Hackers Know About Your Switches
Am einfachsten ist DAI zu implementieren, wenn alle Geräte in einem VLAN ihre IP per DHCP bekommen. In diesem Fall kann der Switch die IP-zu-MAC-Datenbank alleine aufbauen und benötigt keine statischen Einträge. Bei meinen letzten Implementierungen hat sich aber gezeigt, dass die Aussage der PC-Admins, dass in diesem Netz nur DHCP-Clients seien, nicht unbedingt heißen muss, dass nicht manche Geräte doch eine statische Konfiguration haben … ![]()
Deshalb ist es sinnvoll, vorher ein paar Checks durchzuführen, um diese Geräte aufzuspüren. Eine Möglichkeit ist, die Einträge in der ARP-Tabelle des L3-Switches mit den Einträgen in der DHCP-Snooping-Tabelle zu vergleichen. Wenn in der ARP-Tabelle ein Eintrag vorhanden ist (und dies ist nicht das Gateway), es aber zu dieser IP keinen Eintrag in der DHCP-Tabelle gibt, dann besteht die Chance, dass dieser PC doch eine statische IP-Konfiguration hat.
Um diesen Vergleich zu erleichern, habe ich das folgende –sehr simpel gehaltene– Python-Script geschrieben.
Ein Beispiel zur Benutzung des Scriptes. Für das Vlan63 soll die ARP-Tabelle mit der DHCP-Snooping-Tabelle verglichen werden:
- Sicherstellen, dass die ARP-Tabelle des L3-Switches aktuell ist
- Ausgeben der ARP-Tabelle des Cisco-L3-Switches:
- Ausgeben der DHCP-Snooping-Tabelle des Cisco-Access-Switches, auf dem DAI konfiguriert werden soll:
- Auswerten der beiden Dateien mit dai-check.py:
Wenn Geräte dabei sind, die häufiger für ein paar Stunden inaktiv sind, dann könnte es sein, dass für diese kein Eintrag in der ARP-Tabelle enthalten sind. Deshalb pinge ich alle Geräte in dem Vlan einmal an:
karstens-macbook-pro:~ karsten$ nmap -sP 192.168.63.0/24
Starting Nmap 4.76 ( http://nmap.org ) at 2009-08-28 18:09 CEST
...
Host 192.168.63.201 appears to be up.
Host 192.168.63.254 appears to be up.
Nmap done: 256 IP addresses (174 hosts up) scanned in 48.12 seconds
karstens-macbook-pro:~ karsten$
L3-Switch>term len 0
L3-Switch>sh arp | i Vlan63
Internet 192.168.63.254 - 001a.b1f3.9ab2 ARPA Vlan63
Internet 192.168.63.201 137 001c.79a5.ad41 ARPA Vlan63
Internet 192.168.63.79 213 0022.63a9.6384 ARPA Vlan63
...
Diese Liste wird abgespeichert; z.B. als dai-arp.txt
Access-Switch>term len 0
Access-Switch>sh ip dhcp snooping binding vlan 63 | i dhcp-snooping
00:0F:FE:5C:E0:CF 192.168.63.83 223101 dhcp-snooping 63 FastEthernet2/0/28
00:1C:79:A5:AD:41 192.168.63.201 233322 dhcp-snooping 63 FastEthernet1/0/28
...
Auch diese Liste wird abgespeichert; z.B. als dai-dhcp.txt. Das “| i dhcp-snooping” ist deshalb wichtig, weil das Script nur die reine Tabelle ohne Header erwartet. Das könnte/sollte ich sicher einmal verbessern. Wenn das Vlan sich über mehrere Switche erstreckt, werden diese show-Ausgaben einfach in einer Datei gesammelt.
karstens-macbook-pro:~ karsten$ ./dai-check.py dai-arp.txt dai-dhcp.txt
['Internet', '192.168.63.254', '-', '001a.b1f3.9ab2', 'ARPA', 'Vlan63']
['Internet', '192.168.63.206', '137', '001c.79a4.af26', 'ARPA', 'Vlan63']
Das Script dai-check.py sucht jetzt zu jeder IP aus der ARP-Tabelle, ob es diese IP auch in der DHCP-Tabelle gibt. Am Ende wird eine Liste der Einträge aus der ARP-Tabelle ausgegeben, zu denen es keine Entsprechung in der DHCP-Tabelle gibt. Im obigen Beispiel war das die 192.168.63.254 (das Default-Gateway) und die 192.168.63.206, die tatsächlich eine statische Konfiguration hat.
Das Script ist sehr rudimentär, so gibt es beispielsweise keinerlei Checks, ob die Tabellen auch wirklich die richtigen Daten beinhalten. Wer falsche Daten eingibt, wird vermutlich auch ein falsches Ergebnis erhalten!
Per Tunnel ins IPv6-Internet
Da bei vielen DSL-Anbietern IPv6 ein Fremdwort ist, muss man sich oft mit einem Tunnel behelfen. Die Erweiterung einer IOS-Umgebung (Router und Switch) um IPv6 ist zwar nicht sehr aufwendig, umfasst aber doch etliche Schritte, die ich hier beispielhaft zusammenfasse.
Dabei gehe ich von der folgenden Umgebung aus:

Beispiel-Netzwerk
Die notwendigen Schritte:
- Registrieren eines IPv6-Tunnels bei einem Tunnel-Broker:
- Tunnelkonfiguration auf dem IOS-Router
- Anpassungen bei der Verwendung dynamischer IP-Adressen
- Konfigurieren der Firewall
- Konfigurieren der weiteren Router-Interfaces
- Einbinden des internen Switches
Sehr leicht hat man die Einrichtung bei dem (kostenlosen) Anbieter Hurricane Electric: http://tunnelbroker.net/
Dort muss man sich registrieren und bekommt seine Zugangsdaten per Mail zugesendet. Nachdem man sich angemeldet hat, kann man einen neuen Tunnel konfigurieren:

In dem dann folgenden Dialog wird die eigene IPv4-Adresse eingetragen. Weiterhin wird angegeben, wo der Tunnel im Internet terminiert werden soll. In Deutschland bietet sich evtl. Frankfurt an.

Um den Tunnel einrichten zu können, muss der Router, über den man sich ins Internet verbindet, anpingbar sein! Wenn das gewährleistet ist, kann der Dialog mit “Submit” abgeschlossen werden.
In der dann folgenden Bestätigung wählt man die “Tunnel Details” aus, wo man sich noch Beispielkonfigurationen für verschiedene Systeme ausgeben lassen kann. Standardmäßig bekommt man ein /64er Netz. Wenn man hinter dem Router noch mehr Infrastruktur hat (wie in diesem Beispiel), muss man noch das “Routed /48″ aktivieren:

Die grundsätzliche Router-Konfiguration ist recht simpel und kann als Vorlage von der obigen Webseite generiert werden:
interface Tunnel0
description Hurricane Electric IPv6 Tunnel Broker
no ip address
ipv6 address [die zugewiesene /64-Adresse ]
ipv6 enable
tunnel source Dialer0 !!! <<-----
tunnel destination [Der ausgewählte Tunnelserver]
tunnel mode ipv6ip
end
!
ipv6 route ::/0 Tunnel0
Abweichend von der vorgeschlagenen Konfiguration habe ich die "tunnel source" auf das verwendete Dialer-Interface geändert. Damit ist die Konfig unabhängig von der konfigurierten oder dynamisch empfangenen IP-Adresse.
IPv6 muss auch noch global eingeschaltet werden:
ipv6 unicast-routing
ipv6 cef
Die Access-Liste auf dem Public-Interface (Dialer0 bei mir) muss wie oben beschrieben anpingbar sein. Das lässt sich auch auf die richtige Source-IP (66.220.2.74) eingrenzen. Weiterhin muss das IP-Protokoll 41 für den Tunnel erlaubt sein:
gw#sh ip access-lists interface Dialer 0 | i 41|icmp
40 permit icmp any any echo (12 matches)
50 permit 41 any any (3252 matches)
Wenn man eine dynamsiche IP-Adresse hat, dann muss der Tunnel für jede neue IP neu registriert werden. Sehr einfach geht das mit einem EEM-Script von der Cisco EEM Scripting Community (danke an meinen Blogger-Kollegen Jens Link für den Tip):
Dieses Script wird heruntergeladen und muss um die eigenen Tunnel-Parameter ergänzt werden:
set user "USER_ID"
set md5pass "MD5-PASSWORD"
set tid "TUNNEL-ID"
Die User-ID ist nicht der Login sondern die Zeichenkette, die nach dem Login auf der Tunnelbroker.net-Seite zu sehen ist (32 Stellen).
Die Tunnel-ID ist die "Global Tunnel ID" aus den Tunnel-Details der Tunnelbroker.net-Seite.
Das MD5-Password ist das eigene Password, das mit MD5 gehashed wird. Auf dem Mac kann dafür das Programm "md5" verwendet werden, jedes andere anständige Betriebssystem bringt sicher ein entsprechendes Tool mit:
karstens-macbook-pro:~ karsten$ md5 -s "Mein Password"
MD5 ("Mein Password") = 4d3b73493102972e8b989fa5b563b150
karstens-macbook-pro:~ karsten$
Dieses Script wird ins Flash des Routers geladen und muss für den Embedded Event-Manager (EEM) aktiviert werden:
event manager directory user policy "flash:/"
event manager policy ipv6-tunnel-update.tcl type user
Der erste Befehl gibt an, wo die Scripte liegen, der zweite meldet das gerade hochgeladene Script im System an.
Als Nächstes steuert man, wann man die Aktualisierung der IP vornehmen möchte. Dafür habe ich das Script so modifiziert, dass es die Syslog-Ausgaben überwacht und immer dann aktiv wird, wenn der Dialer an das Ausgangs-Interface gebunden wird (ich habe nur einen Dialer im System, daher kann ich das recht einfach halten):
::cisco::eem::event_register_syslog pattern "%DIALER-6-BIND" priority all
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
set url "http://ipv4.tunnelbroker.net"
set php "ipv4_end.php"
set ip "ipv4b=AUTO"
set user "USER"
set md5pass "PASS"
set tid "TUNNEL-ID"
append url "\/$php\?$ip\&pass=$md5pass\&user_id=$user\&tunnel_id=$tid"
after 5000
if {[catch {http::geturl $url -queryblocksize 50 -type "text/plain" } token]} {
action_syslog priority info msg "http request failed"
} else {
action_syslog priority info msg "Response: [http::data $token]"
}
exit 0
Damit wird die neue IP-Adresse auch bei einem Router-Neustart registriert, was das Original-Script nicht macht.
Natürlich wird man auch für IPv6 eine Firewall aktivieren. Hier offenbart sich dann leider das Grauen bei Cisco. Zum einen unterstützt die Zone-Based-Firewall kein IPv6, und auch die traditionelle IOS-Firewall (CBAC) unterstützt nur TCP, UDP, ICMP und FTP. Keine weiteren Protokolle und auch keine Erweiterungen, wie das Inspizieren von Router-eigenem Traffic.
Als erstes wird die FW-Policy angelegt und im Tunnel aktiviert:
ipv6 inspect name FW tcp
ipv6 inspect name FW udp
ipv6 inspect name FW icmp
ipv6 inspect name FW ftp
!
interface Tunnel0
ipv6 inspect FW out
Als Nächstes muss der eingehende Traffic gefiltert werden. Dabei muss man aufpassen, kein einfaches "deny ipv6 any any" zu konfigurieren, da dann das Neighbor-Discovery nicht mehr funktioniert. So könnte es aber aussehen:
ipv6 access-list OUTSIDE-IN-v6
permit icmp any any nd-na
permit icmp any any nd-ns
deny ipv6 any any
!
interface Tunnel0
ipv6 traffic-filter OUTSIDE-IN-v6 in
Aus dem zugewiesenen /48er Netz wird jedem Netz ein Subnet zugewiesen. Welche Subnet-Adressen man nehmen könnte, habe ich hier schon mal angedeutet. Da alle diese Netze die ersten 48 Bit gemeinsam haben, kann man sich die Konfiguration mit Hilfe der "General-Prefixes" erleichtern. Diese haben einen Namen (hier HE1) und beinhalten die ersten 48 Bit der IP-Adresse.
ipv6 general-prefix HE1 2001:aaaa:bbbb::/48
Auf den Interfaces kann bei der Konfiguration der IP-Adressen dieser Prefix referenziert werden:
interface Vlan250
ipv6 address HE1 ::250:0:0:0:1/64
ipv6 enable
Mit dieser Konfig kündigt sich der Router automatisch an, und der PC sollte sich mit einer IPv6-Adresse selbst konfigurieren. Die Funktion kann per Ping ("ping6 ipv6.google.com") oder per Webbrowser ("http://ip6.me") überprüft werden.
Um auf dem verwendeten Cisco Catalyst 3560 IPv6 konfigurieren zu können, muss der Switch erst vorbereitet werden. Das Default-"Switch Database Management-Template" unterstützt kein IPv6:
c3560(config)#sdm prefer dual-ipv4-and-ipv6 default
Je nachdem, was man mit seinem Catalyst alles machen möchte, ist evtl. auch ein anderes Template nötig. Diese sind im Configuration-Guide beschrieben. Dieser Befehl taucht später nicht in der Konfiguration auf, kann aber mit "sh sdm prefer" kontrolliert werden.
Der Rest der Konfiguration ist dann dem Router sehr ähnlich. IPv6 aktivieren, General-Prefix konfigurieren und Interfaces mit einer IPv6-Adresse versehen:
ipv6 general-prefix HE1 2001:aaaa:bbbb::/48
ipv6 unicast-routing
!
interface Vlan250
ipv6 address HE1 ::250:0:0:0:2/64
!
interface Vlan255
ipv6 address HE1 ::255:0:0:0:1/64
Der Router muss jetzt natürlich noch die internen Netze lernen und der Switch eine Default-Route bekommen. In einem kleinen Netz reichen dafür ohne weiteres statische Routen, die mit "ipv6 route" anstelle "ip route" konfiguriert werden. Bei Bedarf kann man natürlich auch RIP, OSPF, EIGRP oder IS-IS benutzen.
VPNs zwischen Standorten mit überlappenden Adressen
Gerade habe ich eine Anfrage bekommen, wie man denn Netze verbinden kann, wenn auf beiden Seiten der gleiche Adress-Bereich verwendet wird. Als Lösung gibt es verschiedene Ansätze:
- Readressierung
- Erweiterung des Netzes um IPv6
- Double-NAT zwischen den Netzen
Je nachdem wie gut das Netz gepflegt ist, muss das nicht ein zu großer Aufwand sein. Spätestens jetzt könnte das ein Grund sein, um DHCP und DNS konsequent umzusetzen. Wenn die überlappenden Adress-Bereiche durch einen Firmen-Zusammenschluss zustande gekommen sind, dann wird es wohl hierauf hinauslaufen.
Wenn man sich noch nicht mit IPv6 beschäftigt hat, wird dies sicher am längsten dauern um implementiert zu werden. Aber dann sollte die Wahrscheinlichkeit für überlappende Netze relativ klein sein.
Hierbei werden die mehrfach verwendeten Netze per NAT verborgen. Je nachdem wie viele Standorte den gleichen Adress-Bereich verwenden, kann die Konfiguration und auch das Management dieser Lösung etwas “eklig” werden. Aber gerade wenn unterschiedliche Firmen verbunden werden sollen, ist dies oft die verwendete Lösung.
Dieser Artikel beschreibt die Konfiguration dieses Ansatzes in Verbindung mit VPN-Tunneln.
Das Ausgangs-Szenario:

An beiden Standorten wird das selbe IP-Netz verwendet. Die Lösung beinhaltet, dass beide Standorte ihre IP-Netze per NAT hinter einem anderen Netz “verbergen”. Dieses neue Netz wird dann verwendet, um auf die Geräte der anderen Seite zuzugreifen.
Um die Kombination von NAT und IPSec zu verstehen, muss man sich einfach bewusst sein, in welcher Reihenfolge im IOS die verschiedenen Funktionen abgearbeitet werden: NAT Order of Operation

Wie man sieht, werden die Daten genatted, bevor sie verschlüsselt werden und auf der anderen Seite entschlüsselt, bevor NAT angewendet wird.
Für jede Seite wird jetzt ein freies Netz gewählt (hier 10.111.111.0/24 und 10.222.222.0/24):

Die Source-Adressen des linken Netzes werden in 10.111.111.x übersetzt, die Source-Adressen des rechten Netzes in 10.222.222.x.
Die (relevante) Konfiguration der zwei Router sieht folgendermaßen aus:
hostname R1
crypto isakmp policy 1
encr aes 256
authentication pre-share
group 5
crypto isakmp key Yes,ThisKeyIsNotReallySecret,LongAndRandom address 192.168.2.2
!
crypto ipsec transform-set ESP-AES256-SHA esp-aes 256 esp-sha-hmac
!
crypto map VPN 1 ipsec-isakmp
set peer 192.168.2.2
set transform-set ESP-AES256-SHA
match address CRYPTO-TO-SITE-2
!
interface FastEthernet0/0
description LAN
ip address 10.10.10.1 255.255.255.0
ip nat inside
!
interface Serial1/0
description Connection to Internet
ip address 192.168.1.2 255.255.255.0
ip nat outside
crypto map VPN
!
ip route 0.0.0.0 0.0.0.0 192.168.1.1
!
ip nat inside source static network 10.10.10.0 10.111.111.0 /24
!
ip access-list extended CRYPTO-TO-SITE-2
permit ip 10.111.111.0 0.0.0.255 10.222.222.0 0.0.0.255
hostname R2
!
crypto isakmp policy 1
encr aes 256
authentication pre-share
group 5
crypto isakmp key Yes,ThisKeyIsNotReallySecret,LongAndRandom address 192.168.1.2
!
crypto ipsec transform-set ESP-AES256-SHA esp-aes 256 esp-sha-hmac
!
crypto map VPN 1 ipsec-isakmp
set peer 192.168.1.2
set transform-set ESP-AES256-SHA
match address CRYPTO-TO-SITE-1
!
interface FastEthernet0/0
description LAN
ip address 10.10.10.1 255.255.255.0
ip nat inside
!
interface Serial1/0
description Connection to Internet
ip address 192.168.2.2 255.255.255.0
ip nat outside
crypto map VPN
!
ip route 0.0.0.0 0.0.0.0 192.168.2.1
!
ip nat inside source static network 10.10.10.0 10.222.222.0 /24
!
ip access-list extended CRYPTO-TO-SITE-1
permit ip 10.222.222.0 0.0.0.255 10.111.111.0 0.0.0.255
Wenn aus dem linken Netz das rechte erreicht werden soll, muss natürlich die NAT-Adresse genommen werden. Bei einem Ping vom linken LAN-Interface zum rechten LAN-Interface sieht das dann folgendermaßen aus:
R1#ping 10.222.222.1 source fastEthernet 0/0 rep 1
Type escape sequence to abort.
Sending 1, 100-byte ICMP Echos to 10.222.222.1, timeout is 2 seconds:
Packet sent with a source address of 10.10.10.1
!
Success rate is 100 percent (1/1), round-trip min/avg/max = 32/32/32 ms
R1#
*Mar 1 00:49:23.527: ICMP: echo reply rcvd, src 10.222.222.1, dst 10.10.10.1
R2#
*Mar 1 00:49:23.319: ICMP: echo reply sent, src 10.10.10.1, dst 10.111.111.1
Ein entscheidender Nachteil dieser Methode ist, dass diese Adress-Übersetzung immer durchgeführt wird und ein Router mit dieser Konfiguration nicht mehr sinnvoll für andere Verbindungen verwendet werden kann. Diese Translation dürfte eigentlich nur verwendet werden, wenn das gegenüberliegende NAT-Netz angesprochen wird.
Diese Bedingung — die auf der PIX/ASA per Policy-NAT einfach umzusetzen ist — würde auf einem IOS-Router mit einer Route-Map beschrieben werden. Diese Route-Maps können aber leider in einer statischen Translation nicht verwendet werden, wenn ganze Netze übersetzt werden.
Cisco IOS: Embedded Packet Capture
Viele Cisco-Geräte erlauben es, direkt auf der Netzwerk-Schnittstelle Pakete mitzuschneiden. Wie das mit der PIX/ASA geht habe ich schon vor längerer Zeit beschrieben.
Seit IOS 12.4(20)T geht das auch auf dem Router. Steffen Lehmann von Systema hat dazu eine kleine Einführung gerschrieben und sie mir zur Verfügung gestellt:
Ab 12.4(20)T kann ohne großen Aufwand ein Router Interface gespiegelt werden und per ftp/tftp der Output im Wireshark kompatiblen Format exportiert werden.
Dies funktioniert auch für SUB Interfaces auf einem 802.1q Trunk .
Die Konfguration
- Erstellen des Buffers
- Erstellen des Capture Point
- Zuordnung Buffer – Capture Point
- Start des Capture
- Monitoring
- Beenden des Capture
- Kopieren des Capture File auf externen Server
Hier wird der das Puffer File definiert, welches für die „gedumpten“ Pakete verwendet wird.
Router#monitor capture buffer >Buffer Filename<

Damit wird definiert, welche Source für eine bestimmte Session (Capture Point) genutzt wird.
Router#monitor capture point ip cef >CapturePointName< >IF Name< >Richtung<

Router#monitor capture point associate >CapturePointName< >Buffer Filename<
![]()
Router#monitor capture point start >CapturePointName<
![]()
Um festzustellen, wie viele Pakete schon gemonitort wurden, kann mit folgendem Kommando nachgesehen werden...
Router#show monitor capture buffer > Buffer Filename<

Router#monitor capture point stop >CapturePointName<
Router#monitor capture buffer >Buffer Filename< export tftp://>IPADRESSE>/>Dateiname<

Jetzt kann die Datei auf dem remote Rechner mit Wireshark geöffnet und analysiert werden.
Cisco IOS autostate
Auf Routern mit einem eingebauten Switch ist ein VLAN erst dann aktiv, wenn ein Gerät an dem zugehörigen Switchport angeschlossen ist.
In Umgebungen, in denen nachts alle Geräte ausgeschaltet werden (und die den Link nicht aktiv halten), geht das VLAN-Interface in den Down-State und das zugehörige Netz wird per Routing-Protokoll nicht mehr angekündigt.
Das hat natürlich alles seinen Grund. Man möchte beispielsweise keinen Traffic für ein Netz “anziehen”, das aktuell nicht vorhanden ist. In manchen Umgebungen macht das aber Probleme. Unter anderem, wenn man für das ISDN-Backup mit einer einfachen “Floating-Static-Route”-Konfiguration arbeitet. Oder man möchte das LAN-Interface administrativ nutzen; natürlich wäre dafür ein Loopback-Interface viel besser geeignet.
Eine Möglichkeit, dieses Problem zu umgehen, ist das Ausschalten des “autostate”:
int Vlan 1
no autostate
Hiermit bleibt das VLAN-Interface immer “Up”, das Netz im Routing und die VLAN-IP-Adresse erreichbar.
Cisco Access-Control-Listen
Immer wieder stelle ich fest, dass manche Admins eine der wichtigsten Erweiterungen der Cisco Access-Listen verpasst haben:
Access-Listen lassen sich komfortabel editieren
Seit einiger Zeit (nein, an das genaue Release erinnere ich mich nicht mehr) haben die ACEs (Access-List-Entries) Sequenznummern, die man beim show access-lists sehen kann:
c1841#sh access-lists
Extended IP access list 100
10 permit icmp any any (5 matches)
Extended IP access list TEST
10 permit icmp any any (5 matches)
20 permit udp any any
30 permit esp any any
Diese Sequenznummern können verwendet werden, um neue ACEs einzufügen. Dazu muss eine bisher nicht verwendete Nummer genommen werden:
c1841(config)#ip access-list ext TEST
c1841(config-ext-nacl)#15 permit tcp any any
c1841(config-ext-nacl)#
c1841(config-ext-nacl)#do sh ip access-list TEST
Extended IP access list TEST
10 permit icmp any any (5 matches)
15 permit tcp any any
20 permit udp any any
30 permit esp any any
c1841(config-ext-nacl)#
ACEs können natürlich auch gelöscht werden:
c1841(config-ext-nacl)#no 10
c1841(config-ext-nacl)#do sh ip access-list TEST
Extended IP access list TEST
15 permit tcp any any
20 permit udp any any
30 permit esp any any
c1841(config-ext-nacl)#
Wenn in einer ACL keine freien Sequenznummern mehr zur Verfügung stehen, können diese neu gebildet werden. Bei einem Reload werden diese mit einem Startwert von 10 und einer Schrittweite von 10 gebildet.
c1841(config)#ip access-list resequence TEST 50 20
c1841(config)#
c1841(config)#do sh ip access-list TEST
Extended IP access list TEST
50 permit tcp any any
70 permit udp any any
90 permit esp any any
c1841(config)#
Wer noch an seinen nummerierten ACLs hängt, kann die Editier-Funktionen natürlich auch benutzen. Dafür muss die Nummer einfach wie ein Name in den named ACLs verwendet werden:
c1841(config)#ip access-list extended 100
c1841(config-ext-nacl)#20 deny ip any any log
c1841(config-ext-nacl)#
c1841(config-ext-nacl)#do sh ip access-list 100
Extended IP access list 100
10 permit icmp any any (5 matches)
20 deny ip any any log
c1841(config-ext-nacl)#
Weitere Funktionen, die bei den ACLs in der Vergangenheit hinzugekommen sind:
Direktes Anzeigen der ACL zu einem Interface
c1841#sh ip access-list interface loo11
Extended IP access list TEST in
10 permit icmp any any (5 matches)
c1841#
c1841#sh ip access-list interface loo12
Extended IP access list TEST in
10 permit icmp any any (10 matches)
c1841#
c1841#sh ip access-list interface loo13
Extended IP access list TEST in
10 permit icmp any any (15 matches)
Extended IP access list TEST2 out
10 permit tcp any any
Obwohl dieselbe ACL auf drei verschiedenen Interfaces gebunden wurde, werden getrennte Statistiken geführt.
Mehrere Ports pro ACE
c1841(config)#ip access-list ext IPSEC
c1841(config-ext-nacl)#permit esp any any
c1841(config-ext-nacl)#permit udp any any eq isakmp non500-isakmp
c1841(config-ext-nacl)#
c1841(config-ext-nacl)#do sh access-list IPSEC
Extended IP access list IPSEC
10 permit esp any any
20 permit udp any any eq isakmp non500-isakmp
c1841(config-ext-nacl)#
Natürlich verliert man bei dieser Konfiguration die getrennten Counter für die unterschiedlichen Ports (hier 500 und 4500).
ACLs können auf weitere Felder wie z.B. den TTL-, den DSCP-Wert oder TCP-Flags filtern
c1841(config)#ip access-list extended TEST3
c1841(config-ext-nacl)#permit icmp any any ttl gt 128
c1841(config-ext-nacl)#permit udp any any dscp ef
c1841(config)#ip access-list extended TEST4
c1841(config-ext-nacl)#permit tcp any any match-all +syn +ack +fin -urg
Im zweiten Beispiel wird TCP-Traffic erlaubt, der sowohl das SYN, ACK und FIN-Bit trägt, aber nicht das URG-Bit.
Gruppieren von Network- oder Service-Objekten
Wer sich traut, das IOS 12.4(20)T einzusetzen, hat sogar die Möglichkeit, Object-Groups zu verwenden, wie es die PIX bzw. ASA schon lange vorgemacht hat:
c1841(config)#object-group network RFC1918
c1841(config-network-group)#10.0.0.0 0.255.255.255
c1841(config-network-group)#172.16.0.0 0.15.255.255
c1841(config-network-group)#range 192.168.0.0 192.168.255.255
c1841(config-network-group)#exit
c1841(config)#
c1841(config)#ip access-list extended TEST5
c1841(config-ext-nacl)#permit icmp any object-group RFC1918
Setzen von Cookies für das Logging
Ab 12.4(22)T kann an das Keyword log oder log-input ein “Cookie” angehängt werden, das als Tag zum Syslog-Server mitgesendet wird:
c1841(config)#ip access-list ext TEST6
c1841(config-ext-nacl)#deny icmp host 10.1.1.1 host 10.2.2.2 log BewareOfTheseHosts
c1841(config-ext-nacl)#
c1841(config-ext-nacl)#do sh ip access-lists TEST6
Extended IP access list TEST6
10 deny icmp host 10.1.1.1 host 10.2.2.2 log (10 matches) (tag = BewareOfTheseHosts)
c1841(config-ext-nacl)#
Auf dem Syslog-Server kommt dieses Tag mit der Log-Meldung an und kann z.B. gefiltert werden:
%SEC-6-IPACCESSLOGDP: list TEST6 denied icmp 10.1.1.1 -> 10.2.2.2 (0/0), 10 packets [BewareOfTheseHosts]
Die OSPF Prozess ID beim PE-CE-Routing
![]()
Wenn OSPF als IGP in einem Netz konfiguriert wird, ist die Prozess-ID nur lokal signifikant. Es ist keine AS-Nummer wie bei EIGRP, und daher funktioniert folgende Konfiguration ohne Probleme:
hostname R1
router ospf 10
network 10.10.10.1 0.0.0.0 area 0
hostname R2
router ospf 20
network 10.10.10.2 0.0.0.0 area 0
Etwas anders verhält sich die Sache aber, wenn man OSPF als PE-CE-Routing-Protokoll einsetzt. In den original Kursunterlagen zum Kurs “Implementing Cisco MPLS” kann man folgendes zum Thema nachlesen:
process-id: Internally used identification parameter for an OSPF routing process.
This parameter is locally assigned and can be any positive integer. A unique value is assigned for each OSPF routing process.
Wenn man seine PE-Router aber so konfiguriert, bekommt man nicht das erwartete Ergebnis.
Um das zu verdeutlichen, habe ich die Konfiguration des MPLS-Kurses verwendet:

Die (relevante) Konfiguration des CE11A:
router ospf 5
network 10.1.11.17 0.0.0.0 area 0
network 150.1.11.17 0.0.0.0 area 0
Die (relevante) Konfiguration des CE12A:
router ospf 6
network 10.1.12.17 0.0.0.0 area 0
network 150.1.12.17 0.0.0.0 area 0
Die (relevante) Konfiguration des PE11:
router ospf 10 vrf CUST-A
redistribute bgp 65001 subnets
network 150.1.11.18 0.0.0.0 area 0
Die (relevante) Konfiguration des PE12:
router ospf 20 vrf CUST-A
redistribute bgp 65001 subnets
network 150.1.12.18 0.0.0.0 area 0
Wie man sieht, sind alle Prozess-IDs unterschiedlich, was innerhalb eines AS kein Problem darstellen würde.
Wenn man sich die Routing-Tabelle der CE-Router anschaut, zeigt sich aber folgendes Problem:
CE11A#sh ip route ospf
10.0.0.0/8 is variably subnetted, 5 subnets, 3 masks
O E2 10.1.12.16/28 [110/65] via 150.1.11.18, 00:26:01, Serial1/0.101
150.1.0.0/28 is subnetted, 2 subnets
O E2 150.1.12.16 [110/1] via 150.1.11.18, 00:26:01, Serial1/0.101
Die Routen werden als External gelernt, anstelle als Intra-Area-Routen, wie es sein sollte.
Eine Möglichkeit, das Problem zu lösen, ist, für jeden Kunden dieselbe Prozess-ID zu benutzen.
Es geht aber auch anders. Innerhalb des PE-OSPF-Prozesses kann die domain-id spezifiziert werden. Wenn diese auf den PE-Routern für jeden Kunden identisch ist, werden die Routen wie gewünscht als IA gelernt.
Die PE12-Konfig wird folgendermaßen angepaßt:
router ospf 20 vrf CUST-A
domain-id 0.0.0.10
redistribute bgp 65001 subnets
network 150.1.12.18 0.0.0.0 area 0
Jetzt passt die Routing-Tabelle auf CE11A:
CE11A#sh ip route ospf
10.0.0.0/8 is variably subnetted, 5 subnets, 3 masks
O IA 10.1.12.16/28 [110/129] via 150.1.11.18, 00:00:35, Serial1/0.101
150.1.0.0/28 is subnetted, 2 subnets
O IA 150.1.12.16 [110/65] via 150.1.11.18, 00:00:35, Serial1/0.101
Warum das Ganze? Aus der Prozess-ID wird der Domain-Identifier abgeleitet und standardmäßig als extended Community Wert 0005 übertragen (beschrieben im RFC 4577).
Die Domain ID des PE11 kommt also bei PE12 an (ich habe “Extended Community” gegen “ExtCom” abgekürzt, damit es lesbar bleibt):
PE12#sh ip bgp vpnv4 all 10.1.11.16
BGP routing table entry for 65001:10:10.1.11.16/28, version 44
Paths: (1 available, best #1, table CUST-A)
Not advertised to any peer
Local
192.168.1.17 (metric 193) from 192.168.1.17 (192.168.1.17)
Origin incomplete, metric 65, localpref 100, valid, internal, best
ExtCom: RT:65001:10 OSPF DOMAIN ID:0x0005:0x0000000A0200
OSPF RT:0.0.0.0:2:0 OSPF ROUTER ID:150.1.11.18:0
mpls labels in/out nolabel/11107
Die “0A” ist in diesem Fall die hexadezimale Form der “10″, die auf PE11 konfiguriert ist. Wenn auf PE11 domain-id 11.12.13.14 konfiguriert wäre, käme bei PE12 folgendes an: OSPF DOMAIN ID:0x0005:0x0B0C0D0E0200
Der Standard sieht jetzt vor, daß eine Route mit abweichender Domain-ID als External importiert wird. Ist die Domain-ID hingegen identisch, wird sie als Intra-Area-Route importiert. Die ganze Sache kann aber noch dadurch erweitert werden, daß es mehr als eine Domain-ID geben kann.
Remote RIP-Routing
IGPs werden normalerweise dazu verwendet, um direkt angeschlossenen Nachbarn Routing-Informationen zu senden. Aber was ist, wenn man einem entfernten Router ein Update senden möchte:
![]() |
Kann R3 ein RIP-Update an R1 senden wenn R2 kein RIP spricht? Tunnel etc. sind natürlich nicht erlaubt. Ja, es geht. Z.B., indem R3 diesen Traffic direkt per Unicast versendet.
Die Konfiguration von R1 startet mit einer IP auf dem Interface und dem Aktivieren von RIP:
interface FastEthernet0/0
ip address 10.10.1.1 255.255.255.0
!
router rip
version 2
passive-interface default
network 10.0.0.0
no auto-summary
Auf R2 werden nur die Interfaces konfiguriert, kein RIP:
interface FastEthernet0/0
ip address 10.10.1.2 255.255.255.0
!
interface FastEthernet0/1
ip address 10.10.2.2 255.255.255.0
Router R3 spricht RIP, benutzt R1 als Neighbor und sendet daher diesem seine Updates als Unicast. Alle Interfaces werden passiv gesetzt (auch auf R1), per Multicast sollen keine Nachbarn mehr erreicht werden. Weiterhin benötigt R3 eine Route, um R1 zu erreichen:
interface Loopback0
ip address 1.1.1.1 255.255.255.255
!
interface FastEthernet0/1
ip address 10.10.2.3 255.255.255.0
!
router rip
version 2
passive-interface default
network 1.0.0.0
network 10.0.0.0
neighbor 10.10.1.1
no auto-summary
!
ip route 0.0.0.0 0.0.0.0 10.10.2.2
Mit dieser Konfig fängt R3 an, seine Updates zu senden:
*Mar 1 00:12:26.291: RIP: sending v2 update to 10.10.1.1 via FastEthernet0/1 (10.10.2.3)
*Mar 1 00:12:26.291: RIP: build update entries
*Mar 1 00:12:26.291: 1.1.1.1/32 via 0.0.0.0, metric 1, tag 0
Diese Updates kommen auch bei R1 an, werden dort aber aufgrund der ungültigen Source-Adresse verworfen:
*Mar 1 00:44:50.767: RIP: ignored v2 update from bad source 10.10.2.3 on FastEthernet0/0
Wenn in der RIP-Konfiguration die Validierung der Source-Adresse abgeschaltet wird, kann die Route von R3 problemlos gelernt werden:
router rip
version 2
passive-interface default
no validate-update-source
network 10.0.0.0
no auto-summary
Router#sh ip route rip
1.0.0.0/32 is subnetted, 1 subnets
R 1.1.1.1 [120/1] via 10.10.2.3, 00:00:21
Wird das für irgendetwas benötigt? Vermutlich nicht, aber interessant ist dieses Verhalten trotzdem …
Generieren von Crypto-Keys
Ein Artikel in Cisco IOS Hints and Tricks beschreibt einen Fehler, den vermutlich viele Leute schon begangen haben (ja, ich natürlich auch): Bei Problemen mit der SSH-Verbindung wurde zu schnell ein “crypto key generate rsa” eingegeben, um neue RSA-Keys zu erzeugen. Leider hat man vergessen, daran zu denken, daß die zertifikatbasierten VPNs von den Schlüsseln abhängen.
Glücklicherweise kennt das IOS seit Version 12.2(8)T die Möglichkeit, jedem Key-Paar ein Label mitzugeben und diese damit für verschiedene Einsatzzwecke zu unterscheiden.
Dabei wird der Befehl crypto key generate rsa mit dem Parameter label versehen:
crypto key generate rsa modulus 2048 label MYLABEL
Dieses Key-Paar kann dann in einem PKI-Trustpoint benutzt werden:
crypto pki trustpoint MYCA
enrollment ...
rsakeypair MYLABEL
Wenn später ein unvorsichtiges “crypto key generate” eingegeben wird, kann das den für die VPN-Zertifikate verwendeten Keys nichts anhaben.
Ein weiterer Vorteil ist, daß beim nächsten Wechsel der Zertifikate auch die Keys neu generiert werden können, ohne daß sich der SSH-Fingerprint ändert.
Update: Mit ISRs hat das bisher immer gut funktioniert. Heute ging die Methode mit 1700er Routern und einem 12.4(15)T8 allerdings schief. Also aufpassen!
Small-Site Multihoming
Ivan Pepelnjak hat in seinen sehr lesenswerten Artikeln Small Site Multi-homing, Redundant Small Site Multi-homing und Servers in Small Site Multi-homing sehr schön beschrieben, wie man sich als kleiner Kunde mit mehreren Providern verbinden kann. Eine sehr wichtige Topologie fehlt allerdings: Wie implementiert man Server, wenn man mit zwei Routern an unterschiedlichen ISPs angeschlossen ist:
![]() |
Dort ist das Problem des asymmetrischen Traffics etwas aufwendiger zu lösen.
Wie in dem Dokument Servers in Small Site Multi-homing beschrieben, hat der Server zwei zusätzliche IP-Adressen, für die auf den zwei Routern jeweils ein statischer NAT-Eintrag vorhanden ist.
Wenn man für den Server annimmt, daß dieser für das Mail-Handling zuständig ist, dann muss man annehmen, daß über beide ISPs Mails eingeliefert werden, egal ob der MX mit der höheren Priorität erreichbar ist oder nicht.
Die Grundkonfig der Router könnte folgendermaßen aussehen (anstelle des Intrerface-Trakings könnte man besser auch “ip sla” verwenden):
hostname R1
!
interface FastEthernet0/0
ip address 10.10.10.1 255.255.255.0
ip nat inside
standby 0 ip 10.10.10.3
standby 0 priority 105
standby 0 preempt
standby 0 track FastEthernet0/1
!
interface FastEthernet0/1
ip address 192.168.1.1 255.255.255.0
ip nat outside
!
ip nat pool ISP-A-POOL 192.168.1.11 192.168.1.11 prefix-length 24
ip nat inside source list INSIDE-HOSTS pool ISP-A-POOL overload
ip nat inside source static 10.10.10.101 192.168.1.101 extendable
!
ip access-list standard INSIDE-HOSTS
permit 10.10.10.0 0.0.0.255
hostname R2
!
interface FastEthernet0/0
ip address 10.10.10.2 255.255.255.0
ip nat inside
standby 0 ip 10.10.10.3
standby 0 preempt
!
interface FastEthernet0/1
ip address 192.168.2.1 255.255.255.0
ip nat outside
!
ip nat pool ISP-B-POOL 192.168.2.12 192.168.2.12 prefix-length 24
ip nat inside source list INSIDE-HOSTS pool ISP-B-POOL overload
ip nat inside source static 10.10.10.102 192.168.2.102 extendable
!
ip access-list standard INSIDE-HOSTS
permit 10.10.10.0 0.0.0.255
Der Traffic fließt hier folgendermaßen:
![]() |
- Vom Server ausgehender Traffic (schwarz) fließt zum aktiven HSRP-Router und bekommt eine Adresse aus dem ISP-A-POOL.
- Von außen initiierter Traffic auf die 192.168.1.101 (grün) fließt über den aktiven Router zurück und NAT läuft wie erwartet.
- Von aussen initiierter Traffic auf die 192.168.2.102 (rot) fließt ebenfalls über den aktiven Router zurück. NAT behandelt diesen Traffic wie vom Server ausgehenden Traffic und das Antwort-Paket bekommt ebenfalls eine Absender-Adresse aus dem ISP-A-POOL, mit der der Client nichts anfangen kann.
Auf dem Switch PBR zu konfigurieren ist aufgrund der PBR-Implementierung vermutlich keine Option (3750: nur auf routed Interface oder SVI, IP Services Image, kein PBR bei gemeinsamen IPv4 und IPv6).
Auf dem Server die Konfiguration vorzunehmen ist evtl. auch nicht möglich oder gewollt.
Auf dem Router R1 ist es allerdings relativ einfach umzusetzen:
ip access-list extended TRAFFIC-FROM-102
permit ip host 10.10.10.102 any
!
route-map POLICY-INSIDE-IN permit 10
match ip address TRAFFIC-FROM-102
set ip next-hop 10.10.10.2
!
interface FastEthernet0/0
ip policy route-map POLICY-INSIDE-IN
Jetzt ergibt sich der Traffic-Fluß wie es gewünscht ist:
![]() |
Jetzt kommt natürlich noch die IOS-Firewall und eingehende ACLs auf beiden Interfaces hinzu.
Dafür muss die Konfiguration noch etwas erweitert werden. Zum einen müssen sowohl eingehende, als auch ausgehende Antwortpakete per Inspection erlaubt werden, da die ACLs ein abschließendes deny any haben sollten. Zum anderen muss der Traffic, der per PBR umgeroutet wird, auch in der ACL erlaubt werden, da die ACL vor dem Policy-Based Routing abgearbeitet wird (hier könnte man natürlich zwischen einer aus- und eingehenden FW-Policy unterscheiden):
ip inspect name FW tcp router-traffic
ip inspect name FW udp router-traffic
ip inspect name FW icmp router-traffic
!
interface FastEthernet0/0
ip access-group INSIDE-IN in
ip inspect FW out
!
interface FastEthernet0/1
ip access-group OUTSIDE-IN in
ip inspect FW out
!
ip access-list extended INSIDE-IN
permit ip host 10.10.10.102 any
!permit whatever you want
ip access-list extended OUTSIDE-IN
permit tcp any host 192.168.1.101 eq smtp
Abschließend natürlich noch der Hinweis, daß dieser Server sinnvollerweise als Mail-Relay in der DMZ implementiert sein sollte. Der “richtige” Mail-Server steht dann intern und bekommt seine Mails von dem Relay.






