Files
deploy_home/ansible/roles/labelprint/templates/nftables.conf.j2
T
Bastian de BylandClaude Opus 5 6cd4d56de1 feat(labelprint): 4x6 label print proxy on a Raspberry Pi
A Pi 3B+ (stickah.local) shares a Phomemo PM246 to the LAN as a plain CUPS
queue, so any machine can print 4x6 labels -- fulfillr-site's shipping labels
in particular -- without installing the vendor driver, which is x86-64 only.
The role builds the TSPL CUPS driver from source instead.

It is Debian, not Fedora, so it lives in its own inventory and playbook
(make deploy-labelprint / check-labelprint) and the home.debyl.io roles can
never run against it. make bootfs renders its cloud-init first-boot files onto
a freshly imaged SD card from the same templates the role uses. The Wi-Fi
credentials for the home and rescue networks are in the vault.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 23:14:45 -04:00

64 lines
2.5 KiB
Django/Jinja

#!/usr/sbin/nft -f
# {{ ansible_managed }}
#
# The print proxy answers to the LAN and to its own rescue access point, and to
# nothing else. This is the outer half of the same rule that cupsd enforces in
# its Location blocks -- both are here on purpose, so a mistake in one is not
# the only thing standing between the printer and the rest of the world.
# Declare-then-delete rather than `flush ruleset`: NetworkManager's shared mode
# keeps its own table for the rescue AP's dnsmasq, and a global flush would take
# that with it every time this file is reloaded.
table inet labelprint
delete table inet labelprint
table inet labelprint {
set trusted {
type ipv4_addr
flags interval
elements = { {{ labelprint_lan_cidr }}, {{ labelprint_ap_cidr }} }
}
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
icmp type { echo-request, destination-unreachable, time-exceeded, parameter-problem } accept
icmpv6 type { echo-request, destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert } accept
# DHCP replies to our own client. Broadcast, so conntrack does not see
# them as related to the request we sent.
udp dport 68 accept
# ssh and IPP, from the LAN or from a machine on the rescue AP.
ip saddr @trusted tcp dport { 22, 631 } accept
ip saddr @trusted udp dport 631 accept
# mDNS: how every client finds this printer, since it has no DNS record.
ip saddr @trusted udp dport 5353 accept
# DHCP for whoever joins the rescue AP. Deliberately not restricted by
# source address: a client asking for its first lease has no address
# yet and sends DHCPDISCOVER from 0.0.0.0, so a source-matched rule
# would mean the rescue network never hands out a lease at all. Only a
# machine already associated to our own AP can reach this port.
iifname "wlan0" udp dport 67 accept
# DNS, once they have an address.
iifname "wlan0" ip saddr {{ labelprint_ap_cidr }} udp dport 53 accept
iifname "wlan0" ip saddr {{ labelprint_ap_cidr }} tcp dport 53 accept
}
# The rescue AP is a way in to this Pi, not a route to anywhere else.
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}