# 網路模擬-Reflector ###### tags: `P4`、`Mininet`、`scapy` ------- Question === - In this environment, we need to prepare a host and switch, you can check [nsg-ethz](https://github.com/nsg-ethz/p4-learning/tree/master/examples/reflector) to build this environment. Environment === ![](https://i.imgur.com/peYwF48.png) Codes === > p4app.json ↓ ``` { "program": "reflector.p4", "switch": "simple_switch", "compiler": "p4c", "options": "--target bmv2 --arch v1model --std p4-16", "switch_cli": "simple_switch_CLI", "cli": true, "pcap_dump": true, "enable_log": true, "topo_module": { "file_path": "", "module_name": "p4utils.mininetlib.apptopo", "object_name": "AppTopo" }, "controller_module": null, "topodb_module": { "file_path": "", "module_name": "p4utils.utils.topology", "object_name": "Topology" }, "mininet_module": { "file_path": "", "module_name": "p4utils.mininetlib.p4net", "object_name": "P4Mininet" }, "topology": { "links": [["h1", "s1"]], "hosts": { "h1": { } }, "switches": { "s1": { "program": "reflector.p4" } } } } ``` > reflector.p4 ↓ ``` /* -*- P4_16 -*- */ #include <core.p4> #include <v1model.p4> /************************************************************************* *********************** H E A D E R S *********************************** *************************************************************************/ typedef bit<48> macAddr_t; header ethernet_t { macAddr_t dstAddr; macAddr_t srcAddr; bit<16> etherType; } struct metadata { /* empty */ } struct headers { ethernet_t ethernet; } /************************************************************************* *********************** P A R S E R *********************************** *************************************************************************/ parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { state start{ packet.extract(hdr.ethernet); transition accept; } } /************************************************************************* ************ C H E C K S U M V E R I F I C A T I O N ************* *************************************************************************/ control MyVerifyChecksum(inout headers hdr, inout metadata meta) { apply { } } /************************************************************************* ************** I N G R E S S P R O C E S S I N G ******************* *************************************************************************/ control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { action swap_mac(){ macAddr_t tmp; tmp = hdr.ethernet.srcAddr; hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; hdr.ethernet.dstAddr = tmp; } apply { // Swap MAC addresses. swap_mac(); //Set Output port == Input port standard_metadata.egress_spec = standard_metadata.ingress_port; } } /************************************************************************* **************** E G R E S S P R O C E S S I N G ******************* *************************************************************************/ control MyEgress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { apply { } } /************************************************************************* ************* C H E C K S U M C O M P U T A T I O N ************** *************************************************************************/ control MyComputeChecksum(inout headers hdr, inout metadata meta) { apply { } } /************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/ control MyDeparser(packet_out packet, in headers hdr) { apply { // parsed headers have to be added again into the packet packet.emit(hdr.ethernet); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; ``` > send_receive.py ↓ ``` #!/usr/bin/env python import sys import socket import random import time from threading import Thread, Event from scapy.all import * class Sniffer(Thread): def __init__(self, interface="eth0"): super(Sniffer, self).__init__() self.interface = interface self.my_mac = get_if_hwaddr(interface) self.daemon = True self.socket = None self.stop_sniffer = Event() def isNotOutgoing(self, pkt): return pkt[Ether].src != self.my_mac def run(self): self.socket = conf.L2listen( type=ETH_P_ALL, iface=self.interface, filter="ip" ) sniff(opened_socket=self.socket, prn=self.print_packet, lfilter=self.isNotOutgoing, stop_filter=self.should_stop_sniffer) def join(self, timeout=None): self.stop_sniffer.set() super(Sniffer, self).join(timeout) def should_stop_sniffer(self, packet): return self.stop_sniffer.isSet() def print_packet(self, packet): print "[!] A packet was reflected from the switch: " # packet.show() ether_layer = packet.getlayer(Ether) print("[!] Info: {src} -> {dst}\n".format(src=ether_layer.src, dst=ether_layer.dst)) def get_if(): ifs = get_if_list() iface = None # "h1-eth0" for i in get_if_list(): if "eth0" in i: iface = i break; if not iface: print "Cannot find eth0 interface" exit(1) return iface def send_packet(iface, addr): raw_input("Press the return key to send a packet:") print "Sending on interface %s to %s\n" % (iface, str(addr)) pkt = Ether(src=get_if_hwaddr(iface), dst='00:01:02:03:04:05') pkt = pkt / IP(dst=addr) sendp(pkt, iface=iface, verbose=False) def main(): addr = "10.0.0.2" addr = socket.gethostbyname(addr) iface = get_if() listener = Sniffer(iface) listener.start() time.sleep(0.1) try: while True: send_packet(iface, addr) time.sleep(0.5) except KeyboardInterrupt: print("[*] Stop sniffing") listener.join(2.0) if listener.isAlive(): listener.socket.close() if __name__ == '__main__': main() ``` Test === > use "p4run" to connect the p4 environment. > using "xterm h1" to open terminal for h1, we need to type twice. one type "wireshark" to check the packet, another type "scapy". > if you type "scapy" and something error, it might be not install, just using "pip install scapy" to fix error. ![](https://i.imgur.com/tH6wHVR.jpg) For scapy, we can follow [Sending & recieving packets](https://0xbharath.github.io/art-of-packet-crafting-with-scapy/scapy/sending_recieving/index.html) this website to know more scapy's command and detail. > follow in this web, we can type "pkt=Ether()/IP()/UDP()" to build the packet model. > > "pkt.show()" can show packet information. ![](https://i.imgur.com/OaJc0js.jpg) > "pkt=Ether(dst="MAC address")/IP(dst="ip address")/UDP(dport=,sport=)", the packet dst you can put what you want, e.g. "pkt=Ether(dst="01:02:03:04:05:06")/IP(dst="10.0.0.1")/UDP(dport=1,sport=1)". > > don't forget to using "pkt.show()" to check packet info. ![](https://i.imgur.com/LGcNfqA.jpg) ![](https://i.imgur.com/xdMblSh.jpg) send packet command you can use "sendp(pkt,iface="h1-eth0")" and check wireshark. ![](https://i.imgur.com/0t4TNrV.jpg) done. Reference === 1.pkt_reflector,source:https://github.com/nsg-ethz/p4-learning/tree/master/examples/reflector 2.sending and receive,source:https://0xbharath.github.io/art-of-packet-crafting-with-scapy/scapy/sending_recieving/index.html --- ###### 2020-05-25 ###### written by **yi-hao tu**