Example #1
0
def rule_manager():
    filtable = Table('filter')
    firewalliot.block_rules()
    db.create_all()
    db.session.query(AuthConns).delete()
    db.session.commit()
    open('/var/log/firewall', 'w').close()
    while True:
        for row in db.session.query(AuthConns):
            if int(row.sessiontime) <= int(time.time()):
                try:
                    rule0 = Rule(
                        jump='ACCEPT',
                        protocol='udp',
                        matches=[Match('udp', '--dst ' + str(row.ip_addr))])
                    filtable.delete_rule('FORWARD', rule0)
                except IptablesError as e:
                    pass
                db.session.delete(
                    AuthConns.query.filter(AuthConns.id == row.id).first())
            elif not row.fw_status:
                rule0 = Rule(
                    jump='ACCEPT',
                    protocol='udp',
                    matches=[Match('udp', '--dst ' + str(row.ip_addr))])
                filtable.prepend_rule('FORWARD', rule0)
                cwfwrule = AuthConns.query.filter_by(id=row.id).first()
                cwferule.fw_status = True
            elif not row.ip_port:
                log_lookup()
                manage_logging()
            else:
                pass
        db.session.commit()
        time.sleep(15)
def unfilter_ports(device):
    """Removes from iptables the ports related with gluster on the given device."""

    input_filter = 'gluster-input'
    output_filter = 'gluster-output'

    print "Removing Gluster port filtering..."

    table = Table('filter')

    chains = table.list_chains()

    if input_filter in chains:

        in_rule = Rule(in_interface=device, jump=input_filter)
        try:
            table.delete_rule('INPUT', in_rule)
        except IptablesError:
            pass
        table.flush_chain(input_filter)
        table.delete_chain(input_filter)
    else:
        print "Gluster input ports are not filtered. Ignoring request..."

    if output_filter in chains:

        out_rule = Rule(out_interface=device, jump=output_filter)
        table.delete_rule('OUTPUT', out_rule)
        table.flush_chain(output_filter)
        table.delete_chain(output_filter)
    else:
        print "Gluster output ports are not filtered. Ignoring request..."
Example #3
0
def unblock_outgoing_packets(proto,
                             ipsrc=None,
                             portsrc=None,
                             ipdst=None,
                             portdst=None):
    """
    Unblocks outgoing packets coming from the kernel using iptables command.
    """
    matches = []
    if portsrc:
        matches.append(Match('tcp', '--sport ' + str(portsrc)))
    if portdst:
        matches.append(Match('tcp', '--dport ' + str(portdst)))
    rule = Rule(
        #in_interface=interface,
        protocol=proto,
        source=ipsrc,
        destination=ipdst,
        matches=matches,
        jump='DROP')

    table = Table('filter')
    try:
        table.delete_rule('OUTPUT', rule)
    except IptablesError:
        print("Unknown rule !", proto, ipsrc, portsrc, ipdst, portdst)
Example #4
0
    def disable_subscription(self, ipaddress, macaddress):
        rule_masquerade = Rule(source=ipaddress, jump="MASQUERADE")

        rule_restrict = Rule(source=ipaddress, matches=[Match("mac", "--mac-source " + macaddress)], jump="ACCEPT")

        table = Table("nat")
        try:
            table.delete_rule("POSTROUTING", rule_masquerade)
            table.delete_rule("PREROUTING", rule_restrict)
        except IptablesError, e:
            sys.stdout.write("Ignoring non-existant rule")
Example #5
0
    def unmarkhost(self, oid, ipaddress):
        target_out = Target('CONNMARK', '--set-mark '+str(oid))
        rule_out = Rule(
            source = ipaddress + "/32",
            jump = target_out)

        target_in = Target('CONNMARK', '--set-mark '+str(oid))
        rule_in = Rule(
            destination = ipaddress + "/32",
            jump = target_out)

        table = Table('mangle')
        try:
            table.delete_rule('out_traffic', rule_out)
            table.delete_rule('in_traffic', rule_in)        
        except IptablesError, e:
            sys.stdout.write('Rule not found: %s' % e)            
Example #6
0
def force_remove(ip_addr):
    filtable = Table('filter')
    try:
        rule0 = Rule(jump='ACCEPT',
                     protocol='udp',
                     matches=[Match('udp', '--dst ' + str(ip_addr))])
        filtable.delete_rule('FORWARD', rule0)
    except IptablesError as e:
        pass

    try:
        rule1 = Rule(jump='LOG',
                     protocol='udp',
                     matches=[
                         Match('udp', '--dst ' + ip_addr),
                         Match('limit', '--limit 1/hour --limit-burst 1')
                     ])
        filtable.delete_rule('FORWARD', rule1)
    except IptablesError as e:
        pass
Example #7
0
def manage_logging():
    filtable = Table('filter')
    for row in db.session.query(AuthConns):
        if row.ip_port and not row.port_status:

            rule0 = Rule(jump='ACCEPT',
                         protocol='udp',
                         matches=[
                             Match(
                                 'udp', '--dst ' + str(row.ip_addr) +
                                 ' --dport ' + str(row.ip_port))
                         ])
            filtable.prepend_rule('FORWARD', rule0)

            try:
                rule1 = Rule(jump='LOG',
                             protocol='udp',
                             matches=[
                                 Match('udp', '--dst ' + str(row.ip_addr)),
                                 Match('limit',
                                       '--limit 1/hour --limit-burst 1')
                             ])
                filtable.delete_rule('FORWARD', rule1)
            except IptablesError as e:
                pass
            try:
                rule2 = Rule(
                    jump='ACCEPT',
                    protocol='udp',
                    matches=[Match('udp', '--dst ' + str(row.ip_addr))])
                filtable.delete_rule('FORWARD', rule2)
            except IptablesError as e:
                pass

            row.port_status = True

        else:
            pass
Example #8
0
def unblock_outgoing_packets(proto, ipsrc=None, portsrc=None, ipdst=None, portdst=None):
    """
    Unblocks outgoing packets coming from the kernel using iptables command.
    """
    matches = []
    if portsrc:
        matches.append(Match("tcp", "--sport " + str(portsrc)))
    if portdst:
        matches.append(Match("tcp", "--dport " + str(portdst)))
    rule = Rule(
        # in_interface=interface,
        protocol=proto,
        source=ipsrc,
        destination=ipdst,
        matches=matches,
        jump="DROP",
    )

    table = Table("filter")
    try:
        table.delete_rule("OUTPUT", rule)
    except IptablesError:
        print("Unknown rule !", proto, ipsrc, portsrc, ipdst, portdst)
Example #9
0
class PortKnocker():
    '''
    Class for analysis iptables log messages and open port upon attempt connect to port.
    '''
    def __init__(self, *args, **kwargs):
        # Files for processing.
        self.pidfile = kwargs["pidfile"]
        self.portknocker_logfile = "/var/log/portknocker_daemon.log"
        self.iptables_logfile = "/dev/shm/iptables.log"
        self.dumpfile = os.path.dirname(
            os.path.realpath(__file__)) + os.sep + "portknocker.dmp"

        # Logger parameters for daemon.
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)
        self.fh = logging.FileHandler(self.portknocker_logfile)
        self.fh.setLevel(logging.INFO)
        self.formatstr = '%(asctime)s - %(levelname)s - %(message)s'
        self.formatter = logging.Formatter(self.formatstr)
        self.fh.setFormatter(self.formatter)
        self.logger.addHandler(self.fh)

        # Netfilter table for setting rules.
        self.table = Table("filter")

        # Reserved ports {"in_int:port":"src_ip"}.
        self.ports = dict()

        # Clean for start, stop and restart daemon.
        self.clean()

    def tail(self, monfile):
        '''
        Get last line in file,  similarly to tail -f filename.
        '''
        try:
            while True:
                for line in tailer.follow(monfile, 1):
                    time.sleep(0.1)
                    yield line
        except:
            self.logger.error("Error while log-file parsing.")

    def set_rule(self, in_int, port, src_ip):
        '''
        Make netfilter rule.
        -I INPUT -i $int_in -p tcp --dport $port -j ACCEPT
        '''
        rule = Rule(in_interface=f"{in_int}",
                    source=f"{src_ip}",
                    protocol="tcp",
                    matches=[Match("tcp", f"--dport {port}")],
                    jump="ACCEPT")
        return rule

    def check_netfilter_rule(self, in_int, port, src_ip):
        '''
        Check rule availability in netfilter.
        '''
        return True if self.set_rule(in_int, port, src_ip) in [
            _rule for _rule in self.table.list_rules("INPUT")
        ] else False

    def set_netfilter_rule(self, in_int, port, src_ip):
        '''
        Set netfilter rule.
        '''
        try:
            if not self.check_netfilter_rule(in_int, port, src_ip):
                self.table.prepend_rule("INPUT",
                                        self.set_rule(in_int, port, src_ip))
                self.logger.info(
                    f"Add netfilter rule for in_int:{in_int} port:{port} src_ip:{src_ip}"
                )
        except:
            self.logger.error(
                f"Rule setting error, in_int:{in_int} port:{port} src_ip:{src_ip}"
            )

    def delete_netfilter_rule(self, in_int, port, src_ip):
        '''
        Delete netfilter rule.
        -D INPUT -t in_int -s src_ip --dport $port
        '''
        try:
            if self.check_netfilter_rule(in_int, port, src_ip):
                self.table.delete_rule('INPUT',
                                       self.set_rule(in_int, port, src_ip))
                self.logger.info(
                    f"Delete netfilter rule for in_int:{in_int} port:{port} src_ip:{src_ip}"
                )
        except:
            self.logger.error(
                f"Error removing netfilter rule, in_int:{in_int} port:{port} src_ip:{src_ip}"
            )

    def checking_established_connections(self, in_int, port, src_ip):
        '''
        Check established port connection.
        If not established connection, then delete for opening port netfilter rule.
        '''
        while True:
            # Timeoute for establish connection.
            time.sleep(30)
            # Enumeration of available connections by port number and connection status.
            if [port, "ESTABLISHED"] in [[str(conn.laddr.port), conn.status]
                                         for conn in psutil.net_connections()]:
                self.logger.info(
                    f"Connection ESTABLISHED port:{port} src_ip:{src_ip}")
                # Timeout before next check connection status.
                time.sleep(30)
            else:
                try:
                    # Delete iptables rule for port opening..
                    self.delete_netfilter_rule(in_int, port, src_ip)
                    self.logger.info(
                        f"Disconnect in_int: port:{port} src_ip:{src_ip}")
                    # Delete port from list reservated.
                    self.deleting_reserved_port(f"{in_int}:{port}")
                    return True
                except:
                    self.logger.error(
                        f"Error while closing the connection, port:{port} src_ip:{src_ip}"
                    )
                    return False

    def save_reservated_ports_set_to_disk(self):
        '''
        Save list reserved ports to file.
        '''
        try:
            with open(self.dumpfile, "w") as dumpfile:
                if len(self.ports):
                    for in_int_port, src_ip in self.ports.items():
                        dumpfile.write(f"{in_int_port}:{src_ip}\n")
            os.chmod(self.dumpfile, 0o600)
        except:
            self.logger.error("Error writing dump file.")

    def get_reservated_ports_from_dumpfile(self):
        '''
        Get list reserved ports from file.
        '''
        try:
            if os.path.exists(
                    self.dumpfile) and (os.path.getsize(self.dumpfile) > 1):
                with open(self.dumpfile, "r") as dumpfile:
                    self.ports = {
                        f"{in_int}:{port}": src_ip
                        for in_int, port, src_ip in [
                            port.rstrip().split(':')
                            for port in dumpfile.readlines()
                        ]
                    }
        except:
            self.logger.error("Error while get reserved ports from file.")

    def set_reservated_port(self, in_int, port, src_ip):
        '''
        Save port number to list reserved ports and save this list to file.
        '''
        try:
            self.ports[f"{in_int}:{port}"] = src_ip
            self.save_reservated_ports_set_to_disk()
        except:
            self.logger.error("Error saving the reserved port.")

    def deleting_all_created_rules(self):
        '''
        Delete all set rule.
        If in memory not reserved ports, then checking records in dumpfile.
        '''
        try:
            # Actions "start" and "stop" create new class copy,
            # him need loading list reserved ports.в
            if not len(self.ports):
                self.get_reservated_ports_from_dumpfile()
            for in_int_port, src_ip in self.ports.items():
                in_int, port = in_int_port.split(':')
                self.delete_netfilter_rule(in_int, port, src_ip)
        except:
            self.logger.warning(
                "Error while remove all rule with reserved ports.")
            return False
        return True

    def clean_reservated_port_file(self):
        '''
        Delete dumpfile.
        '''
        try:
            os.remove(self.dumpfile)
        except:
            self.logger.warning(
                "Error while remove dumpfile. Dumpfile may be missing.")

    def deleting_reserved_port(self, in_int_port):
        '''
        Delete port from list reserved ports and
        save actual list to disk.
        '''
        try:
            if len(self.ports):
                self.ports.pop(in_int_port, 0)
                self.save_reservated_ports_set_to_disk()
        except:
            self.logger.error("Error deleting reserved port.")

    def port_connection_reservate(self):
        '''
        Reserve port and set netfilter rule for port opening.
        '''
        # Counter attempting connection to port.
        port_knock_counter = {}
        # Dictionary of active timer threads.
        timer_threads = {}
        # Dictionary of threads active observed connections.
        connection_threads = {}

        def reservate(in_int, port, src_ip):
            # Port connection attempt counting.
            port_knock_counter[port] = port_knock_counter.setdefault(port, 0)
            port_knock_counter[port] += 1
            # If attempt not one, then running timer.
            if port_knock_counter[port] == 2:
                timer_thread = Thread(name=port,
                                      target=time.sleep,
                                      args=(10, ),
                                      daemon=True)
                timer_threads[port] = timer_thread
                timer_thread.start()
            # Reservate port after five attempting and reset attempt counter.
            if port_knock_counter[port] == 5:
                self.set_reservated_port(in_int, port, src_ip)
                port_knock_counter[port] = 0
                # Because checking thread activity can call exception,  do this.
                connection_threads[port] = Thread(name=port)
                if not timer_threads[port].is_alive(
                ) and not connection_threads[port].is_alive():
                    # Reset attempt counter after stopping timer.
                    port_knock_counter[port] = 0
                # Create netfilter rule for reserved port and starting observed.
                if [
                        key for key in self.ports.keys()
                        if [in_int, port] in [key.split(':')]
                ]:
                    # Sets netfilter rules.
                    self.set_netfilter_rule(in_int, port, src_ip)
                    try:
                        # The flow, in which carried out observant to connection and deleting netfilter rule after disconnect to port.
                        connection_thread = Thread(
                            name=port,
                            target=self.checking_established_connections,
                            args=(
                                in_int,
                                port,
                                src_ip,
                            ),
                            daemon=True)
                        connection_threads[port] = connection_thread
                        connection_thread.start()
                    except:
                        self.logger.error(
                            'Error creating connection control thread!')

        return reservate

    def clean(self):
        '''
        Netfilter rules and dumpfile clean when daemon restarted or stopping.
        '''
        try:
            self.deleting_all_created_rules()
            self.clean_reservated_port_file()
            self.logger.info('PortKnocker stopped ...')
        except:
            self.logger.error('Error clearing rules.')

    def run(self):
        '''
        Master cycle running netfilter log file analyser for search in him new connection records. 
        You need set netfilter rule, equivalent to this template:
        start_port=10000:10049,10051 && \
        end_port=50000 && \
        iptables -I INPUT -i enp0s3 -p tcp -m multiport --dports $start_port:$end_port -j DROP && \
        iptables -I INPUT -i enp0s3 -p tcp -m multiport --dports $start_port:$end_port -j LOG --log-prefix "Iptables: port_knocker " 
        '''
        self.setting_up_rsyslog()
        self.logger.info("PortKnocker running ...")
        reserved_port = self.port_connection_reservate()
        with open(self.iptables_logfile, "w+") as f:
            for line in self.tail(f):
                # Long enough record in netfilter log file containing: string "Iptables: port_knocker",
                # input interface, destination port and note about SYN type package.
                if ("Iptables: port_knocker"
                        in line) and (line.find(" DPT=")
                                      and line.find(" SYN ")):
                    reserved_port(
                        str(*re.findall(r"IN=\w+", line))[3:],
                        str(*re.findall(r"DPT=\d+", line))[4:],
                        str(*re.findall(r"SRC=[\d+\.]+", line))[4:])
                self.clean_log()

    def setting_up_rsyslog(self):
        '''
        Configuring rsislog settings for iptables logging.
        '''
        rsyslog_confd_file = "/etc/rsyslog.d/10-iptables.conf"
        rsyslog_cfg_string = f':msg, contains, "Iptables: port_knocker " -{self.iptables_logfile}\n& ~'
        try:
            with open(rsyslog_confd_file, "r") as rsys_confd:
                for line in rsys_confd.readlines():
                    if "Iptables: port_knocker" in line:
                        return
                raise FileNotFoundError
        except FileNotFoundError:
            with open(rsyslog_confd_file, "w+") as rsys_confd:
                rsys_confd.write(rsyslog_cfg_string)
                self.logger.info(f"Added settings to {rsyslog_confd_file}")
        try:
            os.system("systemctl restart rsyslog")
        except:
            self.logger.error(
                "Check for the rsyslog service. Portknocker demon stopped.")
            self.clean()
            sys.exit()

    def clean_log(self, *args, **kwargs):
        '''
        Cleaning log-files.
        '''
        try:
            logfile = kwargs["logfile"]
            critical_size = kwargs["critical_size"]
        except:
            logfile = self.iptables_logfile
            critical_size = 1048576
        try:
            if os.path.getsize(logfile) >= critical_size:
                open(logfile, "w").close()
        except:
            self.logger.warning(f"Failed to clean up {logfile} file")

    def _demonize(self):
        '''
        Demonization of the portknocker process.
        '''
        self._terminate_daemon_process()
        if os.path.exists(self.pidfile):
            try:
                os.remove(self.pidfile)
            except:
                self.logger.error(
                    f"Pleas check {self.pidfile} permissons and delete him.")
                sys.exit()
        self._start()

    def _start(self):
        '''
        Set the daemon context and run the application.
        '''
        pidlock = PIDLockFile(self.pidfile)
        with DaemonContext(
                pidfile=pidlock,
                working_directory=os.path.dirname(os.path.realpath(__file__)) +
                os.sep,
                stdout=self.fh.stream,
                stderr=self.fh.stream):
            return self.run()

    def _terminate_daemon_process(self):
        '''
        Exit the daemon process specified in the current PID file.
        '''
        self.clean()
        try:
            with open(self.pidfile, "r") as pidfile:
                pid = int(pidfile.readline().strip())
        except:
            self.logger.error(f"Failed to read pidfile {self.pidfile}")
            return
        try:
            os.kill(pid, signal.SIGTERM)
            self.logger.info("Portknocker demon stopped.")
        except:
            self.logger.error(f"Failed to terminate {pid}.")
            return

    def _restart(self):
        '''
        Restart daemon.
        '''
        self._terminate_daemon_process()
        self._start()
Example #10
0
def desbloqueaIP(ip):
	regla = Rule(source = ip, jump = 'DROP')
	tabla = Table('filter')
	tabla.delete_rule('INPUT', regla)