Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
770ca37
package/finit: bump to v4.13
troglobit Jul 14, 2025
a9cbdb3
cli: add terminal reset|resize commands
troglobit Jul 15, 2025
45ddae5
board/common: fixes for unicode translation in log/pager commands
troglobit Aug 5, 2025
c903722
confd: initial firewall support
troglobit Aug 4, 2025
198428b
WIP: firewall infer and well-known-services.yang
troglobit Aug 8, 2025
095e028
confd: drop advanced firewall features for first drop
troglobit Aug 13, 2025
9035341
libsrx: new helper, srx_set_bool()
troglobit Aug 14, 2025
4647188
confd: minor, replace hard-coded string with define
troglobit Aug 14, 2025
5e71367
confd: further simplify firewall
troglobit Aug 14, 2025
ee4573c
confd: add pre-defined services for dhcpv6 and ipp
troglobit Aug 14, 2025
40de66b
confd: default firewall settings in factory-config
troglobit Aug 14, 2025
df32685
utils: silence srload (debug messages)
troglobit Aug 14, 2025
6be8861
TODO: firewall
troglobit Aug 14, 2025
da5d306
confd: new helper function, get all l3 interfaces
troglobit Aug 14, 2025
809d60e
confd: find all interfaces not in a zone and assign to default
troglobit Aug 14, 2025
551f506
statd: initial operational support for firewall
troglobit Aug 15, 2025
d188a95
fixup swap proto/port
troglobit Aug 15, 2025
d85186d
confd: clean up unused pre-defined services
troglobit Aug 15, 2025
da02a85
confd: change to singular form and add must expression
troglobit Aug 16, 2025
24550ce
klish-plugin-infix: minor, xml optimization
troglobit Aug 17, 2025
c5295be
cli: add support for 'show firewall [..]' admin-exec commands
troglobit Aug 17, 2025
383b58b
confd: simplify
troglobit Aug 17, 2025
709eef9
board/common: stop-start firewalld for now, --reload takes too long
troglobit Aug 17, 2025
a95287e
cli: firewall: fix lag in tab completion and colorize zone matrix
troglobit Aug 17, 2025
aedd387
confd: replace 'firewall-cmd --reload' with a little script
troglobit Aug 17, 2025
254dd84
confd: simplify firewalld zone generation
troglobit Aug 17, 2025
a394311
confd: rename zone/policy 'policy' -> 'action', like Ubiquity
troglobit Aug 17, 2025
b202455
confd: rename sources -> networks, for IP networks
troglobit Aug 17, 2025
6a0582f
confd: refactor port-forwarding to allow forwarding a range of ports
troglobit Aug 18, 2025
e24ade5
statd: initial support for /var/log/firewall.log
troglobit Aug 18, 2025
b1b9508
statd: update firewall matrix, if forwarding disabled => deny
troglobit Aug 18, 2025
30274cc
statd: show implicit HOST zone in firewall matrix
troglobit Aug 18, 2025
72581aa
confd: initial support for emergency lockdown (kill switch)
troglobit Aug 18, 2025
a6db4f1
confd: add immutable flag (read-only) for built-in policies
troglobit Aug 19, 2025
f2ee467
confd: add services (xml+enums) for netconf and restconf
troglobit Aug 21, 2025
0b9d7e1
confd: clean up firewalld config files when disabling firewall
troglobit Aug 22, 2025
9afc793
Update firewall TODOs
troglobit Aug 21, 2025
4544fc1
test/infamy: add IPv6 versions of must_reach/must_not_reach
troglobit Aug 21, 2025
8633b83
test: add nmap to Infamy container
troglobit Aug 22, 2025
330f76e
test: new test, basic firewall zone verification
troglobit Aug 21, 2025
8eb3f1b
test: new test, lan-wan gateway with snat
troglobit Aug 22, 2025
04904c0
test: new test, wan-dmz-lan firewall with snat and dnat
troglobit Aug 23, 2025
ee15b8b
Update fw TODOs
troglobit Aug 23, 2025
bf7285e
doc: draft firewall documentation
troglobit Aug 23, 2025
1d1a35d
confd: minor, reorder leafs a bit and udpate descriptions
troglobit Aug 24, 2025
c7ad821
confd: initial support for firewalld rich rules
troglobit Aug 24, 2025
1ecab43
Revert "confd: default firewall settings in factory-config"
troglobit Aug 24, 2025
3fef431
confd: allow services to set destination addr/len
troglobit Aug 24, 2025
2856c58
confd: fix firewall zone and policy inference
troglobit Aug 24, 2025
fa8232d
confd: restore 'enabled' setting to firewall
troglobit Aug 24, 2025
f857632
doc: mention firewall symbolic names for zones and custom filters
troglobit Aug 24, 2025
8295055
confd: sort policy rules according to 'ordered-by user;'
troglobit Aug 24, 2025
96b8450
doc: update fw TODOs, what's left?
troglobit Aug 24, 2025
631b205
test: fix TypeError: non-ordered lists cannot be accessed by index
troglobit Aug 24, 2025
422e812
test: simplify and skip UNIX backup files
troglobit Aug 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions board/common/rootfs/etc/bash.bashrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ log()
{
local fn="/var/log/syslog"
[ -n "$1" ] && fn="/var/log/$1"
less +G "$fn"
less +G -r "$fn"
}

