UFW-FRAMEWORK(8)

๐ŸŽ€ UFW FRAMEWORK(8) ๐ŸŽ€

Nov 2024 ๐Ÿ’… manual page for ufw-framework โœจ

โœจ NAME โœจ

ufw-framework - using the ufw framework ๐Ÿฆ‹

๐Ÿ’– DESCRIPTION ๐Ÿ’–

okay so ufw comes with a command line interface AND a whole framework behind it ๐Ÿ”ฅ the ufw command is the easy-to-use bit for managing a firewall, but the ufw framework is where the admin gets to customize default behavior and add rules the command line tool can't do on its own. that's how ufw gets to flex all of Linux netfilter's power and flexibility ๐Ÿ‘‘

๐ŸŒธ OVERVIEW ๐ŸŒธ

the framework handles boot time initialization, rules files for custom rules, loading netfilter modules, kernel parameter config, and IPv6 config ๐Ÿงš it's made up of these files:

  • /lib/ufw/ufw-init โ€” initialization script
  • /etc/ufw/before.init โ€” initialization customization script run before ufw is initialized
  • /etc/ufw/after.init โ€” initialization customization script run after ufw is initialized
  • /etc/ufw/before[6].rules โ€” rules file containing rules evaluated before UI added rules
  • /etc/ufw/user[6].rules โ€” rules file containing UI added rules (managed with the ufw command)
  • /etc/ufw/after[6].rules โ€” rules file containing rules evaluated after UI added rules
  • /etc/default/ufw โ€” high level configuration
  • /etc/ufw/sysctl.conf โ€” kernel network tunables
  • /etc/ufw/ufw.conf โ€” additional high level configuration

๐Ÿš€ BOOT INITIALIZATION ๐Ÿš€

ufw gets started on boot with /lib/ufw/ufw-init โœจ this script is a standard SysV style initscript used by the ufw command, so do not modify it ๐Ÿ™ˆ if you need extra firewall config that ufw doesn't support yet, the /etc/before.init and /etc/after.init scripts are your friends ๐Ÿซถ if they exist and are executable, ufw-init runs them for you. and heads up: ufw-init will exit with error if either of those scripts exits with error.

ufw-init supports these arguments:

  • start โ€” loads the firewall
  • stop โ€” unloads the firewall
  • restart โ€” reloads the firewall
  • force-reload โ€” same as restart
  • status โ€” basic status of the firewall
  • force-stop โ€” same as stop, except it does not check if the firewall is already loaded ๐Ÿ’€
  • flush-all โ€” flushes the built-in chains, deletes all non-built-in chains and resets the policy to ACCEPT ๐Ÿ˜ญ

ufw-init will call before.init and after.init with start, stop, status and flush-all, but honestly, if you're using them, these scripts typically only need to implement start and stop ๐Ÿ’…

ufw uses a bunch of user-defined chains on top of the built-in iptables chains ๐ŸŒˆ here's the tea: if MANAGE_BUILTINS in /etc/default/ufw is set to 'yes', then on stop and reload the built-in chains get flushed. if it's set to 'no', then on stop and reload the ufw secondary chains are removed and the ufw primary chains are flushed. on top of flushing the ufw specific chains, it also keeps the primary chains in the same order relative to any other user-defined chains that may have been added ๐Ÿฆ‹ this is what lets ufw play nicely with other software that manages its own firewall rules ๐Ÿค

to make sure your firewall loads on boot, you must hook this script into the boot process ๐Ÿ”ฅ if ufw isn't already integrated, check your distribution's documentation for the proper way to modify your boot process ๐Ÿ“–

๐ŸŽ€ RULES FILES ๐ŸŽ€

ufw is partly a front-end for iptables-restore โœจ its rules get saved in /etc/ufw/before.rules, /etc/ufw/after.rules and /etc/ufw/user.rules. admins can customize before.rules and after.rules however they like, using the standard iptables-restore syntax ๐Ÿ’– rules are evaluated like this: before.rules first, then user.rules, and after.rules last. IPv6 rules get evaluated the same way, just with the files named before6.rules, user6.rules and after6.rules ๐Ÿงš also, lowkey important: ufw status only shows rules added with ufw, NOT the rules found in the /etc/ufw rules files ๐Ÿ‘€

Important: ufw only uses the *filter table by default. You may add any other tables such as *nat, *raw and *mangle as desired. For each table a corresponding COMMIT statement is required. ๐Ÿšจ

