Skip to content

Firewall API

Firewall configuration classes.

FirewallConfig

FirewallConfig

Bases: UCISection

Firewall configuration manager.

Source code in src/wrtkit/firewall.py
class FirewallConfig(UCISection):
    """Firewall configuration manager."""

    zones: List[FirewallZone] = Field(default_factory=list)
    forwardings: List[FirewallForwarding] = Field(default_factory=list)
    remote_policy: Optional[RemotePolicy] = None

    def __init__(self, **data: Any) -> None:
        super().__init__(**data)
        self._package = "firewall"
        self._section = ""
        self._section_type = ""

    def add_zone(self, zone: FirewallZone) -> "FirewallConfig":
        """Add a zone and return self for chaining."""
        self.zones.append(zone)
        return self

    def add_forwarding(self, forwarding: FirewallForwarding) -> "FirewallConfig":
        """Add a forwarding rule and return self for chaining."""
        self.forwardings.append(forwarding)
        return self

    def get_commands(self) -> List[UCICommand]:
        """Get all UCI commands for firewall configuration."""
        commands = []
        for zone in self.zones:
            commands.extend(zone.get_commands())
        for forwarding in self.forwardings:
            commands.extend(forwarding.get_commands())
        return commands

add_zone(zone)

Add a zone and return self for chaining.

Source code in src/wrtkit/firewall.py
def add_zone(self, zone: FirewallZone) -> "FirewallConfig":
    """Add a zone and return self for chaining."""
    self.zones.append(zone)
    return self

add_forwarding(forwarding)

Add a forwarding rule and return self for chaining.

Source code in src/wrtkit/firewall.py
def add_forwarding(self, forwarding: FirewallForwarding) -> "FirewallConfig":
    """Add a forwarding rule and return self for chaining."""
    self.forwardings.append(forwarding)
    return self

get_commands()

Get all UCI commands for firewall configuration.

Source code in src/wrtkit/firewall.py
def get_commands(self) -> List[UCICommand]:
    """Get all UCI commands for firewall configuration."""
    commands = []
    for zone in self.zones:
        commands.extend(zone.get_commands())
    for forwarding in self.forwardings:
        commands.extend(forwarding.get_commands())
    return commands

FirewallZone

FirewallZone

Bases: UCISection

Represents a firewall zone configuration.

Source code in src/wrtkit/firewall.py
class FirewallZone(UCISection):
    """Represents a firewall zone configuration."""

    name: Optional[str] = None
    input: Optional[str] = None
    output: Optional[str] = None
    forward: Optional[str] = None
    masq: Optional[bool] = None
    mtu_fix: Optional[bool] = None
    network: List[str] = Field(default_factory=list)

    def __init__(self, zone_name: str, **data: Any) -> None:
        super().__init__(**data)
        self._package = "firewall"
        self._section = zone_name
        self._section_type = "zone"

    def get_commands(self) -> List[UCICommand]:
        """Generate UCI commands for this zone.

        Overrides base to emit 'network' as a space-joined UCI option
        (uci set firewall.wan.network='wan wan6') instead of add_list,
        matching OpenWrt's native firewall zone format.
        """
        commands = []
        commands.append(UCICommand("set", f"{self._package}.{self._section}", self._section_type))

        for field_name, field_value in self.model_dump(exclude_none=True).items():
            if field_name.startswith("_"):
                continue

            if field_name == "network" and isinstance(field_value, list):
                if field_value:
                    commands.append(
                        UCICommand(
                            "set",
                            f"{self._package}.{self._section}.{field_name}",
                            " ".join(self._get_option_value(v) for v in field_value),
                        )
                    )
            elif isinstance(field_value, list):
                for item in field_value:
                    commands.append(
                        UCICommand(
                            "add_list",
                            f"{self._package}.{self._section}.{field_name}",
                            self._get_option_value(item),
                        )
                    )
            else:
                commands.append(
                    UCICommand(
                        "set",
                        f"{self._package}.{self._section}.{field_name}",
                        self._get_option_value(field_value),
                    )
                )

        return commands

    # Immutable builder methods (composable)
    def with_name(self, value: str) -> "FirewallZone":
        """Set the zone name (returns new copy)."""
        return self.model_copy(update={"name": value})

    def with_input(self, value: str) -> "FirewallZone":
        """Set the input policy (ACCEPT, REJECT, DROP) (returns new copy)."""
        return self.model_copy(update={"input": value})

    def with_output(self, value: str) -> "FirewallZone":
        """Set the output policy (ACCEPT, REJECT, DROP) (returns new copy)."""
        return self.model_copy(update={"output": value})

    def with_forward(self, value: str) -> "FirewallZone":
        """Set the forward policy (ACCEPT, REJECT, DROP) (returns new copy)."""
        return self.model_copy(update={"forward": value})

    def with_masq(self, value: bool) -> "FirewallZone":
        """Enable or disable masquerading (returns new copy)."""
        return self.model_copy(update={"masq": value})

    def with_mtu_fix(self, value: bool) -> "FirewallZone":
        """Enable or disable MTU fix (returns new copy)."""
        return self.model_copy(update={"mtu_fix": value})

    def with_network(self, network_name: str) -> "FirewallZone":
        """Add a network to this zone (returns new copy)."""
        networks = self.network.copy()
        networks.append(network_name)
        return self.model_copy(update={"network": networks})

    def with_networks(self, networks: List[str]) -> "FirewallZone":
        """Set all networks for this zone (returns new copy)."""
        return self.model_copy(update={"network": networks.copy()})

    # Convenience builder methods for common configurations
    def with_default_policies(
        self,
        input_policy: str = "ACCEPT",
        output_policy: str = "ACCEPT",
        forward_policy: str = "ACCEPT",
    ) -> "FirewallZone":
        """Set default policies for the zone (returns new copy)."""
        return self.model_copy(
            update={"input": input_policy, "output": output_policy, "forward": forward_policy}
        )