follow()
{
local fn="/var/log/syslog"
[ -n "$1" ] && fn="/var/log/$1"
tail -F "$fn"
less +F -r "$fn"
}

_logfile_completions()
Expand Down
3 changes: 3 additions & 0 deletions board/common/rootfs/etc/finit.d/available/firewalld.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
service [2345] <!pid/syslogd> reload:'firewall reload' \
firewalld --nofork --log-target syslog \
-- Firewall daemon
6 changes: 6 additions & 0 deletions board/common/rootfs/etc/syslog.d/firewall.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Log firewall denied/rejected packet logs to dedicated file
# https://www.cyberciti.biz/faq/enable-firewalld-logging-for-denied-packets-on-linux/
:msg, contains, "_DROP"
kern.* -/var/log/firewall.log
:msg, contains, "_REJECT"
kern.* -/var/log/firewall.log
3 changes: 2 additions & 1 deletion board/common/rootfs/usr/bin/pager
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
# -K :: exit immediately when an interrupt character (usually ^C) is typed
# -R :: Almost raw control charachters, only ANSI color escape sequences and
# OSC 8 hyperlink sequences are output. Allows veritcal scrolling
# -r :: Causes "raw" control characters to be displayed, including unicode.
# -X :: No termcap initialization and deinitialization set to the terminal.
# This is what leaves the contents of the output on screen.

export LESS="-P %f (press h for help or q to quit)"
export LANG=en_US.UTF-8

less -RIKd -FX "$@"
less -rIKd -FX "$@"
11 changes: 9 additions & 2 deletions board/common/rootfs/usr/bin/yorn
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
#!/bin/sh
opts="-n1"

if [ "$1" = "-q" ]; then
opts="$opts -s"
shift
fi

Q=$@

/bin/echo -n "$Q, are you sure (y/N)? "
read -n1 yorn
read $opts yorn
echo

