Source code for linuxnet.iptables.targets.masqueradetarget
# Copyright (c) 2021, 2022, 2023, 2024, Panagiotis Tsirigotis
# This file is part of linuxnet-iptables.
#
# linuxnet-iptables is free software: you can redistribute it and/or
# modify it under the terms of version 3 of the GNU Affero General Public
# License as published by the Free Software Foundation.
#
# linuxnet-iptables is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General
# Public License along with linuxnet-iptables. If not, see
# <https://www.gnu.org/licenses/>.
"""
This module provides the MasqueradeTarget class which provides access to
the iptables MASQUERADE target.
"""
from typing import List, Optional, Tuple
from ..deps import get_logger
from ..exceptions import IptablesParsingError
from .target import Target, TargetParser
_logger = get_logger("linuxnet.iptables.target.masqueradetarget")
[docs]class MasqueradeTarget(Target):
"""This class provides access to the ``MASQUERADE`` target
"""
def __init__(self, *,
port: Optional[int] =None, last_port: Optional[int] =None,
is_random=False, is_random_fully=False):
"""
:param port: port number (integer)
:param last_port: port number (integer) used when defining
a port range
:param is_random: if ``True``, use the **iptables(8)**
``--random`` option
:param is_random_fully: if ``True``, use the **iptables(8)**
``--random-fully`` option
"""
super().__init__('MASQUERADE', terminates=True)
self.__port = port
self.__last_port = last_port
self.__is_random = is_random
self.__is_random_fully = is_random_fully
[docs] def to_iptables_args(self) -> List[str]:
"""Returns a list of **iptables(8)** arguments
"""
retval = super().to_iptables_args()
if self.__port is not None:
dest_spec = f':{self.__port:d}'
if self.__last_port is not None:
dest_spec += f'-{self.__last_port:d}'
retval += ['--to-ports', dest_spec]
if self.__is_random:
retval.append('--random')
if self.__is_random_fully:
retval.append('--random-fully')
return retval
[docs] def uses_random_port_mapping(self) -> bool:
"""Returns the random target attribute
"""
return self.__is_random
[docs] def uses_fully_random_port_mapping(self) -> bool:
"""Returns the random-fully target attribute
"""
return self.__is_random_fully
[docs] def get_ports(self) -> Tuple[int, Optional[int]]:
"""Returns the port range
"""
return (self.__port, self.__last_port)
@classmethod
def parse(cls, parser: TargetParser) -> Target:
"""Parse the ``MASQUERADE`` target options
:meta private:
"""
field_iter = parser.get_field_iter()
# If there are arguments to the target, they are after the
# field 'masq'/'random'/'random-fully' fields which are optional.
field = field_iter.forward_to(['masq', 'random', 'random-fully'])
if field is None:
return MasqueradeTarget()
port = None
last_port = None
is_random = False
is_random_fully = False
field_iter.put_back(field)
for val in field_iter:
try:
if val == 'masq':
if next(field_iter) != 'ports:':
raise IptablesParsingError(
"'masq' not followed by 'ports:'")
port_spec = next(field_iter)
if '-' in port_spec:
port_str, last_port_str = port_spec.split('-', 1)
port = int(port_str)
last_port = int(last_port_str)
else:
port = int(port_spec)
elif val == 'random':
is_random = True
elif val == 'random-fully':
is_random_fully = True
else:
raise IptablesParsingError(
f'unknown MASQUERADE argument: {val}')
except IptablesParsingError:
raise
except Exception as ex:
raise IptablesParsingError(f'bad value for {val}') from ex
return MasqueradeTarget(port=port, last_port=last_port,
is_random=is_random,
is_random_fully=is_random_fully)
TargetParser.register_target('MASQUERADE', MasqueradeTarget)