def unblock(self): ''' ''' st,output = getstatusoutput("pfctl -a switchyard -Fr") # flush rules log_debug("Flushing rules: {}".format(output)) st,output = getstatusoutput("pfctl -X {}".format(self._token)) log_info("Releasing pf: {}".format(output.replace('\n', '; ')))
def __init__(self, interfaces, rules): super().__init__(interfaces, rules) self._intf = interfaces st,output = getstatusoutput("iptables-save") self._saved_iptables = output self._arpignore = {} self._rulecmds = [ 'iptables -F', 'iptables -t raw -F' ] # --protocol {} -i {} --port {} doall = False for r in rules: cmds = self._parse_rule(r) self._rulecmds.extend(cmds) if r == 'all': doall = True if doall: badintf = [] for intf in interfaces: st,output = getstatusoutput('sysctl net.ipv4.conf.{}.arp_ignore'.format(intf)) if st != 0: badintf.append(intf) continue self._arpignore[intf] = int(output.split()[-1]) st,output = getstatusoutput('sysctl -w net.ipv4.conf.{}.arp_ignore=8'.format(intf)) for intf in badintf: self._intf.remove(intf) # alias of interfaces, so just remove # from self._intf log_debug("Rules to install: {}".format(self._rulecmds))
def send_packet(self, dev, packet): ''' Send a Switchyard Packet object on the given device (string name of device). Raises SwitchyException if packet object isn't valid, or device name isn't recognized. ''' if isinstance(dev, int): dev = self._lookup_devname(dev) if isinstance(dev, Interface): dev = dev.name pdev = self.pcaps.get(dev, None) if not pdev: raise SwitchyException( "Unrecognized device name for packet send: {}".format(dev)) else: if packet is None: raise SwitchyException("No packet object given to send_packet") if not isinstance(packet, Packet): raise SwitchyException( "Object given to send_packet is not a Packet (it is: {})". format(type(packet))) # convert packet to bytes and send it rawpkt = packet.to_bytes() log_debug("Sending packet on device {}: {}".format( dev, str(packet))) pdev.send_packet(rawpkt)
def block(self): ''' pfctl -a switchyard -f- < rules.txt pfctl -a switchyard -F rules pfctl -t switchyard -F r ''' st,output = _sendcmd(["/sbin/pfctl","-aswitchyard", "-f-"], self._rules) log_debug("Installing rules: {}".format(output))
def _recv(self, nbytes): try: data, sourceaddr, destaddr = self._socket_queue_from_stack.get( block=self._block, timeout=self._timeout) log_debug("recv from {}<-{}:{}".format(data, sourceaddr, destaddr)) return data, sourceaddr, destaddr except Empty as e: pass log_debug("recv timed out") raise timeout("timed out")
def bind(self, address): # block firewall port # set stack to only allow packets through for addr/port self._local_addr = address # update firewall and pcap filters log_debug( "Updating firewall/bpf rule on bind(): {} dst port {}".format( self._protoname, self._local_addr[1])) Firewall.add_rule("{}:{}".format(self._protoname, self._local_addr[1])) PcapLiveDevice.set_bpf_filter_on_all_devices("{} dst port {}".format( self._protoname, self._local_addr[1]))
def _sig_handler(self, signum, stack): ''' Handle process INT signal. ''' log_debug("Got SIGINT.") if signum == signal.SIGINT: PyLLNet.running = False if self.pktqueue.qsize() == 0: # put dummy pkt in queue to unblock a # possibly stuck user thread self.pktqueue.put( (None,None,None) ) self.pktqueue = Queue()
def _sig_handler(self, signum, stack): ''' Handle process INT signal. ''' log_debug("Got SIGINT.") if signum == signal.SIGINT: PyLLNet.running = False if self.pktqueue.qsize() == 0: # put dummy pkt in queue to unblock a # possibly stuck user thread self.pktqueue.put((None, None, None)) self.pktqueue = Queue()
def __init__(self, interfaces, rules): super().__init__(interfaces, rules) self._interfaces = interfaces for r in rules: cmds = self._parse_rule(r) self._rules.extend(cmds) st,output = getstatusoutput("pfctl -E") mobj = re.search("Token\s*:\s*(\d+)", output, re.M) if mobj is None: raise RuntimeError("Couldn't get pfctl token. Are you running as root?") self._token = mobj.groups()[0] log_debug("Rules to install: {}".format(self._rules)) log_info("Enabling pf: {}".format(output.replace('\n', '; ')))
def __low_level_dispatch(pcapdev, devname, pktqueue): ''' Thread entrypoint for doing low-level receive and dispatch for a single pcap device. ''' count = 0 while PyLLNet.running: # a non-zero timeout value is ok here; this is an # independent thread that handles input for this # one pcap device. it throws any packets received # into the shared queue (which is read by the actual # user code) pktinfo = pcapdev.recv_packet(timeout=0.2) if pktinfo is None: continue log_debug("Got packet on device {}, dlt {}".format(devname, pcapdev.dlt)) pktqueue.put( (devname,pcapdev.dlt,pktinfo) ) count += 1 if count % 100 == 0: stats = pcapdev.stats() log_debug("Periodic device statistics {}: {} received, {} dropped, {} dropped/if".format(devname, stats.ps_recv, stats.ps_drop, stats.ps_ifdrop)) log_debug("Receiver thread for {} exiting".format(devname)) stats = pcapdev.stats() log_debug("Final device statistics {}: {} received, {} dropped, {} dropped/if".format(devname, stats.ps_recv, stats.ps_drop, stats.ps_ifdrop))
def __low_level_dispatch(pcapdev, devname, pktqueue): ''' Thread entrypoint for doing low-level receive and dispatch for a single pcap device. ''' count = 0 while PyLLNet.running: # a non-zero timeout value is ok here; this is an # independent thread that handles input for this # one pcap device. it throws any packets received # into the shared queue (which is read by the actual # user code) pktinfo = pcapdev.recv_packet(timeout=0.2) if pktinfo is None: continue log_debug("Got packet on device {}, dlt {}".format( devname, pcapdev.dlt)) pktqueue.put((devname, pcapdev.dlt, pktinfo)) count += 1 if count % 100 == 0: stats = pcapdev.stats() log_debug( "Periodic device statistics {}: {} received, {} dropped, {} dropped/if" .format(devname, stats.ps_recv, stats.ps_drop, stats.ps_ifdrop)) log_debug("Receiver thread for {} exiting".format(devname)) stats = pcapdev.stats() log_debug( "Final device statistics {}: {} received, {} dropped, {} dropped/if" .format(devname, stats.ps_recv, stats.ps_drop, stats.ps_ifdrop))
def __init__(self, family, xtype, proto=0, fileno=0): family = AddressFamily(family) if family != AddressFamily.AF_INET: raise NotImplementedError( "socket for family {} not implemented".format(family)) if xtype not in [SOCK_DGRAM, SOCK_STREAM]: raise NotImplementedError( "socket type {} not implemented".format(xtype)) self._family = family self._socktype = xtype self._protoname = 'udp' self._proto = IPProtocol.UDP if self._socktype == SOCK_STREAM: self._protoname = 'tcp' self._proto = IPProtocol.TCP self._timeout = None self._block = True self._remote_addr = (None, None) self._local_addr = ('0.0.0.0', _get_ephemeral_port()) log_debug("Adding firewall/bpf rule {} dst port {}".format( self._protoname, self._local_addr[1])) try: Firewall.add_rule("{}:{}".format(self._protoname, self._local_addr[1])) # only get packets with destination port of local port, or any # icmp packets PcapLiveDevice.set_bpf_filter_on_all_devices( "{} dst port {} or icmp".format(self._protoname, self._local_addr[1])) except: with yellow(): print( "Unable to complete socket emulation setup (failed on firewall/bpf filter installation). Did you start the program via srpy?" ) import traceback print("Here is the raw exception information:") with red(): print(indent(traceback.format_exc(), ' ')) sys.exit() ApplicationLayer.init() self._socket_queue_to_stack, self._socket_queue_from_stack = ApplicationLayer.queues( )
def send_packet(self, dev, packet): ''' Send a Switchyard Packet object on the given device (string name of device). Raises SwitchyException if packet object isn't valid, or device name isn't recognized. ''' pdev = self.pcaps.get(dev, None) if not pdev: raise SwitchyException("Unrecognized device name for packet send: {}".format(dev)) else: if packet is None: raise SwitchyException("No packet object given to send_packet") if not isinstance(packet, Packet): raise SwitchyException("Object given to send_packet is not a Packet (it is: {})".format(type(packet))) # convert packet to bytes and send it rawpkt = packet.to_bytes() log_debug("Sending packet on device {}: {}".format(dev, str(packet))) pdev.send_packet(rawpkt)
def __init__(self, devlist, name=None): LLNetBase.__init__(self) signal.signal(signal.SIGINT, self._sig_handler) signal.signal(signal.SIGTERM, self._sig_handler) signal.signal(signal.SIGHUP, self._sig_handler) signal.signal(signal.SIGUSR1, self._sig_handler) signal.signal(signal.SIGUSR2, self._sig_handler) self.devs = devlist # self.__initialize_devices(includelist, excludelist) self.devinfo = self.__assemble_devinfo() self.pcaps = {} self.__make_pcaps() log_info("Using network devices: {}".format(' '.join(self.devs))) for devname, intf in self.devinfo.items(): log_debug("{}: {}".format(devname, str(intf))) PyLLNet.running = True self.__spawn_threads() if name: self.__name = name else: self.__name = gethostname()
def shutdown(self): ''' Should be called by Switchyard user code when a network object is being shut down. (This method cleans up internal threads and network interaction objects.) ''' if not PyLLNet.running: return PyLLNet.running = False log_debug("Joining threads for shutdown") for t in self.threads: t.join() log_debug("Closing pcap devices") for devname,pdev in self.pcaps.items(): pdev.close() log_debug("Done cleaning up")
def shutdown(self): ''' Should be called by Switchyard user code when a network object is being shut down. (This method cleans up internal threads and network interaction objects.) ''' if not PyLLNet.running: return PyLLNet.running = False log_debug("Joining threads for shutdown") for t in self.threads: t.join() log_debug("Closing pcap devices") for devname, pdev in self.pcaps.items(): pdev.close() log_debug("Done cleaning up")
def shutdown(self): self.__linkem.shutdown() self.__done = True log_debug("Joining node codeexec thread {} node {}".format(self.__t.name, self.__name)) self.__t.join()
def setup_switchyard_stack(proto, localaddr): log_debug("Starting up stack thread") ApplicationLayer.init() return ApplicationLayer.queues()
def _send(self, data, remote_addr): log_debug("socketemu send: {}->{}:{}".format(data, self._local_addr, remote_addr)) self._socket_queue_to_stack.put((data, self._local_addr, remote_addr))
def add_rule(self, rule): for cmd in self._parse_rule(rule): st,output = getstatusoutput(cmd) self._rulecmds.append(cmd) log_debug("Adding firewall rule: {}".format(cmd))
def add_rule(self, rule): cmds = self._parse_rule(rule) self._rules.extend(cmds) st,output = _sendcmd(["/sbin/pfctl","-aswitchyard", "-f-"], cmds) log_debug("Adding firewall rules: {}".format(cmds))
def shutdown(self): self.__linkem.shutdown() self.__done = True log_debug("Joining node codeexec thread {} node {}".format( self.__t.name, self.__name)) self.__t.join()
def add_rule(self, rule): for cmd in self._parse_rule(rule): st, output = getstatusoutput(cmd) self._rulecmds.append(cmd) log_debug("Adding firewall rule: {}".format(cmd))
def __del__(self): log_debug("Exiting socket code")