def prerouting(self, conn_port, target_port, target_addr): """Create the PREROUTING rule in the "nat" table :Returns: Integer - Rule ID :parm conn_port: The TCP port on the local machine to map. :type target_port: Integer :parm target_port: The TCP port on the remote machines to map. :type target_port: Integer :param target_addr: The IP address of the remote machien to map to. :type target_addr: String """ run_cmd( 'sudo iptables -A PREROUTING -t nat -i ens160 -p tcp --dport {} -j DNAT --to {}:{}' .format(conn_port, target_addr, target_port)) try: prerouting_id = self.find_rule(target_port, target_addr, table='nat', conn_port=conn_port) except RuntimeError: raise RuntimeError( 'Unable to find newly created PERROUTING rule for port {} to {}:{}' .format(conn_port, target_addr, target_port)) else: return prerouting_id
def show(self, table='filter', format='parsed'): """Display configured firewall rules for a given table :Returns: String or Dictionary :Raises: ValueError :param table: The specific iptable table to view, must be either 'filter' or 'nat' :type table: String, default "filter" :param format: Set to 'raw' for unprocess output, or 'parsed' for just the important stuff :type format: String, default 'parsed' """ with self: if table.lower() == 'nat': result = run_cmd( 'sudo iptables --numeric -L PREROUTING -t nat --line-numbers' ) if format.lower() == 'parsed': return self._prettify_nat_output(result.stdout) else: return result.stdout elif table.lower() == 'filter': result = run_cmd( 'sudo iptables --numeric -L FORWARD -t filter --line-numbers' ) if format.lower() == 'parsed': return self._prettify_filter_output(result.stdout) else: return result.stdout else: raise ValueError( 'Param "table" must be either "nat" or "filter", supplied: {}' .format(table))
def pingable(addr): """Issue a ping command to check if the target address is routable. :Returns: Boolean :param addr: The IPv4 address that is not ping-able :type addr: String """ try: shell.run_cmd(PING_SYNTAX.format(addr)) except shell.CliError: ok = False else: ok = True return ok
def test_cli_result_attributes(self): """Verify that the CliResult object attributes remain stable""" # NEVER REMOVE OR MODIFY A VALUE IN THIS LIST expected = ['command', 'exit_code', 'stderr', 'stdout'] result = shell.run_cmd('ls') for attr in expected: self.assertTrue(hasattr(result, attr))
def delete_rule(self, rule_id, table): """Destroy a port mapping rule :Returns: None :param rule_id: The rule by number to delete in the supplied table :type rule_id: String :param table: The specific table within iptables to delete a rule from. Must be either 'filter' or 'nat'. :type table: String """ with self: if table.lower() == 'nat': chain = 'PREROUTING' elif table.lower() == 'filter': chain = 'FORWARD' else: raise ValueError( 'Param "table" must be either "nat" or "filter", supplied: {}' .format(table)) run_cmd('iptables -t {} -D {} {}'.format(table, chain, rule_id))
def forward(self, target_port, target_addr): """Create the FORWARD rule in the "filter" table :Returns: Integer - Rule ID :parm target_port: The TCP port on the remote machines to map. :type target_port: Integer :param target_addr: The IP address of the remote machien to map to. :type target_addr: String """ run_cmd('sudo iptables -A FORWARD -p tcp -d {} --dport {} -j ACCEPT'. format(target_addr, target_port)) try: forward_id = self.find_rule(target_port, target_addr, table='filter') except RuntimeError: raise RuntimeError( 'Unable to find newly created FORWARD rule for {}:{}'.format( target_addr, target_port)) else: return forward_id
def save_rules(self): """Make the current firewall config persist reboots""" with self: result = run_cmd('sudo iptables-save') with open('/etc/iptables/rules.v4', 'w') as the_file: the_file.write(result.stdout)
def test_happy_path(self): """Running a valid command returns an instance of shell.CliResult""" result = shell.run_cmd('ls') self.assertTrue(isinstance(result, tuple))