def decode(self, aBuffer): e = ImpactPacket.Ethernet(aBuffer) self.set_decoded_protocol(e) off = e.get_header_size() if e.get_ether_type() == ImpactPacket.IP.ethertype: self.ip_decoder = IPDecoder() packet = self.ip_decoder.decode(aBuffer[off:]) elif e.get_ether_type() == IP6.IP6.ethertype: self.ip6_decoder = IP6Decoder() packet = self.ip6_decoder.decode(aBuffer[off:]) elif e.get_ether_type() == ImpactPacket.ARP.ethertype: self.arp_decoder = ARPDecoder() packet = self.arp_decoder.decode(aBuffer[off:]) elif e.get_ether_type() == eap.DOT1X_AUTHENTICATION: self.eapol_decoder = EAPOLDecoder() packet = self.eapol_decoder.decode(aBuffer[off:]) # LLC ? elif e.get_ether_type() < 1500: self.llc_decoder = LLCDecoder() packet = self.llc_decoder.decode(aBuffer[off:]) else: self.data_decoder = DataDecoder() packet = self.data_decoder.decode(aBuffer[off:]) e.contains(packet) return e
def sendReply(nonce): #build ethernet frame eth = ImpactPacket.Ethernet() eth.set_ether_type(0x88b5) eth.set_ether_shost(ETH_MY_MAC) eth.set_ether_dhost(ETH_MY_MAC) #build ip packet ip = ImpactPacket.IP() ip.set_ip_v(4) ip.set_ip_len(32) ip.set_ip_src("127.0.0.1") ip.set_ip_dst("127.0.0.1") #build UDP packet udp = ImpactPacket.UDP() udp.set_uh_sport(62001) udp.set_uh_dport(62000) udp.set_uh_ulen(12) payload = nonce udp.contains(ImpactPacket.Data(payload)) ip.contains(udp) eth.contains(ip) device = findalldevs()[0] s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x88b5)) s.bind(('lo', 0)) s.send(eth.get_packet()) print "Sent: " + nonce signal.alarm(0) #disable the alarm
def icmp_reply(self, eth_src, eth_dst, ip_src, ip_dst, i_type, i_code, ip_pkt): # TODO: we have access to the personality here """Function creates and sends back an ICMP reply Args: eth_src : ethernet source address eth_dst : ethernet destination address ip_src : ip source address ip_dst : ip destination address i_type : type of the icmp reply i_code : code of the icmp reply """ # truncate inner packet l = ip_pkt.get_ip_len() hdr = None if l > 1472: # (MTU) 1500 - (IPv4) 20 - (ICMP) 8 = 1472 hdr = ip_pkt.get_packet()[:1472] else: hdr = ip_pkt.get_packet() # icmp packet reply_icmp = ImpactPacket.ICMP() reply_icmp.set_icmp_type(i_type) reply_icmp.set_icmp_code(i_code) reply_icmp.set_icmp_id(0) reply_icmp.set_icmp_seq(0) reply_icmp.set_icmp_void(0) reply_icmp.contains(ImpactPacket.Data(hdr)) reply_icmp.calculate_checksum() reply_icmp.auto_checksum = 1 # ip packet reply_ip = ImpactPacket.IP() reply_ip.set_ip_v(4) reply_ip.set_ip_p(1) reply_ip.set_ip_rf(False) reply_ip.set_ip_df(False) reply_ip.set_ip_mf(False) reply_ip.set_ip_src(ip_src) reply_ip.set_ip_dst(ip_dst) reply_ip.set_ip_id( random.randint(0, 50000) ) # TODO: provide IP IDs according to personality, altough tracepath does not care reply_ip.contains(reply_icmp) # ethernet frame reply_eth = ImpactPacket.Ethernet() reply_eth.set_ether_type(0x800) eth_src = [int(i, 16) for i in eth_src.split(':')] eth_dst = [int(i, 16) for i in eth_dst.split(':')] reply_eth.set_ether_shost(eth_src) reply_eth.set_ether_dhost(eth_dst) reply_eth.contains(reply_ip) logger.debug('Sending reply: %s', reply_eth) # send raw frame try: self.pcapy_object.sendpacket(reply_eth.get_packet()) except pcapy.PcapError as ex: logger.exception('Exception: Cannot send reply packet: %s', ex)
def send_ns_packet(self, source_link, send_frequency, target_address, vlan_id=0): ip = IP6.IP6() ip.set_source_address(self.get_source_address()) ip.set_destination_address(self.get_target_address()) ip.set_traffic_class(0) ip.set_flow_label(0) ip.set_hop_limit(255) s = socket(AF_PACKET, SOCK_RAW, IPPROTO_ICMPV6) s.bind((self.network_card, N)) payload = self.create_ns_message(source_link, target_address) print send_frequency for i in range(0, send_frequency): icmp = ICMP6.ICMP6() icmp.set_byte(0, 135) # Put Type? icmp.set_byte(1, 00) # Put Code? payloadObject = ImpactPacket.Data() payloadObject.set_data(payload) icmp.contains(payloadObject) ip.contains(icmp) ip.set_next_header(ip.child().get_ip_protocol_number()) ip.set_payload_length(ip.child().get_size()) eth = ImpactPacket.Ethernet( '\x33\x33\x00\x00\x00\x01\xff\xff\xff\xff\xff\xff\x81\x00') eth.pop_tag() if vlan_id != 0: vlan = ImpactPacket.EthernetTag() vlan.set_vid(vlan_id) eth.push_tag(vlan) icmp.calculate_checksum() eth.contains(ip) s.send(eth.get_packet())
def sendpacket(self, data): ipe = ImpactPacket.Ethernet() ipe.set_ether_dhost(self.MACADDRESS) ipd = ImpactPacket.Data(data) ipd.ethertype = 0x86dd # Ethertype for IPv6 ipe.contains(ipd) p = ipe.get_packet() self.s.send(p)
def buildAnswer(self, in_onion): eth = ImpactPacket.Ethernet() ip = ImpactPacket.IP() eth.contains(ip) eth.set_ether_shost(in_onion[O_ETH].get_ether_dhost()) eth.set_ether_dhost(in_onion[O_ETH].get_ether_shost()) ip.set_ip_src(in_onion[O_IP].get_ip_dst()) ip.set_ip_dst(in_onion[O_IP].get_ip_src()) ip.set_ip_id(self.machine.getIPID()) return [eth, ip]
def main(): signal.signal(signal.SIGALRM, lambda *args: handle_alarm()) #build ethernet frame eth = ImpactPacket.Ethernet() eth.set_ether_type(0x88b5) eth.set_ether_shost(ETH_MY_MAC) eth.set_ether_dhost(ETH_MY_MAC) #build ip packet ip = ImpactPacket.IP() ip.set_ip_v(4) ip.set_ip_len(32) ip.set_ip_src("127.0.0.1") ip.set_ip_dst("127.0.0.1") #build UDP packet udp = ImpactPacket.UDP() udp.set_uh_sport(62000) udp.set_uh_dport(62001) udp.set_uh_ulen(12) inp1 = '' print "Client.... Port: " + str(udp.get_uh_sport()) print "--------------------------------------------" while (len(inp1) != 4): inp1 = raw_input('Enter 4-bit ASCII nonce to send: ') if (len(inp1) != 4): print "Enter 4-bit ASCII" payload = inp1 udp.contains(ImpactPacket.Data(payload)) ip.contains(udp) eth.contains(ip) device = 'lo' s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x88b5)) s.bind((device, 0)) s.send(eth.get_packet()) print "Sent: " + inp1 receiveReply()
def get_arp(self, sha, spa, tha, tpa, arp_type): ethernet_layer = ImpactPacket.Ethernet() arp_layer = ImpactPacket.ARP() ethernet_layer.contains(arp_layer) arp_layer.set_ar_hrd(1) # Hardware type Ethernet arp_layer.set_ar_pro(0x800) # IP arp_layer.set_ar_op(arp_type) arp_layer.set_ar_hln(6) arp_layer.set_ar_pln(4) arp_layer.set_ar_sha( self.addresses_helper.get_mac_in_list_format2(sha)) arp_layer.set_ar_spa(self.addresses_helper.get_ip_in_list_format(spa)) arp_layer.set_ar_tha( self.addresses_helper.get_mac_in_list_format2(tha)) arp_layer.set_ar_tpa(self.addresses_helper.get_ip_in_list_format(tpa)) ethernet_layer.set_ether_shost(arp_layer.get_ar_sha()) ethernet_layer.set_ether_dhost(arp_layer.get_ar_tha()) return ethernet_layer
def buildAnswer(self, in_onion): eth = ImpactPacket.Ethernet() arp = ImpactPacket.ARP() eth.contains(arp) arp.set_ar_hrd(1) # Hardward type Ethernet arp.set_ar_pro(0x800) # IP arp.set_ar_op(2) # REPLY arp.set_ar_hln(6) arp.set_ar_pln(4) arp.set_ar_sha(string2tuple(self.machine.macAddress)) arp.set_ar_spa(string2tuple(self.machine.ipAddress)) arp.set_ar_tha(in_onion[O_ARP].get_ar_sha()) arp.set_ar_tpa(in_onion[O_ARP].get_ar_spa()) eth.set_ether_shost(arp.get_ar_sha()) eth.set_ether_dhost(arp.get_ar_tha()) return [eth, arp]
def arp_reply(self, arp_pkt): """Function creates and sends back an ARP reply Args: arp_pkt : received arp packet """ # arp packet reply_arp = ImpactPacket.ARP() reply_arp.set_ar_hln(6) # Ethernet size 6 reply_arp.set_ar_pln(4) # IPv4 size 4 reply_arp.set_ar_hrd( 1) # 1:'ARPHRD ETHER', 6:'ARPHRD IEEE802', 15:'ARPHRD FRELAY' reply_arp.set_ar_op( 2 ) # 1:'REQUEST', 2:'REPLY', 3:'REVREQUEST', 4:'REVREPLY', 8:'INVREQUEST', 9:'INVREPLY' reply_arp.set_ar_pro(0x800) # IPv4 0x800 mac = [int(i, 16) for i in self.mac.split(':')] target_ip = unicode('.'.join(map(str, arp_pkt.get_ar_tpa()))) for d in self.devices: if target_ip in d.bind_list: mac = [int(i, 16) for i in d.mac.split(':')] break reply_arp.set_ar_sha(mac) reply_arp.set_ar_tha(arp_pkt.get_ar_sha()) reply_arp.set_ar_spa(arp_pkt.get_ar_tpa()) reply_arp.set_ar_tpa(arp_pkt.get_ar_spa()) # ethernet frame reply_eth = ImpactPacket.Ethernet() reply_eth.set_ether_type(0x800) reply_eth.set_ether_shost(mac) reply_eth.set_ether_dhost(arp_pkt.get_ar_sha()) reply_eth.contains(reply_arp) logger.debug('Sending reply: %s', reply_eth) # send raw frame try: self.pcapy_object.sendpacket(reply_eth.get_packet()) except pcapy.PcapError as ex: logger.exception('Exception: Cannot send reply packet: %s', ex)
def packet(self, target, packet): """Function forging a packet for connection con. Only L1-3 get created. """ ethhead = ImpactPacket.Ethernet() iphead = ImpactPacket.IP() if target == Connection.HEAD: # Set MACs: ethhead.set_ether_shost(self.tail.mac) ethhead.set_ether_dhost(self.head.mac) # Set IPs iphead.set_ip_src(self.tail.ipaddr) iphead.set_ip_dst(self.head.ipaddr) # target == TCPConnection.TAIL else: # Set MACs: ethhead.set_ether_dhost(self.tail.mac) ethhead.set_ether_shost(self.head.mac) # Set IPs iphead.set_ip_dst(self.tail.ipaddr) iphead.set_ip_src(self.head.ipaddr) iphead.contains(packet) ethhead.contains(iphead) return ethhead
def build_ethernet_reply(eth, proto): reply = ImpactPacket.Ethernet() reply.set_ether_dhost(eth.get_ether_shost()) reply.set_ether_shost(OUR_MAC_ARRAY) reply.set_ether_type(proto) return reply
def __init__(self, max_rate=2500, num_flows=10000, pkt_size=100, flow_size_cdf={ 0.999: 10, 0.9999: 100, 0.99999: 1000, 1.0: 100000, }, num_src_machines=100, num_dst_machines=100, iface="eth0", batch_size=1, entity='e', workspace='w'): ''' Initialize a packet generator instance with the specified parameters: - max_rate: maximum bitrate to gen packets in kbps - num_flows: total num of active flows at any given time - pkt_size: packet size - dst_ports_pdf: a dict mapping cdf -> port num "random" can be used instead of port num. - flow_size_pdf: a dict mapping cdf -> flow sizes in packets - num_src/dst_machines: total number of machines this flow generator will simulate - src/dst_ip_prefix: subnet the machines will use as source and dst addresses format: "x.x.x.x/int" - src/dst_mac_prefix: specify the macs for the machines. format:"xx:xx:xx:xx:xx:xx/int" - src/dst_mac_list: If specified, this will override the prefix - iface: name of interface to send packets on ''' self.batch_size = batch_size self.max_flows = num_flows self.flow_size_cdf = flow_size_cdf self.pkt_size = pkt_size self.cdf_counter = 0 self.workspace = workspace self.entity = entity # Calculate the delay between packets to maintain bitrate self.delay = self.batch_size * pkt_size * 8.0 / max_rate / 1000 #print "Delay: %s ms" % (self.delay*1000) # maintains the active flow set self.flows = [] # what flow should a packet come from? self.next_flow = 0 # socket to use if AS_ROOT: e = dts.Entity(iface, entity, True) print 'Entity "{}" registered.'.format(e.title) w = dts.Workspace(iface, workspace) try: w.attach(e) print 'Attached to workspace "{}".'.format(w.title) except dts.DTSException: # Failed to attach, probably does not exists, # then try to create w.create_on_dts(e) print 'Created workspace "{}" and attached to it.'.format( w.title) super(FlowGenerator, self).__init__() self.total_sent = 0 # cache the creation of a packet self.eth = ImpactPacket.Ethernet() self.ip = ImpactPacket.IP() self.udp = ImpactPacket.UDP() data_len = (pkt_size - self.eth.get_header_size() - self.ip.get_header_size() - self.udp.get_header_size()) data = ImpactPacket.Data() data.set_bytes(array.array('B', [i % 0xff for i in range(data_len)])) self.udp.contains(data) self.ip.contains(self.udp) self.eth.contains(self.ip) self.calibrated = False
def randomMAC(): mac = (random.randint(0x00, 0xff), random.randint(0x00, 0xff), random.randint(0x00, 0xff), random.randint(0x00, 0xff), random.randint(0x00, 0xff), random.randint(0x00, 0xff)) return mac #Generate arp packets with randomly #s = socket(AF_INET, SOCK_RAW) s = socket(AF_PACKET, SOCK_RAW) s.bind(("h4-eth0", 0x0806)) pktid = 0 while (pktid <= 100000000): eth = ImpactPacket.Ethernet() forged_mac = randomMAC() eth.set_ether_shost(randomMAC()) eth.set_ether_dhost(randomMAC()) eth.set_ether_type(0x0806) print "send packet #", pktid, "with src_mac:", ':'.join( map(lambda x: "%02x" % x, forged_mac)) arp = ImpactPacket.ARP( ) # create the arp packet that will be inside of layer 1 arp.set_ar_hrd(0x0001) # set hardware type to ARPHRD ETHER (ethernet) arp.set_ar_op( 0x01 ) # Set tyoe to Arp Reply (0x02 = Reply, 0x04 = RevReply, 0x03 = RevRequest) arp.set_ar_pro(0x800) # 2048 (Set to standard IP protocol) arp.set_ar_hln(6) # Length should be 6 (octaves of mac address) arp.set_ar_pln(4) # should be 4 (octaves of i.p. address)
def main(): import sys DEFAULT_PROTOCOLS = ('tcp', ) sockets = [] print version.BANNER parser = argparse.ArgumentParser() parser.add_argument( "-i", metavar='FILE', help= 'pcap file to read packets. If not specified the program sniffes traffic (only as root)' ) parser.add_argument( "-o", metavar='FILE', help='pcap output file where the packets with errors will be written') options = parser.parse_args() outFile = options.o if options.i is None: sniffTraffic = True toListen = DEFAULT_PROTOCOLS else: sniffTraffic = False inFile = options.i packetNum = 0 if outFile: f_out = open(outFile, 'wb') f_out.write(str(pcapfile.PCapFileHeader())) if sniffTraffic is False: f_in = open(inFile, 'rb') hdr = pcapfile.PCapFileHeader() hdr.fromString(f_in.read(len(hdr))) decoder = ImpactDecoder.EthDecoder() else: for protocol in toListen: try: protocol_num = socket.getprotobyname(protocol) except socket.error: print "Ignoring unknown protocol:", protocol toListen.remove(protocol) continue s = socket.socket(socket.AF_INET, socket.SOCK_RAW, protocol_num) s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) sockets.append(s) print "Listening on protocols:", toListen decoder = ImpactDecoder.IPDecoder() while 1: if sniffTraffic is False: pkt = pcapfile.PCapFilePacket() try: pkt.fromString(f_in.read(len(pkt))) except: break pkt['data'] = f_in.read(pkt['savedLength']) p = pkt['data'] else: ready = select(sockets, [], [])[0] for s in ready: p = s.recvfrom(4096)[0] if 0 == len(p): # Socket remotely closed. Discard it. sockets.remove(s) s.close() packet = decoder.decode(p) packetNum += 1 if sniffTraffic is True: instance = packet.child() else: instance = packet.child().child() if isinstance(instance, ImpactPacket.TCP): tcppacket = instance if tcppacket.get_th_sport() == 445 or tcppacket.get_th_dport( ) == 445 or tcppacket.get_th_sport( ) == 139 or tcppacket.get_th_dport() == 139: data = tcppacket.child() if data.get_size() > 0: logPacket = process(data, packetNum) if logPacket is True: pkt_out = pcapfile.PCapFilePacket() if sniffTraffic is True: eth = ImpactPacket.Ethernet() eth.contains(packet) eth.set_ether_type(0x800) pkt_out['data'] = eth.get_packet() else: pkt_out['data'] = str(p) if outFile: f_out.write(str(pkt_out))
def handle_packet(self, ethernet_packet, path, event, tunnels, cb_tunnel=None): """Forwards packet to the appropriate protocol handler based on configuration Args: ethernet_packet : intercepted packet path : length of the patch in the virtual network event : extracted attack-related information tunnels : opened network tunnels cb_tunnel : callback function for data extraction Return: constructed reply packet """ reply = None ip_packet = ethernet_packet.child() eth_dst = ethernet_packet.get_ether_shost() for protocol_name, protocol_number, protocol_class in self.protocol_mapping: if event['protocol'] == protocol_number: # search for defined services for service in self.service_list: if protocol_name == service[0] and event['port_dst'] == service[1]: try: if service[2] == 'filtered': reply = protocol_class.filtered( ip_packet, path, self.personality, cb_ipid=self.get_ip_id, cb_icmpid=self.get_icmp_id) elif service[2] == 'closed': reply = protocol_class.closed( ip_packet, path, self.personality, cb_cipid=self.get_cip_id, cb_tcpseq=self.get_tcp_seq, cb_tcpts=self.get_tcp_ts) elif service[2] == 'open': reply = protocol_class.opened( ip_packet, path, self.personality, cb_ipid=self.get_ip_id, cb_tcpseq=self.get_tcp_seq, cb_tcpts=self.get_tcp_ts) elif service[2] == 'block': reply = protocol_class.blocked(ip_packet, path, self.personality) elif service[2].startswith('proxy '): proxy_data = service[2][len('proxy '):].split(':') proxy_ip = ipaddress.ip_address(unicode(proxy_data[0])) # proxy_mode = proxy_data[1] # find configured tunnel interface for tunnel_interface, remote_ip, tunnel_mode in tunnels: # self.interface, self.remote_ip, self.tunnel_mode if remote_ip == proxy_ip: # update ttl delta_ttl = ip_packet.get_ip_ttl() - path ip_packet.set_ip_ttl(delta_ttl) ip_packet.auto_checksum = 1 # create tunnel outer encapsulation # IPPROTO_GRE || IPPROTO_IPIP if tunnel_mode == 'gre': s = gevent.socket.socket( gevent.socket.AF_PACKET, gevent.socket.SOCK_RAW, gevent.socket.IPPROTO_GRE) s.sendto(ip_packet.get_packet(), (tunnel_interface, 0x0800)) else: s = gevent.socket.socket( gevent.socket.AF_PACKET, gevent.socket.SOCK_RAW, gevent.socket.IPPROTO_IPIP) s.sendto(ip_packet.get_packet(), (tunnel_interface, 0x0800)) reply_ip = cb_tunnel(proxy_ip) if reply_ip is None: return None delta_ttl = reply_ip.get_ip_ttl() - path if delta_ttl < 1: logger.debug('Reply packet dropped: TTL reached 0 within virtual network.') return reply_ip.set_ip_ttl(delta_ttl) reply_ip.auto_checksum = 1 reply_ip.set_ip_src(ip_packet.get_ip_dst()) reply_eth = ImpactPacket.Ethernet() reply_eth.set_ether_type(0x800) reply_eth.set_ether_shost(self.ethernet) reply_eth.set_ether_dhost(eth_dst) reply_eth.contains(reply_ip) return reply_eth else: logger.error('Error: No interface found for proxy IP %s', proxy_data[0]) break return None else: # script is excpected to provide proper IP packet as a reply as series of # bytes through stdout script = gevent.subprocess.Popen( service[2], shell=True, stdin=gevent.subprocess.PIPE, stdout=gevent.subprocess.PIPE, stderr=gevent.subprocess.PIPE) try: output, error = script.communicate(input=ip_packet.get_packet(), timeout=10) if not len(output): return None try: reply = self.decoder.decode(output) except BaseException: try: reply = self.decoder_icmp.decode(output) except BaseException: logger.exception( 'Exception: Cannot decode packet from script.') return None if len(error): logger.info('Service log: %s', error) inner_packet = reply.child() # TCP if reply.get_ip_p() == 6: inner_packet.set_th_sport(event['port_dst']) inner_packet.set_th_dport(event['port_src']) inner_packet.set_th_seq(self.get_tcp_seq()) inner_packet.calculate_checksum() reply.contains(inner_packet) # UDP elif reply.get_ip_p() == 17: inner_packet.set_uh_sport(event['port_dst']) packet = ip_packet.child() inner_packet.set_uh_dport(event['port_src']) inner_packet.calculate_checksum() reply.contains(inner_packet) # IP reply.set_ip_id(self.get_ip_id()) reply.set_ip_src(ip_packet.get_ip_dst()) reply.set_ip_dst(ip_packet.get_ip_src()) reply.auto_checksum = 1 except gevent.subprocess.TimeoutExpired: logger.exception('Exception: script timeout expired.') script.kill() return None except BaseException: logger.exception('Exception: script subprocess error.') script.kill() return None except Exception as ex: # log exception logger.exception('Exception: Device %s with issue: %s', self.name, ex) return None if reply is not None: reply_eth = ImpactPacket.Ethernet() reply_eth.set_ether_type(0x800) reply_eth.set_ether_shost(self.ethernet) reply_eth.set_ether_dhost(eth_dst) reply_eth.contains(reply) return reply_eth return None # check default actions try: if self.action_dictionary[protocol_name] == 'filtered': reply = protocol_class.filtered( ip_packet, path, self.personality, cb_ipid=self.get_ip_id, cb_icmpid=self.get_icmp_id) elif self.action_dictionary[protocol_name] == 'closed': reply = protocol_class.closed( ip_packet, path, self.personality, cb_cipid=self.get_cip_id, cb_tcpseq=self.get_tcp_seq, cb_tcpts=self.get_tcp_ts) elif self.action_dictionary[protocol_name] == 'open': reply = protocol_class.opened( ip_packet, path, self.personality, cb_ipid=self.get_ip_id, cb_tcpseq=self.get_tcp_seq, cb_tcpts=self.get_tcp_ts) elif self.action_dictionary[protocol_name] == 'block': reply = protocol_class.blocked(ip_packet, path, self.personality) elif self.action_dictionary[protocol_name].startswith('proxy '): proxy_data = self.action_dictionary[protocol_name][len('proxy '):].split(':') proxy_ip = ipaddress.ip_address(unicode(proxy_data[0])) proxy_mode = proxy_data[1] # find configured tunnel interface for tunnel_interface, remote_ip, tunnel_mode in tunnels: # self.interface, self.remote_ip, self.tunnel_mode if remote_ip == proxy_ip: # update ttl delta_ttl = ip_packet.get_ip_ttl() - path ip_packet.set_ip_ttl(delta_ttl) ip_packet.auto_checksum = 1 # create tunnel outer encapsulation # IPPROTO_GRE || IPPROTO_IPIP if tunnel_mode == 'gre': s = gevent.socket.socket( gevent.socket.AF_PACKET, gevent.socket.SOCK_RAW, gevent.socket.IPPROTO_GRE) s.sendto(ip_packet.get_packet(), (tunnel_interface, 0x0800)) else: s = gevent.socket.socket( gevent.socket.AF_PACKET, gevent.socket.SOCK_RAW, gevent.socket.IPPROTO_IPIP) s.sendto(ip_packet.get_packet(), (tunnel_interface, 0x0800)) reply_ip = cb_tunnel() if reply_ip is None: return None delta_ttl = reply_ip.get_ip_ttl() - path if delta_ttl < 1: logger.debug('Reply packet dropped: TTL reached 0 within virtual network.') return reply_ip.set_ip_ttl(delta_ttl) reply_ip.auto_checksum = 1 reply_ip.set_ip_src(ip_packet.get_ip_dst()) reply_ip.set_ip_dst(ip_packet.get_ip_src()) reply = reply_ip break else: logger.error('Error: No interface found for proxy IP %s', proxy_data[0]) return None except Exception as ex: # log exception logger.exception('Exception: Device %s with issue: %s', self.name, ex) if reply is not None: reply_eth = ImpactPacket.Ethernet() reply_eth.set_ether_type(0x800) try: reply_eth.set_ether_shost(self.ethernet) except IndexError: logger.exception('Exception: Invalid ethernet format: %s', self.ethernet) reply_eth.set_ether_dhost(eth_dst) reply_eth.contains(reply) return reply_eth return None