after you modify any of these files, you must reload ufw for the rules to take effect ๐Ÿ”„ check out the EXAMPLES section for common uses of these rules files ๐Ÿ’œ

๐Ÿงฉ MODULES ๐Ÿงฉ

netfilter has a ton of different connection tracking modules โœจ these modules understand the underlying protocol, which lets the admin simplify their rule sets, which is giving efficiency ๐Ÿ™Œ you can adjust which netfilter modules get loaded by changing IPT_MODULES in /etc/default/ufw. some popular modules to load are:

  • nf_conntrack_ftp
  • nf_nat_ftp
  • nf_conntrack_irc
  • nf_nat_irc
  • nf_conntrack_netbios_ns
  • nf_conntrack_pptp
  • nf_conntrack_tftp
  • nf_nat_tftp
  • nf_conntrack_sane
Unconditionally loading connection tracking modules (nf_conntrack_*) like this is deprecated ๐Ÿฅ€ ufw still supports it, but new config should only contain the specific modules the site actually requires. for more info, see CONNECTION HELPERS ๐Ÿ™ˆ

๐ŸŒˆ KERNEL PARAMETERS ๐ŸŒˆ

ufw will read in /etc/ufw/sysctl.conf on boot when enabled ๐Ÿ“ please note that /etc/ufw/sysctl.conf overrides values in the system systcl.conf (usually /etc/sysctl.conf) ๐Ÿ‘€ admins can change which file gets used by modifying /etc/default/ufw ๐Ÿ”ง

๐ŸŒ IPV6 ๐ŸŒ

IPv6 is enabled by default ๐Ÿ’œ when it's disabled, all incoming, outgoing and forwarded packets get dropped, with the one exception being traffic on the loopback interface ๐Ÿซข to adjust this behavior, set IPV6 to 'yes' in /etc/default/ufw. see the ufw manual page for details ๐Ÿ“–

๐Ÿ’… EXAMPLES ๐Ÿ’…

okay so as mentioned, ufw loads its rules files into the kernel using the iptables-restore and ip6tables-restore commands ๐Ÿง  if you want to add rules to the ufw rules files by hand, you need to be familiar with these, plus the iptables and ip6tables commands ๐Ÿค“ below are some common examples of using the ufw rules files. all examples assume IPv4 only, and that DEFAULT_FORWARD_POLICY in /etc/default/ufw is set to DROP โœจ

๐ŸŽญ IP Masquerading ๐ŸŽญ

to allow IP masquerading so computers from the 10.0.0.0/8 network on eth1 can share the single IP address on eth0:

Edit /etc/ufw/sysctl.conf to have:

net.ipv4.ip_forward=1

Add to the end of /etc/ufw/before.rules, after the *filter section:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.0.0.0/8 -o eth0 -j MASQUERADE
COMMIT
If your firewall is using IPv6 tunnels or 6to4 AND is also doing NAT, then you should not usually masquerade protocol '41' (ipv6) packets ๐Ÿ™…โ€โ™€๏ธ for example, instead of the above, /etc/ufw/before.rules can be adjusted to have:
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.0.0.0/8 ! --protocol 41 -o eth0 -j
              MASQUERADE
COMMIT

Add the ufw route to allow the traffic:

ufw route allow in on eth1 out on eth0 from 10.0.0.0/8

๐Ÿ”€ Port Redirections ๐Ÿ”€

to forward tcp port 80 on eth0 so it goes to the webserver at 10.0.0.2:

Edit /etc/ufw/sysctl.conf to have:

net.ipv4.ip_forward=1

Add to the end of /etc/ufw/before.rules, after the *filter section:

*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -i eth0 --dport 80 -j DNAT \
  --to-destination 10.0.0.2:80
COMMIT

Add the ufw route rule to allow the traffic:

ufw route allow in on eth0 to 10.0.0.2 port 80 proto tcp

โœจ CONNECTION HELPERS โœจ

okay so connection helpers are literally the best ๐Ÿงš Lots of protocols need netfilter connection tracking helpers to group related packets into RELATED flows, which keeps your rulesets clean and precise ๐Ÿ’… For example, with a couple of kernel modules and a couple of rules, you can just allow a connection to FTP port 21, and then the kernel looks at the traffic and marks the other FTP data packets as RELATED to that first connection. no cap, it's giving efficiency ๐Ÿฆ‹

When helpers first showed up, you could only configure them at module load time. So if your FTP server was listening on some other port instead of 21, you had to load the nf_conntrack_ftp module and specify the right port yourself ๐Ÿ™ˆ Eventually everyone realized that using connection helpers unconditionally could lead to abuse ๐Ÿ’€ Some protocols let users specify data that could be used to get through the firewall in ways nobody wanted. As of kernel 4.7, automatic conntrack helper assignment (aka handling packets for a given port on all IP addresses) is disabled ๐Ÿšซ If you really need the old behavior, you can bring it back by setting net/netfilter/nf_conntrack_helper=1 in /etc/ufw/sysctl.conf, but the safer move is to have your firewall use the CT target to link traffic to a specific helper, then set RELATED rules that use that helper. That way you can tailor how helpers are used for your site and avoid the abuse ๐Ÿซถ

To use helpers securely, here's the game plan ๐Ÿ“

  1. net/netfilter/nf_conntrack_helper should be set to 0 (default) ๐ŸŒฑ
  2. create a rule for the start of a connection (eg for FTP, port 21) ๐Ÿšช
  3. create a helper rule to associate the helper with this connection ๐Ÿ”—
  4. create a helper rule to associate a RELATED flow with this connection ๐Ÿ’œ
  5. if needed, add the corresponding nf_conntrack_* module to IPT_MODULES ๐Ÿงฉ
  6. optionally add the corresponding nf_nat_* module to IPT_MODULES โœจ

Honestly, you want your connection helper rules to be as specific as possible, and you need anti-spoofing set up correctly for your site so your ruleset doesn't end up with security holes ๐Ÿ˜ญ For more info, check out ANTI-SPOOFING, above, and https://home.regit.org/netfilter-en/secure-use-of-helpers/ ๐ŸŒธ

Right now, helper rules have to be managed through the RULES FILES. A future version of ufw is going to add syntax for working with helper rules, so stay tuned ๐Ÿ‘‘


๐ŸŒธ NOTES ๐ŸŒธ

okay bestie, listen up because this one is a little chaotic ๐Ÿ™ˆ When you use ufw with libvirt and bridging, packets can get blocked ๐Ÿ˜ค The libvirt team recommends setting these sysctls to turn off netfilter on the bridge:

net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
Heads up: the bridge module has to be loaded into the kernel before you set these values. One way to make sure this works with ufw is to add bridge to IPT_MODULES in /etc/default/ufw, then add the rules above to /etc/ufw/sysctl.conf ๐Ÿ’…

If you'd rather not turn off netfilter on the bridge, you can instead configure iptables to allow all traffic to be forwarded across the bridge ๐ŸŒ‰ For example, add this to /etc/ufw/before.rules inside the *filter section:

-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT

When you use ufw with LXD or Incus, the guests need some extra rules for the bridge (by default, lxdbr0) so they can do DHCP, DNS, and outbound connections ๐Ÿ“ For example:

ufw allow in on lxdbr0 to any port 67 proto udp
ufw allow in on lxdbr0 to any port 53
ufw route allow in on lxdbr0 from XXX.YYY.ZZZ.0/24

The first two rules only let guests reach the host for DHCP and DNS, and the third rule lets guests on the XXX.YYY.ZZZ.0/24 subnet (as configured by LXD or Incus) reach the world ๐ŸŒ Adjust as needed for your setup, like your site requirements, the bridge name, or the bridge network.

If you want traffic from the outside to reach your guests, you'll need additional rules ๐Ÿ“ฌ For example, to allow HTTPS to the 10.210.254.123 guest:

ufw route allow out on lxdbr0 to 10.210.254.123 port 443 proto tcp
Note: to keep in on lxdbr0 and out on lxdbr0 straight, think about the traffic from the host and guest point of view ๐Ÿง  If the traffic is coming from the guest into or through the host, use in on lxdbr0. If the traffic is coming from anywhere out to the guest, use out on lxdbr0. And as always, you may need more rules depending on your default policy ๐Ÿ’œ

๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹

ufw(8), iptables(8), ip6tables(8), iptables-restore(8), ip6tables-restore(8), sysctl(8), sysctl.conf(5)


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

ufw is Copyright 2008-2024, Canonical Ltd. ๐Ÿ’–


And that's a wrap, bestie ๐ŸŽ€ This was ufw from the UFW FRAMEWORK(8) page, dated Nov 2024 โœจ Go forth and secure your rulesets, you absolute legend ๐Ÿซถ๐ŸŒˆ

๐Ÿ“ฆ where this page comes from