Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ TMPDIR = ./tmp
IPTABLES_DIR ?= $(shell for dir in /usr/sbin /sbin /usr/bin /bin /usr/local/sbin /usr/local/bin; do \
if [ -x $$dir/iptables ]; then echo $$dir; break; fi; done)

# Find nftables location
NFTABLES_DIR ?= $(shell for dir in /usr/sbin /sbin /usr/bin /bin /usr/local/sbin /usr/local/bin; do \
if [ -x $$dir/nft ]; then echo $$dir; break; fi; done)

# Get version from setup.cfg
VERSION := $(shell grep '^version = ' setup.cfg | cut -d' ' -f3)

Expand Down Expand Up @@ -75,6 +79,7 @@ build:
sed -i 's|#STATE_PREFIX#|$(LIBDIR)/ufw|g' $(STAGE_DIR)/src/common.py
sed -i 's|#PREFIX#|$(PREFIX)|g' $(STAGE_DIR)/src/common.py
sed -i 's|#IPTABLES_DIR#|$(IPTABLES_DIR)|g' $(STAGE_DIR)/src/common.py
sed -i 's|#NFTABLES_DIR#|$(NFTABLES_DIR)|g' $(STAGE_DIR)/src/common.py
sed -i 's|#SHARE_DIR#|$(DATADIR)/ufw|g' $(STAGE_DIR)/src/common.py
@if [ -n "$$UFW_SKIP_CHECKS" ]; then \
echo "Updating do_checks"; \
Expand Down Expand Up @@ -155,6 +160,9 @@ install: build
install -m 640 $(STAGE_DIR)/conf/after6.rules $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/conf/user.rules $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/conf/user6.rules $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/conf/before.nft $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/conf/after.nft $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/conf/user.nft $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/src/before.init $(DESTDIR)$(SYSCONFDIR)/ufw/
install -m 640 $(STAGE_DIR)/src/after.init $(DESTDIR)$(SYSCONFDIR)/ufw/

Expand All @@ -171,6 +179,11 @@ install: build
install -m 644 $(STAGE_DIR)/conf/user.rules $(DESTDIR)$(DATADIR)/ufw/iptables/
install -m 644 $(STAGE_DIR)/conf/user6.rules $(DESTDIR)$(DATADIR)/ufw/iptables/

install -d $(DESTDIR)$(DATADIR)/ufw/nftables
install -m 644 $(STAGE_DIR)/conf/before.nft $(DESTDIR)$(DATADIR)/ufw/nftables/
install -m 644 $(STAGE_DIR)/conf/after.nft $(DESTDIR)$(DATADIR)/ufw/nftables/
install -m 644 $(STAGE_DIR)/conf/user.nft $(DESTDIR)$(DATADIR)/ufw/nftables/

# Install translations if they exist
@if [ -d "$(STAGE_DIR)/locales/mo" ] && [ -n "$$(ls -A $(STAGE_DIR)/locales/mo 2>/dev/null)" ]; then \
echo "Installing translations..."; \
Expand Down
50 changes: 50 additions & 0 deletions conf/after.nft
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# after.nft
#
# Rules that should be run after the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-after-input
# ufw-after-output
# ufw-after-forward
#
# This file uses nftables syntax. The inet family handles both IPv4 and IPv6.
#

# Don't delete these required lines, otherwise there will be errors
table inet ufw {
chain ufw-after-input {
}
chain ufw-after-output {
}
chain ufw-after-forward {
}
}
# End required lines

table inet ufw {
chain ufw-after-input {
# don't log noisy services by default
# (return early so the default policy logging doesn't fire for these)
udp dport 137 return
udp dport 138 return
tcp dport 139 return
tcp dport 445 return

# DHCPv4 client/server noise
udp dport 67 return
udp dport 68 return

# DHCPv6 client/server noise
udp dport 546 return
udp dport 547 return

# don't log noisy broadcast / multicast
fib daddr type { broadcast, multicast } return
}

chain ufw-after-output {
}

chain ufw-after-forward {
}
}
103 changes: 103 additions & 0 deletions conf/before.nft
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#
# before.nft
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#
# This file uses nftables syntax. The inet family handles both IPv4 and IPv6.
#

# Don't delete these required lines, otherwise there will be errors
table inet ufw {
chain ufw-before-input {
}
chain ufw-before-output {
}
chain ufw-before-forward {
}
}
# End required lines

table inet ufw {
chain ufw-before-input {
# allow all on loopback
iifname "lo" accept

# quickly process packets for which we already have a connection
ct state related,established accept

# drop INVALID packets
# (logging of these is managed by ufw's log level, not here)
ct state invalid drop

# ok icmp codes for INPUT (IPv4)
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept

# ok icmpv6 codes for INPUT (RFC 4890, 4.4.1 and 4.4.2)
# multicast ping replies have no associated connection so allow before
# the INVALID check above
ip6 nexthdr icmpv6 icmpv6 type echo-reply accept
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
# NDP messages must arrive with hop-limit 255
ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
# IND solicitation / advertisement
ip6 nexthdr icmpv6 icmpv6 type 141 ip6 hoplimit 255 accept
ip6 nexthdr icmpv6 icmpv6 type 142 ip6 hoplimit 255 accept
# MLD (source must be link-local or unspecified)
ip6 nexthdr icmpv6 ip6 saddr fe80::/10 icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, 143 } accept
# SEND certificate path solicitation / advertisement
ip6 nexthdr icmpv6 icmpv6 type { 148, 149 } ip6 hoplimit 255 accept
# MR advertisement / solicitation / termination (link-local, hl=1)
ip6 nexthdr icmpv6 ip6 saddr fe80::/10 ip6 hoplimit 1 icmpv6 type { 151, 152, 153 } accept
# Home Agent Address Discovery, Mobile Prefix
ip6 nexthdr icmpv6 icmpv6 type { 144, 145, 146, 147 } accept
# drop packets with RH0 headers (IPv6)
ip6 nexthdr ipv6-route drop

# allow DHCPv4 client
udp sport 67 udp dport 68 accept
# allow DHCPv6 client (link-local only)
ip6 saddr fe80::/10 ip6 daddr fe80::/10 udp sport 547 udp dport 546 accept

# allow MULTICAST mDNS for service discovery
udp daddr 224.0.0.251 udp dport 5353 accept
ip6 daddr ff02::fb udp dport 5353 accept

# allow MULTICAST UPnP for service discovery
udp daddr 239.255.255.250 udp dport 1900 accept
ip6 daddr ff02::f udp dport 1900 accept

# drop non-local unicast packets
fib daddr type != { local, multicast, broadcast } drop
}

chain ufw-before-output {
# allow all on loopback
oifname "lo" accept

# quickly process packets for which we already have a connection
ct state related,established accept

# ok icmpv6 codes for OUTPUT (RFC 4890, 4.4.1 and 4.4.2)
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } accept
ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
ip6 nexthdr icmpv6 icmpv6 type { 141, 142 } ip6 hoplimit 255 accept
ip6 nexthdr icmpv6 ip6 saddr fe80::/10 icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, 143 } accept
ip6 nexthdr icmpv6 icmpv6 type { 148, 149 } ip6 hoplimit 255 accept
ip6 nexthdr icmpv6 ip6 saddr fe80::/10 ip6 hoplimit 1 icmpv6 type { 151, 152, 153 } accept
}

chain ufw-before-forward {
# quickly process packets for which we already have a connection
ct state related,established accept

# ok icmp codes for FORWARD
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept

# ok icmpv6 codes for FORWARD (RFC 4890, 4.3.1 and 4.3.2)
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } accept
}
}
4 changes: 4 additions & 0 deletions conf/ufw.defaults
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# /etc/default/ufw
#

# Set the firewall backend. Supported values are 'iptables' and 'nftables'.
# Changing this requires a 'ufw disable && ufw enable' to take effect.
FIREWALL_BACKEND="iptables"

# Set to yes to apply rules to support IPv6 (no means only IPv6 on loopback
# accepted). You will need to 'disable' and then 'enable' the firewall for
# the changes to take affect.
Expand Down
9 changes: 9 additions & 0 deletions conf/user.nft
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ufw-nftables user rules
# This file is managed by ufw. Do not edit directly.
# Rules are defined using ### tuple ### comments which ufw parses to
# reconstruct the logical rule set. The nftables statements below each
# tuple are regenerated from those tuples on every ufw invocation.

### RULES ###

### END RULES ###
18 changes: 0 additions & 18 deletions src/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,6 @@ def __init__(

self.profiles = ufw.applications.get_profiles(self.files["apps"])

self.iptables = os.path.join(ufw.common.iptables_dir, "iptables")
self.iptables_restore = os.path.join(
ufw.common.iptables_dir, "iptables-restore"
)
self.ip6tables = os.path.join(ufw.common.iptables_dir, "ip6tables")
self.ip6tables_restore = os.path.join(
ufw.common.iptables_dir, "ip6tables-restore"
)

try:
self.iptables_version = ufw.util.get_iptables_version(self.iptables)
except OSError: # pragma: no coverage
err_msg = tr("Couldn't determine iptables version")
raise UFWError(err_msg)

# Initialize via initcaps only when we need it (LP: #1044361)
self.caps = None

def initcaps(self) -> None:
"""Initialize the capabilities database. This needs to be called
before accessing the database."""
Expand Down
18 changes: 18 additions & 0 deletions src/backend_iptables.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ def __init__(
self, "iptables", dryrun, files, rootdir=rootdir, datadir=datadir
)

self.iptables = os.path.join(ufw.common.iptables_dir, "iptables")
self.iptables_restore = os.path.join(
ufw.common.iptables_dir, "iptables-restore"
)
self.ip6tables = os.path.join(ufw.common.iptables_dir, "ip6tables")
self.ip6tables_restore = os.path.join(
ufw.common.iptables_dir, "ip6tables-restore"
)

try:
self.iptables_version = ufw.util.get_iptables_version(self.iptables)
except OSError: # pragma: no coverage
err_msg = _("Couldn't determine iptables version")
raise UFWError(err_msg)

# Initialize via initcaps only when we need it (LP: #1044361)
self.caps = None

self.chains = {"before": [], "user": [], "after": [], "misc": []}
for ver in ["4", "6"]:
chain_prefix = "ufw"
Expand Down
Loading
Loading