
Un renifleur OpenFlow pour aider au dépannage réseau dans les réseaux de production.
OFP_Sniffer est un renifleur OpenFlow destiné au dépannage et à l'apprentissage.
Actuellement en version 1.2, il analyse tous les messages OpenFlow 1.0, fonctionne avec InfluxDB, Grafana et Slack. OpenFlow 1.3 sera disponible dans OFP_Sniffer version 1.3 (à paraître prochainement).
Il fonctionne directement en ligne de commande Linux et analyse tous les messages OpenFlow sur le réseau ou à partir de fichiers libpcap. Avec OFP_Sniffer, vous pouvez facilement suivre les messages OpenFlow et les erreurs associées (le cas échéant) sans ouvrir X11 ou Wireshark. OFP_Sniffer a été écrit en Python 3.6 pour supporter le déploiement SDN AmLight (www.sdn.amlight.net). AmLight SDN utilise Internet2 FlowSpace Firewall, OESS et On.Lab ONOS, et ces applications ont été testées et sont entièrement prises en charge.
En tant qu'outil en ligne de commande, il a quelques paramètres d'entrée :
# ./ofp_sniffer.py -h
Usage:
./ofp_sniffer.py [-p min|full] [-f pcap_filter] [-F filter_file] [-i dev] [-r pcap_file]
-p : print all TCP/IP headers. Default: min
-f pcap_filter or --pcap-filter=pcap_filter: add a libpcap filter
-F filters_file.json or --filters-file=filters.json
-i interface or --interface=interface. Default: eth0
-r captured.pcap or --src-file=captured.pcap
-T topology.json or --topology-file=topology.json
-w file or --save-to-file=file: save output to file provided
-o or --print-ovs : print using ovs-ofctl format
-h or --help : prints this help
-c or --no-colors: removes colors
-v or --version : prints version
-O WARN:CRIT or --oess-fvd=WARN:CRIT: monitor OESS FVD status
-N or --notify-via-slack: send notifications via Slack. Param is the Slack channel
-S or --enable-statistics: creates statistics
À partir de la version 1.0, des applications sont prises en charge pour répondre à des besoins spécifiques, comme le suivi des messages OESS FVD ou la création de statistiques via REST et leur intégration aux NMS (par exemple, Zabbix).
Plus d'informations : https://amlight.net/wp-content/uploads/2015/03/wpeif-2016-ofpsniffer.pdf
##################### Installation ######################
Requires Python 3.6
git clone https://github.com/amlight/ofp_sniffer.git
cd ofp_sniffer
pip3.6 install -r docs/requirements.txt
sudo ./ofp_sniffer.py
##################### Exemples #########################
Des exemples sont fournis ci-dessous :
---------------------- -------------------------
| Mininet | | OVS-OFCTL 2.3.0 |
| 192.168.56.101:6634| <-------> | eth1 - 192.168.56.102 |
---------------------- -------------------------
# ovs-ofctl dump-flows tcp:192.168.56.101:6634
cookie=0x0, duration=2183.377s, table=0, n_packets=0, n_bytes=0, idle_age=2183, in_port=1,dl_vlan=2 actions=output:2
# ./ofp_sniffer.py -i eth1 -f " or port 6634"
Sniffing device eth1
2015-09-13 11:47:38.655503 192.168.56.102:37450 -> 192.168.56.101:6634 Size: 74
OpenFlow Version: 1.0(1) Type: Hello(0) Length: 8 XID: 1
1 OpenFlow Hello
2015-09-13 11:47:38.656964 192.168.56.101:6634 -> 192.168.56.102:37450 Size: 74
OpenFlow Version: 1.0(1) Type: Hello(0) Length: 8 XID: 174
174 OpenFlow Hello
2015-09-13 11:47:38.657638 192.168.56.102:37450 -> 192.168.56.101:6634 Size: 86
OpenFlow Version: 1.0(1) Type: Vendor(4) Length: 20 XID: 2
2 OpenFlow Vendor : NICIRA(0x2320)
2 OpenFlow Vendor Data: 12 2
2015-09-13 11:47:38.657870 192.168.56.102:37450 -> 192.168.56.101:6634 Size: 74
OpenFlow Version: 1.0(1) Type: BarrierReq(18) Length: 8 XID: 3
3 OpenFlow Barrier Request
2015-09-13 11:47:38.659270 192.168.56.101:6634 -> 192.168.56.102:37450 Size: 74
OpenFlow Version: 1.0(1) Type: BarrierRes(19) Length: 8 XID: 3
3 OpenFlow Barrier Reply
# ovs-ofctl add-flow tcp:192.168.56.101:6634 "dl_dst=10:00:00:01:20:00,dl_type=0x88bc actions=mod_vlan_vid:14,output:2"
# ./ofp_sniffer.py -i eth1 -f " or port 6634"
2015-09-13 11:49:08.171463 192.168.56.102:37451 -> 192.168.56.101:6634 Size: 154
OpenFlow Version: 1.0(1) Type: FlowMod(14) Length: 88 XID: 2
2 OpenFlow Match - wildcards: 3678439 dl_type: 0x88bc dl_dst: 10:00:00:01:20:00
2 OpenFlow Body - Cookie: 0x00 Command: Add(0) Idle/Hard Timeouts: 0/0 Priority: 32768 Buffer ID: 0xffffffff Out Port: 65535 Flags: Unknown Flag(0)
2 OpenFlow Action - Type: SetVLANID Length: 8 VLAN ID: 14 Pad: 0
2 OpenFlow Action - Type: OUTPUT Length: 8 Port: 2 Max Length: 0
# ovs-ofctl del-flows tcp:192.168.56.101:6634 "dl_type=0x88bc,dl_dst=10:00:00:01:20:00, "
2015-09-13 11:50:43.636925 192.168.56.102:37454 -> 192.168.56.101:6634 Size: 138
OpenFlow Version: 1.0(1) Type: FlowMod(14) Length: 72 XID: 2
2 OpenFlow Match - wildcards: 3678439 dl_type: 0x88bc dl_dst: 10:00:00:01:20:00
2 OpenFlow Body - Cookie: 0x00 Command: Delete(3) Idle/Hard Timeouts: 0/0 Priority: 32768 Buffer ID: 0xffffffff Out Port: 65535 Flags: Unknown Flag(0)
# ovs-ofctl add-flow tcp:192.168.56.101:6634 "dl_dst=10:00:00:01:20:00,dl_type=0x88bc actions=mod_vlan_vid:14,output:2"
2015-09-13 11:52:58.563737 192.168.56.102:37455 -> 192.168.56.101:6634 Size: 154
OpenFlow Version: 1.0(1) Type: FlowMod(14) Length: 88 XID: 2
2 OpenFlow Match - wildcards: 3678439 dl_type: 0x88bc dl_dst: 10:00:00:01:20:00
2 OpenFlow Body - Cookie: 0x00 Command: Add(0) Idle/Hard Timeouts: 0/0 Priority: 32768 Buffer ID: 0xffffffff Out Port: 65535 Flags: Unknown Flag(0)
2 OpenFlow Action - Type: SetVLANID Length: 8 VLAN ID: 14 Pad: 0
2 OpenFlow Action - Type: OUTPUT Length: 8 Port: 2 Max Length: 0
Utilisation des filtres :
Lorsque vous utilisez l'option -F ./filters.json, vous avez plusieurs options :
"rejected_of_types" : utilisé pour sélectionner les types de messages OpenFlow que vous NE voulez PAS voir. Vous pouvez définir différents filtres selon la version d'OpenFlow.
Filtres par Ethertype :
Si vous recherchez un Ethertype spécifique transporté par les messages PacketOut ou PacketIn, vous pouvez rejeter tous les autres, ce qui facilite la visualisation.
Exemple :
"filters":{
"ethertypes": {
"lldp" : 0,
"fvd" : 0,
"arp" : 1,
"others": [ "88b5" ]
},
"packetIn_filter": {
"switch_dpid": "any",
"in_port": "any"
},
"packetOut_filter": {
"switch_dpid": "any",
"out_port": "any"
}
}
}
Dans la section ethertype, 1 signifie filtrer, 0 signifie afficher. Dans l'exemple fourni, les messages ARP ne seront pas visibles, tandis que OESS FVD et LLDP le seront. Vous pouvez ajouter le nombre hexadécimal de l'Ethertype (sans le 0x) dans la section "others", en ajoutant simplement des virgules (",").
"packetIn_filter" : utilisé pour définir quels messages PacketIn + LLDP vous souhaitez voir. Vous pouvez définir par commutateur et/ou par port. Pour le commutateur, vous devez utiliser le datapath_id tel que vu par l'application que vous utilisez. Par exemple, certaines applications remplissent le champ c_id avec of:dpid_id, d'autres avec dpid:dpid_id. Pour les ports, utilisez le port_id OpenFlow, pas le nom du port. Par exemple, sur Brocade, eth1/1 == 1. Utilisez donc 1 au lieu d'eth1/1.
"packetOut_filter" : utilisé pour définir quels messages PacketOut + LLDP vous souhaitez voir. Vous pouvez définir par commutateur et/ou par port. Pour le commutateur, vous devez utiliser le datapath_id tel que vu par l'application que vous utilisez. Par exemple, certaines applications remplissent le champ c_id avec of:dpid_id, d'autres avec dpid:dpid_id. Pour les ports, utilisez le port_id OpenFlow, pas le nom du port. Par exemple, sur Brocade, eth1/1 == 1. Utilisez donc 1 au lieu d'eth1/1.
Prise en charge des proxies OpenFlow :
Lorsque vous utilisez un proxy OpenFlow, selon l'interface que vous sélectionnez pour renifler, vous allez voir l'une des deux possibilités :
IP_Controller <-> IP_Proxy IP_Proxy <-> IP_Switch
Il est difficile d'associer quel contrôleur parle à quel commutateur. Pour faciliter ce dépannage, le renifleur OpenFlow surveille automatiquement tous les messages PacketOut + LLDP pour créer un dictionnaire de {(IP, port): name_switch}. Si c'est votre cas, modifiez le fichier docs/topology.json. La prochaine fois que vous exécuterez le renifleur, vous verrez l'IP et entre parenthèses le périphérique derrière le proxy. Exemple :
2015-12-16 15:37:41.563621 200.0.207.79(andes1):7801 -> 190.103.184.135:6633 Size: 157 Bytes
OpenFlow Version: 1.0(1) Type: PacketIn(10) Length: 103 XID: 0
0 PacketIn: buffer_id: 0xffffffff total_len: 85 in_port: 49 reason: OFPR_NO_MATCH(0) pad: 0
0 Ethernet: Destination MAC: ff:ff:ff:ff:ff:ff Source MAC: de:ad:be:ef:ba:11 Protocol: 0x8100
0 Ethernet: Prio: 0 CFI: 0 VID: 3720
0 LLDP: Chassis Type(1) Length: 7 SubType: 4 ID: of:cc4e249102000000
0 LLDP: Port Type(2) Length: 5 SubType: 2 ID: 2
0 LLDP: TTL(3) Length: 2 Seconds: 120
0 LLDP: END(0) Length: 0
2015-12-16 15:37:41.564414 190.103.184.133(andes1):56132 -> 190.103.187.72:6633 Size: 165 Bytes
OpenFlow Version: 1.0(1) Type: PacketIn(10) Length: 99 XID: 0
0 PacketIn: buffer_id: 0xffffffff total_len: 81 in_port: 49 reason: OFPR_NO_MATCH(0) pad: 0
0 Ethernet: Destination MAC: ff:ff:ff:ff:ff:ff Source MAC: de:ad:be:ef:ba:11 Protocol: 0x8942
0 LLDP: Chassis Type(1) Length: 7 SubType: 4 ID: of:cc4e249102000000
0 LLDP: Port Type(2) Length: 5 SubType: 2 ID: 2
0 LLDP: TTL(3) Length: 2 Seconds: 120
0 LLDP: END(0) Length: 0
Le nom (andes1) représente un commutateur appelé "andes1" avec le DPID cc4e249126000000. Notez que le DPID montré dans l'exemple n'est pas le même, car un message PacketIn est utilisé comme exemple. PacketIn montre le DPID des voisins de "andes1".
J'espère que ce code vous aidera.
Questions/Suggestions : AmLight Dev Team [email protected]