with_name(value)

Set the zone name (returns new copy).

Source code in src/wrtkit/firewall.py
def with_name(self, value: str) -> "FirewallZone":
    """Set the zone name (returns new copy)."""
    return self.model_copy(update={"name": value})

with_input(value)

Set the input policy (ACCEPT, REJECT, DROP) (returns new copy).

Source code in src/wrtkit/firewall.py
def with_input(self, value: str) -> "FirewallZone":
    """Set the input policy (ACCEPT, REJECT, DROP) (returns new copy)."""
    return self.model_copy(update={"input": value})

with_output(value)

Set the output policy (ACCEPT, REJECT, DROP) (returns new copy).

Source code in src/wrtkit/firewall.py
def with_output(self, value: str) -> "FirewallZone":
    """Set the output policy (ACCEPT, REJECT, DROP) (returns new copy)."""
    return self.model_copy(update={"output": value})

with_forward(value)

Set the forward policy (ACCEPT, REJECT, DROP) (returns new copy).

Source code in src/wrtkit/firewall.py
def with_forward(self, value: str) -> "FirewallZone":
    """Set the forward policy (ACCEPT, REJECT, DROP) (returns new copy)."""
    return self.model_copy(update={"forward": value})

with_masq(value)

Enable or disable masquerading (returns new copy).

Source code in src/wrtkit/firewall.py
def with_masq(self, value: bool) -> "FirewallZone":
    """Enable or disable masquerading (returns new copy)."""
    return self.model_copy(update={"masq": value})

with_mtu_fix(value)

Enable or disable MTU fix (returns new copy).

Source code in src/wrtkit/firewall.py
def with_mtu_fix(self, value: bool) -> "FirewallZone":
    """Enable or disable MTU fix (returns new copy)."""
    return self.model_copy(update={"mtu_fix": value})

with_network(network_name)

Add a network to this zone (returns new copy).

Source code in src/wrtkit/firewall.py
def with_network(self, network_name: str) -> "FirewallZone":
    """Add a network to this zone (returns new copy)."""
    networks = self.network.copy()
    networks.append(network_name)
    return self.model_copy(update={"network": networks})

with_networks(networks)

Set all networks for this zone (returns new copy).

Source code in src/wrtkit/firewall.py
def with_networks(self, networks: List[str]) -> "FirewallZone":
    """Set all networks for this zone (returns new copy)."""
    return self.model_copy(update={"network": networks.copy()})

with_default_policies(input_policy='ACCEPT', output_policy='ACCEPT', forward_policy='ACCEPT')

Set default policies for the zone (returns new copy).

Source code in src/wrtkit/firewall.py
def with_default_policies(
    self,
    input_policy: str = "ACCEPT",
    output_policy: str = "ACCEPT",
    forward_policy: str = "ACCEPT",
) -> "FirewallZone":
    """Set default policies for the zone (returns new copy)."""
    return self.model_copy(
        update={"input": input_policy, "output": output_policy, "forward": forward_policy}
    )

FirewallForwarding

FirewallForwarding

Bases: UCISection

Represents a firewall forwarding rule.

Source code in src/wrtkit/firewall.py
class FirewallForwarding(UCISection):
    """Represents a firewall forwarding rule."""

    src: Optional[str] = None
    dest: Optional[str] = None

    def __init__(self, forwarding_name: str, **data: Any) -> None:
        super().__init__(**data)
        self._package = "firewall"
        self._section = forwarding_name
        self._section_type = "forwarding"

    # Immutable builder methods (composable)
    def with_src(self, value: str) -> "FirewallForwarding":
        """Set the source zone (returns new copy)."""
        return self.model_copy(update={"src": value})

    def with_dest(self, value: str) -> "FirewallForwarding":
        """Set the destination zone (returns new copy)."""
        return self.model_copy(update={"dest": value})

with_src(value)

Set the source zone (returns new copy).

Source code in src/wrtkit/firewall.py
def with_src(self, value: str) -> "FirewallForwarding":
    """Set the source zone (returns new copy)."""
    return self.model_copy(update={"src": value})

with_dest(value)

Set the destination zone (returns new copy).

Source code in src/wrtkit/firewall.py
def with_dest(self, value: str) -> "FirewallForwarding":
    """Set the destination zone (returns new copy)."""
    return self.model_copy(update={"dest": value})

Usage Example

from wrtkit import UCIConfig
from wrtkit.firewall import FirewallZone, FirewallForwarding

config = UCIConfig()

# Create a LAN zone
lan_zone = FirewallZone("lan")\
    .with_name("lan")\
    .with_input("ACCEPT")\
    .with_output("ACCEPT")\
    .with_forward("ACCEPT")\
    .with_network("lan")
config.firewall.add_zone(lan_zone)

# Create a WAN zone
wan_zone = FirewallZone("wan")\
    .with_name("wan")\
    .with_input("REJECT")\
    .with_masq(True)\
    .with_mtu_fix(True)\
    .with_network("wan")
config.firewall.add_zone(wan_zone)

# Create a forwarding rule
forwarding = FirewallForwarding("fwd_lan_wan")\
    .with_src("lan")\
    .with_dest("wan")
config.firewall.add_forwarding(forwarding)

See Also