if [ x$yorn != "xy" ] && [ x$yorn != "xY" ]; then
if [ "x$yorn" != "xy" ] && [ "x$yorn" != "xY" ]; then
echo "OK, aborting."
exit 1
fi
Expand Down
1 change: 1 addition & 0 deletions configs/aarch64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ BR2_PACKAGE_CONNTRACK_TOOLS=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_FPING=y
BR2_PACKAGE_FIREWALLD=y
BR2_PACKAGE_FRR=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
Expand Down
1 change: 1 addition & 0 deletions configs/aarch64_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ BR2_PACKAGE_AVAHI_DEFAULT_SERVICES=y
BR2_PACKAGE_CHRONY=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_FIREWALLD=y
BR2_PACKAGE_FRR=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
Expand Down
1 change: 1 addition & 0 deletions configs/r2s_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ BR2_PACKAGE_CONNTRACK_TOOLS=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_FPING=y
BR2_PACKAGE_FIREWALLD=y
BR2_PACKAGE_FRR=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
Expand Down
1 change: 1 addition & 0 deletions configs/riscv64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ BR2_PACKAGE_CONNTRACK_TOOLS=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_FPING=y
BR2_PACKAGE_FIREWALLD=y
BR2_PACKAGE_FRR=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
Expand Down
1 change: 1 addition & 0 deletions configs/x86_64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ BR2_PACKAGE_CONNTRACK_TOOLS=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_FPING=y
BR2_PACKAGE_FIREWALLD=y
BR2_PACKAGE_FRR=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
Expand Down
1 change: 1 addition & 0 deletions configs/x86_64_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ BR2_PACKAGE_AVAHI_DEFAULT_SERVICES=y
BR2_PACKAGE_CHRONY=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_FIREWALLD=y
BR2_PACKAGE_FRR=y
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_PACKAGE_IPROUTE2=y
Expand Down
31 changes: 31 additions & 0 deletions doc/TODO.org
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
* TODO Add support for firewall
- [X] Interfaces are not defaulting to the default zone, must handle bridge
ports and changes to enslavement, so regenerate every time is a must!
- [X] Add missing upper to port forward since port ranges are supported, see services!
- [X] =[do] show firewall= not available yet
- [X] Add RPC to pause firewall using =firewall-cmd --panic-on= and restart
firewall again with =firewall-cmd --panic-off=. The current state can
be queried using =firewall-cmd --query-panic=, which returns =yes=
- [X] Remove debug log messages!
- [X] Add "Log Messages" section to =show firewall= when =LogDenied ≠ off=
- [ ] Investigate filtering out firewall log messages from other log files
- [1/2] Rename policy->policy to policy->action, and replace allow->forward
- [X] Rename zone->sources to networks
- [X] A zone's action is for ingress, clarify this if missing!
- [X] Any services/ports listed in a zone with policy:accept are a NO-OP
- [X] =firwall-cmd --reload= takes fooooorever! :-(
- [X] If forwarding is disabled in a zone then the zone matrix should
show deny for the same zone-to-zone communication
- [X] We should show the implicit rules for communicating with the HOST
- [X] Investigate "padlock" on built-in policys (and zones?) and expose more?
- [X] Document established,related somewhere, fixed/padlocked policy? Also,
document why this is a good idea to always have enabled. See RH docs.
- [ ] Podman published ports, <https://firewalld.org/2024/11/strict-forward-ports>
- [ ] Software fastpath <https://firewalld.org/2023/05/nftables-flowtable>
- +[ ] Allow overriding/editing immutable policies and zones+
- [X] Add tests: basic (end device), wan-lan, wan-lan-dmz, +hammer (stress)+
- [X] Add documentation
- See <https://docs.rockylinux.org/guides/security/firewalld-beginners/>
- Add some tool tips: nc, nmap, ping, and socat to stress the firewall
- [X] Fix inference so we can remove defaults from factory-config!

* TODO doc: User Guide

- Feature set and scope, e.g.
Expand Down
238 changes: 238 additions & 0 deletions doc/firewall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
# Firewall Documentation

## Introduction

The Infix firewall aims to simplify network security. Instead of complex
per-interface rules, you work with *zones*. A zone defines a level of trust
between all interfaces assigned to it and security policies regulate traffic
flow between zones.

![Firewall](img/firewall.svg){ align=left width="180" }

This approach is intuitive and maintainable — you think in terms of trust
relationships ("internal networks can access the Internet", "Internet cannot
access my internal network") rather than individual interface rules. When you
add new interfaces to existing zones, they automatically inherit the
established security policies.

The firewall controls three distinct traffic flows: traffic destined for the
host itself, traffic between interfaces within the same zone, and traffic
between different zones.

> [!TIP] Impatient and ready to get going?
> [Fast forward to the Examples: End Device, Home/Office Router, Enterprise Gateway](#examples)

## Zones

Zones are logical groupings of network interfaces that share the same trust
level. Each zone has a default *action* that determines what happens to
traffic destined for the host itself (INPUT chain). A LAN zone may have this
set to *accept*, while a DMZ zone may be set to *reject* by default and only
allow a subset of *services*, e.g., DHCP, DNS, and SSH, on input.

### Intra-Zone Traffic

For a LAN zone, the trust level can be set to allow IP routing between all
interfaces and networks. This is often referred to as *intra-zone* traffic
and is controlled by the zone's `forwarding` setting, it works independently
of the zone action. When enabled, devices on different interfaces within the
same zone can communicate directly with each other.

> [!NOTE] Remember IP forwarding!
> Allowing forwarding between interfaces in the zone is not enough, this only
> prevents the firewall from actively blocking the traffic flows, you also
> need to enable [IP forwarding](network.md#ipv4-forwarding).

### Port Forwarding

Each zone can have port forwarding rules (DNAT) that redirect incoming traffic
from one port to a different internal address and port. This is effectively a
security policy that allows external access to internal services.

The *Firewall Matrix* shows a ⚠ conditional warning flag, coloring the zone
yellow, when policy exceptions like port forwarding are active.

![Firewall Matrix](img/fw-matrix.png)

### Default Zone Concept

Infix requires you to specify a default zone. Any interface not explicitly
assigned to a zone automatically belongs to the default zone. This ensures
that no interface is left without firewall protection.

Choose your default zone carefully — it should be the most restrictive zone
appropriate for unmanaged interfaces. For routers, this is typically the
`wan` zone.

## Policies

![Zone based firewall](img/fw-zones.svg){ align=right width="420" }

Policy rules control traffic **between** zones. By default all inter-zone
traffic is rejected. Meaning you must explicitly allow the traffic flows
you intend.

IP masquerading (SNAT) is a policy setting that applies to traffic egressing
a target zone. (Essential for Internet access from private networks.)

A policy, like zones, have a default action. If it is *not* set to `accept`
you must specify which services are allowed.

See the [examples below](#enterprise-gateway) for how to set up a policy. The
built-in help system can also be useful:

```
admin@example:/config/firewall/policy/lan-to-dmz/> help masquerade
NAME
masquerade <true/false>

DESCRIPTION
Enable masquerading (SNAT) for traffic matching this policy.

admin@example:/config/firewall/policy/lan-to-dmz/>
```

### Symbolic Names

The symbolic names `HOST` and `ANY` are available for use in both `ingress`
and `egress` zones. In fact, the CLI uses inference when first enabling the
firewall to inject a default policy to allow an IPv6 autoconf address.

### Custom Filters

For more advanced firewall scenarios *custom filters* can be used. The only
support currently are various ICMP type traffic control. Enough to support
the default `allow-host-ipv6` policy.

## Services

Several pre-defined services exist, that cover most use-cases, but you can
also define custom services for applications not covered by the built-in ones.

### Built-in services

Infix provides predefined services for common protocols:

- **`ssh`**: Secure Shell (port 22/tcp)
- **`http`**: Web traffic (port 80/tcp)
- **`https`**: Secure web traffic (port 443/tcp)
- **`dns`**: Domain Name System (port 53/tcp and 53/udp)
- **`dhcp`**: DHCP server (port 67/udp)
- **`dhcpv6-client`**: DHCPv6 client traffic
- **`netconf`**: Network Configuration Protocol (port 830/tcp)
- **`restconf`**: REST-based Network Configuration Protocol (port 443/tcp)

... and more, see `infix-firewall-services.yang` for details

## Examples

### End Device Protection

For devices on untrusted networks like public Wi-Fi or other open Internet
connections. Provides maximum protection while allowing essential
connectivity.

```
admin@example:/> configure
admin@example:/config/> edit firewall
admin@example:/config/firewall/> set default public
admin@example:/config/firewall/> edit zone public
admin@example:/config/firewall/zone/public/> set description "Public untrusted network - end device protection"
admin@example:/config/firewall/zone/public/> set action drop
admin@example:/config/firewall/zone/public/> set interface eth0
admin@example:/config/firewall/zone/public/> set service ssh
admin@example:/config/firewall/zone/public/> set service dhcpv6-client
admin@example:/config/firewall/zone/public/> leave
```

### Home/Office Router

For typical routers that need to protect internal devices while providing
internet access. The LAN zone trusts internal devices, while the WAN zone
blocks external threats.

```
admin@example:/> configure
admin@example:/config/> edit firewall
admin@example:/config/firewall/> set default wan
admin@example:/config/firewall/> edit zone lan
admin@example:/config/firewall/zone/lan/> set description "Internal LAN network - trusted"
admin@example:/config/firewall/zone/lan/> set action accept
admin@example:/config/firewall/zone/lan/> set interface eth1
admin@example:/config/firewall/zone/lan/> set service ssh
admin@example:/config/firewall/zone/lan/> set service dhcp
admin@example:/config/firewall/zone/lan/> set service dns
admin@example:/config/firewall/zone/lan/> end
admin@example:/config/firewall/> edit zone wan
admin@example:/config/firewall/zone/wan/> set description "External WAN interface - untrusted"
admin@example:/config/firewall/zone/wan/> set action drop
admin@example:/config/firewall/zone/wan/> set interface eth0
admin@example:/config/firewall/zone/wan/> end
admin@example:/config/firewall/> edit policy loc-to-wan
admin@example:/config/firewall/policy/loc-to-wan/> set description "Allow local LAN/DMZ traffic to WAN with SNAT"
admin@example:/config/firewall/policy/loc-to-wan/> set ingress lan
admin@example:/config/firewall/policy/loc-to-wan/> set egress wan
admin@example:/config/firewall/policy/loc-to-wan/> set action accept
admin@example:/config/firewall/policy/loc-to-wan/> set masquerade
admin@example:/config/firewall/policy/loc-to-wan/> leave
```

> [!NOTE]
> Policy rules apply in a stateful, unidirectional manner. Meaning, you only
> consider one direction of the traffic. The return traffic (established,
> related) is implicitly allowed.

### Enterprise Gateway

For businesses that need to host public services while protecting internal
resources. We can build upon the Home/Office Router example above and add
a DMZ zone with additional policies for controlled access.

```
admin@example:/> configure
admin@example:/config/> edit firewall zone dmz
admin@example:/config/firewall/zone/dmz/> set description "Semi-trusted public services"
admin@example:/config/firewall/zone/dmz/> set action drop
admin@example:/config/firewall/zone/dmz/> set interface eth1
admin@example:/config/firewall/zone/dmz/> set service ssh
admin@example:/config/firewall/zone/dmz/> end
admin@example:/config/firewall/> edit policy lan-to-wan
admin@example:/config/firewall/policy/lan-to-wan/> set ingress dmz
admin@example:/config/firewall/policy/lan-to-wan/> end
admin@example:/config/firewall/> edit policy lan-to-dmz
admin@example:/config/firewall/policy/lan-to-dmz/> set description "Allow LAN to manage DMZ services"
admin@example:/config/firewall/policy/lan-to-dmz/> set ingress lan
admin@example:/config/firewall/policy/lan-to-dmz/> set egress dmz
admin@example:/config/firewall/policy/lan-to-dmz/> set action accept
admin@example:/config/firewall/policy/lan-to-dmz/> end
admin@example:/config/firewall/> edit zone wan port-forward 8080 tcp
admin@example:/config/firewall/zone/wan/port-forward/8080/tcp/> set to addr 192.168.2.10
admin@example:/config/firewall/zone/wan/port-forward/8080/tcp/> set to port 80
admin@example:/config/firewall/zone/wan/port-forward/8080/tcp/> leave
```

This adds a DMZ zone for public services, updates the internet access policy
to include DMZ traffic, allows LAN management of DMZ services, and forwards
external web traffic to the DMZ server.

## Logging and Monitoring

Different log levels are available to monitor and debug firewall behavior.
Configure logging using the CLI:

```
admin@example:/> configure
admin@example:/config/> edit firewall
admin@example:/config/firewall/> set logging all
admin@example:/config/firewall/> leave
```

Firewall logs help you understand traffic patterns and security events. The
CLI admin-exec command `show firewall` shows the last 10 log messages in the
overview:

![Firewall logs](img/fw-logs.png)

Use the command `show log firewall.log` to display the full logfile (remember,
the syslog daemon rotates and zips too big log files). You can also use the
`follow firewall.log` command to continuously monitor firewall log messages.
1 change: 1 addition & 0 deletions doc/img/firewall.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/img/fw-logs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/img/fw-matrix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions doc/img/fw-zones.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading