def _reload_user_rules(self): '''Reload firewall rules file''' err_msg = _("problem running") if self.dryrun: msg("> | iptables-restore") if self.use_ipv6(): msg("> | ip6tables-restore") elif self.is_enabled(): # first flush the user logging chains try: for c in self.chains['user']: self._chain_cmd(c, ['-F', c]) self._chain_cmd(c, ['-Z', c]) except Exception: raise UFWError(err_msg) # then restore the system rules (rc, out) = cmd_pipe(['cat', self.files['rules']], \ [self.iptables_restore, '-n']) if rc != 0: raise UFWError(err_msg + " iptables") if self.use_ipv6(): (rc, out) = cmd_pipe(['cat', self.files['rules6']], \ [self.ip6tables_restore, '-n']) if rc != 0: raise UFWError(err_msg + " ip6tables")
def reset(self, force=False): """Reset the firewall""" res = "" prompt = _("Resetting all rules to installed defaults. Proceed with " "operation (%(yes)s|%(no)s)? ") % ( {"yes": self.yes, "no": self.no} ) if self.backend.do_checks and ufw.util.under_ssh(): prompt = _( "Resetting all rules to installed defaults. This may " "disrupt existing ssh connections. Proceed with " "operation (%(yes)s|%(no)s)? " ) % ({"yes": self.yes, "no": self.no}) if self.backend.do_checks and not force: msg(ufw.util.wrap_text(prompt), output=sys.stdout, newline=False) ans = sys.stdin.readline().lower().strip() if ans != "y" and ans != self.yes and ans != self.yes_full: res = _("Aborted") return res if self.backend.is_enabled(): res += self.set_enabled(False) res = self.backend.reset() return res
def _reload_user_rules(self): """Reload firewall rules file""" err_msg = _("problem running") if self.dryrun: msg("> | iptables-restore") if self.use_ipv6(): msg("> | ip6tables-restore") elif self._is_enabled(): # first flush the user logging chains try: for c in self.chains["user"]: self._chain_cmd(c, ["-F", c]) self._chain_cmd(c, ["-Z", c]) except Exception: raise UFWError(err_msg) # then restore the system rules (rc, out) = cmd_pipe(["cat", self.files["rules"]], [self.iptables_restore, "-n"]) if rc != 0: raise UFWError(err_msg + " iptables") if self.use_ipv6(): (rc, out) = cmd_pipe(["cat", self.files["rules6"]], [self.ip6tables_restore, "-n"]) if rc != 0: raise UFWError(err_msg + " ip6tables")
def start_firewall(self): '''Start the firewall''' err_msg = _("problem running") if self.dryrun: msg("> " + _("running ufw-init")) else: (rc, out) = cmd([self.files['init'], 'start']) if rc != 0: debug(out) raise UFWError(err_msg + " ufw-init") if not self.defaults.has_key('loglevel') or \ self.defaults['loglevel'] not in self.loglevels.keys(): # Add the loglevel if not valid try: self.set_loglevel("low") except Exception: err_msg = _("Could not set LOGLEVEL") raise UFWError(err_msg) else: try: self.update_logging(self.defaults['loglevel']) except Exception: err_msg = _("Could not load logging rules") raise UFWError(err_msg)
def stop_firewall(self): """Stops the firewall""" err_msg = _("problem running") if self.dryrun: msg("> " + _("running ufw-init")) else: (rc, out) = cmd([self.files["init"], "force-stop"]) if rc != 0: debug(out) raise UFWError(err_msg + " ufw-init")
def stop_firewall(self): '''Stop the firewall''' err_msg = _("problem running") if self.dryrun: msg("> " + _("running ufw-init")) else: (rc, out) = cmd([self.files['init'], 'force-stop']) if rc != 0: debug(out) raise UFWError(err_msg + " ufw-init")
def continue_under_ssh(self): '''If running under ssh, prompt the user for confirmation''' proceed = True if self.backend.do_checks and ufw.util.under_ssh(): # pragma: no cover prompt = _("Command may disrupt existing ssh connections. " \ "Proceed with operation (%(yes)s|%(no)s)? ") % \ ({'yes': self.yes, 'no': self.no}) msg(prompt, output=sys.stdout, newline=False) ans = sys.stdin.readline().lower().strip() if ans != "y" and ans != self.yes and ans != self.yes_full: proceed = False return proceed
def delete_rule(self, number, force=False): '''Delete rule''' try: n = int(number) except Exception: err_msg = _("Could not find rule '%s'") % number raise UFWError(err_msg) rules = self.backend.get_rules() if n <= 0 or n > len(rules): err_msg = _("Could not find rule '%d'") % n raise UFWError(err_msg) rule = self.backend.get_rule_by_number(n) if not rule: err_msg = _("Could not find rule '%d'") % n raise UFWError(err_msg) rule.remove = True ip_version = "v4" if rule.v6: ip_version = "v6" proceed = True if not force: if rule.forward: rstr = "route %s" % \ ufw.parser.UFWCommandRouteRule.get_command(rule) else: rstr = ufw.parser.UFWCommandRule.get_command(rule) prompt = _("Deleting:\n %(rule)s\nProceed with operation " \ "(%(yes)s|%(no)s)? ") % ({'rule': rstr, \ 'yes': self.yes, \ 'no': self.no}) msg(prompt, output=sys.stdout, newline=False) ans = sys.stdin.readline().lower().strip() if ans != "y" and ans != self.yes.lower() and \ ans != self.yes_full.lower(): proceed = False res = "" if proceed: res = self.set_rule(rule, ip_version) else: res = _("Aborted") return res
def reset(self, force=False): '''Reset the firewall''' res = "" prompt = _("Resetting all rules to installed defaults. Proceed with " \ "operation (%(yes)s|%(no)s)? ") % \ ({'yes': self.yes, 'no': self.no}) if self.backend.do_checks and ufw.util.under_ssh(): prompt = _("Resetting all rules to installed defaults. This may " \ "disrupt existing ssh connections. Proceed with " \ "operation (%(yes)s|%(no)s)? ") % \ ({'yes': self.yes, 'no': self.no}) if self.backend.do_checks and not force: # pragma: no cover msg(ufw.util.wrap_text(prompt), output=sys.stdout, newline=False) ans = sys.stdin.readline().lower().strip() if ans != "y" and ans != self.yes and ans != self.yes_full: res = _("Aborted") return res if self.backend.is_enabled(): res += self.set_enabled(False) res = self.backend.reset() return res
def set_rule(self, rule, allow_reload=True): """Updates firewall with rule by: * appending the rule to the chain if new rule and firewall enabled * deleting the rule from the chain if found and firewall enabled * inserting the rule if possible and firewall enabled * updating user rules file * reloading the user rules file if rule is modified """ rstr = "" if rule.v6: if not self.use_ipv6(): err_msg = _("Adding IPv6 rule failed: IPv6 not enabled") raise UFWError(err_msg) if rule.action == "limit": # Netfilter doesn't have ip6t_recent yet, so skip return _("Skipping unsupported IPv6 '%s' rule") % (rule.action) if rule.multi and rule.protocol != "udp" and rule.protocol != "tcp": err_msg = _("Must specify 'tcp' or 'udp' with multiple ports") raise UFWError(err_msg) newrules = [] found = False modified = False delete = False rules = self.rules position = rule.position if rule.v6: if self.iptables_version < "1.4" and (rule.dapp != "" or rule.sapp != ""): return _("Skipping IPv6 application rule. Need at least iptables 1.4") rules = self.rules6 # bail if we have a bad position if position < 0 or position > len(rules): err_msg = _("Invalid position '%d'") % (position) raise UFWError(err_msg) if position > 0 and rule.remove: err_msg = _("Cannot specify insert and delete") raise UFWError(err_msg) if position > len(rules): err_msg = _("Cannot insert rule at position '%d'") % position raise UFWError(err_msg) # First construct the new rules list try: rule.normalize() except Exception: raise count = 1 inserted = False matches = 0 last = ("", "", "", "") for r in rules: try: r.normalize() except Exception: raise current = (r.dst, r.src, r.dapp, r.sapp) if count == position: # insert the rule if: # 1. the last rule was not an application rule # 2. the current rule is not an application rule # 3. the last application rule is different than the current # while the new rule is different than the current one if ( (last[2] == "" and last[3] == "" and count > 1) or (current[2] == "" and current[3] == "") or last != current ): inserted = True newrules.append(rule.dup_rule()) last = ("", "", "", "") else: position += 1 last = current count += 1 ret = UFWRule.match(r, rule) if ret < 1: matches += 1 if ret == 0 and not found and not inserted: # If find the rule, add it if it's not to be removed, otherwise # skip it. found = True if not rule.remove: newrules.append(rule.dup_rule()) elif ret < 0 and not rule.remove and not inserted: # If only the action is different, replace the rule if it's not # to be removed. found = True modified = True newrules.append(rule.dup_rule()) else: newrules.append(r) if inserted: if matches > 0: rstr = _("Skipping inserting existing rule") if rule.v6: rstr += " (v6)" return rstr else: # Add rule to the end if it was not already added. if not found and not rule.remove: newrules.append(rule.dup_rule()) # Don't process non-existing or unchanged pre-exisiting rules if not found and rule.remove and not self.dryrun: rstr = _("Could not delete non-existent rule") if rule.v6: rstr += " (v6)" return rstr elif found and not rule.remove and not modified: rstr = _("Skipping adding existing rule") if rule.v6: rstr += " (v6)" return rstr if rule.v6: self.rules6 = newrules else: self.rules = newrules # Update the user rules file try: self._write_rules(rule.v6) except UFWError: raise except Exception: err_msg = _("Couldn't update rules file") UFWError(err_msg) # We wrote out the rules, so set reasonable string. We will change # this below when operating on the live firewall. rstr = _("Rules updated") if rule.v6: rstr = _("Rules updated (v6)") # Operate on the chains if self._is_enabled() and not self.dryrun: flag = "" if modified or self._need_reload(rule.v6) or inserted: rstr = "" if inserted: rstr += _("Rule inserted") else: rstr += _("Rule updated") if rule.v6: rstr += " (v6)" if allow_reload: # Reload the chain try: self._reload_user_rules() except Exception: raise else: rstr += _(" (skipped reloading firewall)") elif found and rule.remove: flag = "-D" rstr = _("Rule deleted") elif not found and not modified and not rule.remove: flag = "-A" rstr = _("Rule added") if flag != "": exe = self.iptables chain_prefix = "ufw" if rule.v6: exe = self.ip6tables chain_prefix = "ufw6" rstr += " (v6)" chain_suffix = "input" if rule.direction == "out": chain_suffix = "output" chain = "%s-user-%s" % (chain_prefix, chain_suffix) # Is the firewall running? err_msg = _("Could not update running firewall") (rc, out) = cmd([exe, "-L", chain, "-n"]) if rc != 0: raise UFWError(err_msg) rule_str = "%s %s %s" % (flag, chain, rule.format_rule()) pat_log = re.compile(r"(-A +)(ufw6?-user-[a-z\-]+)(.*)") for s in self._get_lists_from_formatted(rule_str, chain_prefix, chain_suffix): (rc, out) = cmd([exe] + s) if rc != 0: msg(out, sys.stderr) UFWError(err_msg) # delete any lingering RETURN rules (needed for upgrades) if flag == "-A" and pat_log.search(" ".join(s)): c = pat_log.sub(r"\2", " ".join(s)) (rc, out) = cmd([exe, "-D", c, "-j", "RETURN"]) if rc != 0: debug("FAILOK: -D %s -j RETURN" % (c)) return rstr
def set_rule(self, rule, allow_reload=True): '''Updates firewall with rule by: * appending the rule to the chain if new rule and firewall enabled * deleting the rule from the chain if found and firewall enabled * inserting the rule if possible and firewall enabled * updating user rules file * reloading the user rules file if rule is modified ''' rstr = "" if rule.v6: if not self.use_ipv6(): err_msg = _("Adding IPv6 rule failed: IPv6 not enabled") raise UFWError(err_msg) if rule.action == 'limit': # Netfilter doesn't have ip6t_recent yet, so skip return _("Skipping unsupported IPv6 '%s' rule") % (rule.action) if rule.multi and rule.protocol != "udp" and rule.protocol != "tcp": err_msg = _("Must specify 'tcp' or 'udp' with multiple ports") raise UFWError(err_msg) newrules = [] found = False modified = False rules = self.rules position = rule.position if rule.v6: if self.iptables_version < "1.4" and (rule.dapp != "" or \ rule.sapp != ""): return _( "Skipping IPv6 application rule. Need at least iptables 1.4" ) rules = self.rules6 # bail if we have a bad position if position < 0 or position > len(rules): err_msg = _("Invalid position '%d'") % (position) raise UFWError(err_msg) if position > 0 and rule.remove: err_msg = _("Cannot specify insert and delete") raise UFWError(err_msg) if position > len(rules): err_msg = _("Cannot insert rule at position '%d'") % position raise UFWError(err_msg) # First construct the new rules list try: rule.normalize() except Exception: raise count = 1 inserted = False matches = 0 last = ('', '', '', '') for r in rules: try: r.normalize() except Exception: raise current = (r.dst, r.src, r.dapp, r.sapp) if count == position: # insert the rule if: # 1. the last rule was not an application rule # 2. the current rule is not an application rule # 3. the last application rule is different than the current # while the new rule is different than the current one if (last[2] == '' and last[3] == '' and count > 1) or \ (current[2] == '' and current[3] == '') or \ last != current: inserted = True newrules.append(rule.dup_rule()) last = ('', '', '', '') else: position += 1 last = current count += 1 ret = UFWRule.match(r, rule) if ret < 1: matches += 1 if ret == 0 and not found and not inserted: # If find the rule, add it if it's not to be removed, otherwise # skip it. found = True if not rule.remove: newrules.append(rule.dup_rule()) elif ret < 0 and not rule.remove and not inserted: # If only the action is different, replace the rule if it's not # to be removed. found = True modified = True newrules.append(rule.dup_rule()) else: newrules.append(r) if inserted: if matches > 0: rstr = _("Skipping inserting existing rule") if rule.v6: rstr += " (v6)" return rstr else: # Add rule to the end if it was not already added. if not found and not rule.remove: newrules.append(rule.dup_rule()) # Don't process non-existing or unchanged pre-exisiting rules if not found and rule.remove and not self.dryrun: rstr = _("Could not delete non-existent rule") if rule.v6: rstr += " (v6)" return rstr elif found and not rule.remove and not modified: rstr = _("Skipping adding existing rule") if rule.v6: rstr += " (v6)" return rstr if rule.v6: self.rules6 = newrules else: self.rules = newrules # Update the user rules file try: self._write_rules(rule.v6) except UFWError: raise except Exception: err_msg = _("Couldn't update rules file") UFWError(err_msg) # We wrote out the rules, so set reasonable string. We will change # this below when operating on the live firewall. rstr = _("Rules updated") if rule.v6: rstr = _("Rules updated (v6)") # Operate on the chains if self.is_enabled() and not self.dryrun: flag = "" if modified or self._need_reload(rule.v6) or inserted: rstr = "" if inserted: rstr += _("Rule inserted") else: rstr += _("Rule updated") if rule.v6: rstr += " (v6)" if allow_reload: # Reload the chain try: self._reload_user_rules() except Exception: raise else: rstr += _(" (skipped reloading firewall)") elif found and rule.remove: flag = '-D' rstr = _("Rule deleted") elif not found and not modified and not rule.remove: flag = '-A' rstr = _("Rule added") if flag != "": exe = self.iptables chain_prefix = "ufw" if rule.v6: exe = self.ip6tables chain_prefix = "ufw6" rstr += " (v6)" chain_suffix = "input" if rule.direction == "out": chain_suffix = "output" chain = "%s-user-%s" % (chain_prefix, chain_suffix) # Is the firewall running? err_msg = _("Could not update running firewall") (rc, out) = cmd([exe, '-L', chain, '-n']) if rc != 0: raise UFWError(err_msg) rule_str = "%s %s %s" % (flag, chain, rule.format_rule()) pat_log = re.compile(r'(-A +)(ufw6?-user-[a-z\-]+)(.*)') for s in self._get_lists_from_formatted(rule_str, \ chain_prefix, \ chain_suffix): (rc, out) = cmd([exe] + s) if rc != 0: msg(out, sys.stderr) UFWError(err_msg) # delete any lingering RETURN rules (needed for upgrades) if flag == "-A" and pat_log.search(" ".join(s)): c = pat_log.sub(r'\2', " ".join(s)) (rc, out) = cmd([exe, '-D', c, '-j', 'RETURN']) if rc != 0: debug("FAILOK: -D %s -j RETURN" % (c)) return rstr