summaryrefslogtreecommitdiff
path: root/fw/man
diff options
context:
space:
mode:
Diffstat (limited to 'fw/man')
-rw-r--r--fw/man/fw482
-rw-r--r--fw/man/fwrules224
2 files changed, 706 insertions, 0 deletions
diff --git a/fw/man/fw b/fw/man/fw
new file mode 100644
index 0000000..34a9d19
--- /dev/null
+++ b/fw/man/fw
@@ -0,0 +1,482 @@
+.TH FW 8
+.SH NAME
+fw \- firewall
+.SH SYNOPSIS
+.B fw
+.RB [ -dSW ]
+.RB [ -m
+.IR ctlmtpt ]
+.RB [ -n
+.IR net ]
+.RB [ -s
+.IR srv ]
+.br
+.RB [ -e
+.I ether
+.B -a
+.IR addr / mask
+.RB [ -g
+.IR gateway ]]
+.br
+.I rules
+.RI [ outside
+.IR inside ]
+.SH DESCRIPTION
+.I Fw
+is a network firewall.
+It can filter a network card, the traffic crossing between two networks,
+or the traffic of a single namespace.
+Rules are written in an
+.IR ndb (6)
+file; see
+.B RULES
+below.
+.PP
+The three ways of running it follow.
+The first two filter
+.IR packets ,
+as they cross a wire; the third filters
+.IR requests ,
+before any packet exists.
+.SS Filtering a network card
+.IP
+.EX
+fw -e /net/ether0 -a 10.0.2.15/24 -g 10.0.2.2 /lib/fw/host.ndb
+.EE
+.PP
+Everything sent or received through that card is filtered, whoever sent
+it.
+One card to one
+.IR fw ,
+so a machine with two cards to filter runs two of them.
+.PP
+The card cannot stay attached to the IP stack, or packets would reach it
+whatever the rules said.
+So
+.I fw
+takes the card and hands the stack a
+.I pkt
+interface instead - a card with
+.I fw
+on the other end of it:
+.IP
+.EX
+network ---- ether0 [ fw ] stack ---- your programs
+.EE
+.PP
+The stack keeps the address it had, given as
+.BI -a " addr/mask"\f1,
+and
+.B -g
+names the gateway.
+Nothing is left doing ARP for an address whose card has been taken away,
+so
+.I fw
+answers for it and resolves the next hop itself.
+.SS Gateway, between two networks
+.IP
+.EX
+fw /lib/fw/gate.ndb /net.wan!203.0.113.2!/24 /net.lan!10.0.0.1!/24
+.EE
+.PP
+.I Fw
+sits between two networks and decides, packet by packet, what may cross:
+.IP
+.EX
+internet ---- ether0 [ fw ] ether1 ---- your machines
+ outside inside
+.EE
+.PP
+The side facing the untrusted network is the
+.IR outside ,
+the side facing the machines you are protecting is the
+.IR inside .
+Rules are written in those terms, so which side is which matters.
+.PP
+Every packet between the two networks goes through
+.IR fw ,
+so one the rules forbid is thrown away before the far side ever sees it.
+Nothing is opened, nothing replies, and the sender is told nothing.
+A side is written
+.IB net ! addr ! mask\f1,
+naming the mountpoint of an IP stack and the address to give the
+interface
+.I fw
+creates on it.
+.SS Filtering one namespace
+.IP
+.EX
+fw.rc /lib/fw/web.ndb mothra
+.EE
+.PP
+Given neither of those,
+.I fw
+serves a synthetic
+.B /net
+in place of
+.IR ip (3),
+and every program in that namespace reaches the network through it.
+A write of
+.B connect
+or
+.B announce
+to a protocol ctl file is matched against the rules before it reaches
+the kernel.
+A refused write fails, and the diagnostic is what
+.IR dial (2)
+reports to the program that tried it.
+.PP
+Because the policy lives in a namespace, each program can have its own.
+Filtering a program's requests is not a boundary by itself - see
+.B CONTAINMENT
+below - so to sandbox one, run
+.B /lib/fw/fw.rc
+rather than
+.I fw
+directly: it builds the namespace, mounts the filter, drops the devices
+that would go around it, and only then runs the program.
+.PP
+The difference is one of altitude.
+Packet filtering sees everything, including traffic no local program
+asked for, but cannot tell one program from another.
+Request filtering knows exactly who asked, but only ever sees intentions,
+so it cannot stop an inbound connection before the handshake and cannot
+see traffic that is merely passing through.
+.PP
+The options are:
+.TP
+.B -W
+require wire (packet) filtering; exit rather than fall back to filtering
+requests.
+.TP
+.B -S
+do not track connections.
+Every packet is then matched against the rules, and a rule permitting
+traffic one way does not permit the replies.
+.TP
+.B -d
+report every packet and every decision on standard error.
+.TP
+.BI -m " ctlmtpt"
+mount the control files here, default
+.BR /mnt/fw .
+Packet filtering only.
+.TP
+.BI -e " ether"
+take this card and filter the packets of this machine, eg
+.BR /net/ether0 .
+.TP
+.BI -a " addr/mask"
+the address the stack should keep once its card has been taken.
+Without it
+.I fw
+reads the address and mask off the card it is taking, which is almost
+always what you want; give it only to use something other than the
+address the card already has.
+.TP
+.BI -g " gateway"
+the next hop for anything off this network.
+Without it
+.I fw
+takes the default route the stack was already using; if there was none,
+only the local network is reachable.
+.TP
+.BI -n " net"
+filter this stack rather than
+.BR /net .
+.TP
+.BI -s " srv"
+post the served filesystem on
+.BI /srv/ srv
+as well as mounting it.
+Which filesystem that is depends on the mode, and so does the risk.
+Filtering packets it is the control files, and anyone who can open them
+can rewrite the rules; filtering requests it is the synthetic
+.BR /net ,
+and anyone who can mount it has the network the rules were meant to
+ration.
+Either way, do not post it anywhere the traffic being filtered can reach
+.BR /srv .
+.SH RULES
+Rules live in an
+.IR ndb (6)
+file, matched from the top, first match deciding, and traffic matching
+nothing denied.
+Connections are tracked, so permitting traffic one way permits the
+replies.
+The file format, the attributes, and worked rule sets are in
+.IR fwrules (6).
+.SH CONTROL
+When filtering packets,
+.I fw
+serves four files, by default under
+.BR /mnt/fw .
+There are none when filtering requests: that policy is chosen when the
+namespace is built and lasts as long as it does, so to change it, build
+the namespace again.
+.TP
+.B ctl
+Read it for the commands it takes.
+Writing a rule installs it at once.
+A rule that will not parse fails the write and leaves the running rules
+alone.
+.TP
+.B rules
+The current rules, as ndb, one rule per line and numbered from one in
+the order shown - so rule
+.I n
+in a diagnostic is line
+.I n
+here, which is what
+.B delete
+counts.
+What it prints can be written back unchanged.
+.IP
+Writing it replaces the whole set.
+Writes accumulate and are applied when the file is closed, so a set
+arriving in several messages is still installed in one step and no packet
+is matched against half of it.
+A clunk cannot report an error, so a set that will not parse is noted in
+.B /sys/log/fw
+and the running rules are kept;
+.B ctl
+is the way in if you want to be told.
+.TP
+.B flows
+The connections being tracked.
+.TP
+.B stats
+Packets passed and dropped, then each rule with the number of decisions
+it has made.
+A rule at zero is either dead or waiting for something that has not
+happened, and it is worth knowing which.
+.PP
+The commands accepted by
+.B ctl
+are
+.BR prepend ,
+.BR append ,
+.B delete
+.IR n ,
+.BR flush ,
+.B reload
+.RI [ file ],
+.B save
+.RI [ file ],
+and
+.BR flushflows .
+.B Reload
+and
+.B save
+with no argument use the file
+.I fw
+was started with.
+.PP
+There are three things called the rules: the file, what is running, and
+what has been typed at
+.BR ctl .
+.B Reload
+makes the running rules match the file, discarding anything typed;
+.B save
+makes the file match the running rules, keeping it.
+Neither happens on its own.
+.SH CONTAINMENT
+Filtering
+.B /net
+achieves nothing on its own, because
+.IP
+.EX
+bind -a '#I' /net
+.EE
+.PP
+puts the real stack back.
+A filtered program must also be denied the devices that reach a network
+directly, through
+.B /dev/drivers
+(see
+.IR cons (3)):
+.IP
+.EX
+echo chdev '&~' 'Iluσ' >/dev/drivers
+.EE
+.PP
+That mask can only ever have bits added, and every new process group
+inherits it, so nothing below can undo it.
+Note that the
+.B &
+form permits
+.I only
+the devices named, so using it to try to regain one silently drops
+everything else instead.
+.PP
+.B /lib/fw/fw.rc
+does this in the right order: private namespace, mount, drop, exec.
+.SH BOOT
+.B /lib/fw/fwstart
+starts a firewall for each card named in
+.BR /lib/ndb/fw ,
+which is an
+.IR ndb (6)
+file of one entry per card:
+.IP
+.EX
+fw=ether0 rules=/lib/fw/wan.ndb
+fw=ether1 rules=/lib/fw/lan.ndb
+.EE
+.PP
+No address appears there.
+.I Fw
+reads each card's address, mask and gateway from the card it is taking
+over, so this file cannot drift out of step with
+.IR ipconfig (8).
+Control files land under
+.BI /mnt/fw/ ether0
+and so on, one directory per card.
+.PP
+Run it after the network is configured and before anything dials.
+Too early and there is no address to read; too late and something has
+already connected unfiltered.
+A card named here that does not exist, or a rule file that is missing,
+is reported and skipped rather than stopping the rest.
+.SH EXAMPLES
+Filter this machine's card, keeping the address it already has:
+.IP
+.EX
+fw -e /net/ether0 -a 10.0.2.15/24 -g 10.0.2.2 /lib/fw/host.ndb
+.EE
+.PP
+Filter two cards, one
+.I fw
+each:
+.IP
+.EX
+fw -m /mnt/fw/ether0 -e /net/ether0 -a 198.51.100.7/24 -g 198.51.100.1 \
+ /lib/fw/wan.ndb
+fw -m /mnt/fw/ether1 -e /net/ether1 -a 10.0.0.1/24 /lib/fw/lan.ndb
+.EE
+.PP
+Sit between two networks:
+.IP
+.EX
+fw /lib/fw/gate.ndb /net.wan!203.0.113.2!/24 /net.lan!10.0.0.1!/24
+.EE
+.PP
+Sandbox one program, which may resolve names and speak https:
+.IP
+.EX
+fw.rc /lib/fw/web.ndb mothra
+.EE
+.PP
+Give a program no network whatever.
+An empty rule file permits nothing:
+.IP
+.EX
+fw.rc /lib/fw/none.ndb troff -ms doc
+.EE
+.PP
+Block a port on a running firewall, at once, including anything already
+connected:
+.IP
+.EX
+echo prepend deny=in proto=tcp lport=80 >/mnt/fw/ctl
+.EE
+.PP
+Edit the rule file and apply it, or keep what was typed at
+.BR ctl :
+.IP
+.EX
+echo reload >/mnt/fw/ctl
+echo save >/mnt/fw/ctl
+.EE
+.PP
+See what a rule has actually done:
+.IP
+.EX
+cat /mnt/fw/stats
+.EE
+.SH FILES
+.TP
+.B /lib/fw
+rule sets
+.TP
+.B /lib/fw/fwstart
+starts one firewall per card at boot
+.TP
+.B /lib/ndb/fw
+which cards are filtered, and with what
+.TP
+.B /mnt/fw
+control files
+.TP
+.B /sys/log/fw
+where rules marked
+.B log=yes
+are recorded
+.SH SOURCE
+.B /sys/src/cmd/fw
+.SH "SEE ALSO"
+.IR ip (3),
+.IR cons (3),
+.IR fwrules (6),
+.IR ndb (6),
+.IR dial (2),
+.IR syslog (2),
+.IR fork (2),
+.IR ipconfig (8)
+.SH BUGS
+There is no address translation.
+A machine behind a
+.I fw
+gateway needs a routable address, or must import
+.B /net
+rather than route through it.
+.PP
+Packet filtering drops silently, so a refused connection is discovered
+by timing out.
+Request filtering fails
+.IR dial (2)
+immediately with a reason, which is much easier to diagnose.
+.PP
+IPv6 extension headers are not walked; such packets are matched on their
+addresses and next-header protocol alone.
+ICMP has no type or code matching.
+.PP
+Taking a card is destructive and is not undone reliably.
+The interface that replaces it is unbound when
+.I fw
+stops, and the address goes with it, so a
+.I fw
+that is killed leaves the card bound to nothing and the machine with no
+network.
+It cannot be restarted unaided either: the address it would have read
+off the card is the address that has just been lost, so it must be told
+one with
+.BR -a ,
+or the card configured again with
+.IR ipconfig (8)
+first.
+.I Fw
+tries to put the card back as it exits, which covers an orderly stop but
+not a kill.
+Whatever restarts
+.I fw
+should be prepared to configure the card first.
+.PP
+The first packet to an unresolved next hop is dropped while
+.I fw
+asks for its ethernet address, exactly as any other stack would, so a
+run of
+.I fw
+begins with one drop that no rule caused.
+.PP
+.I Fw
+does not implement
+.BR Tflush ,
+so a request it is blocked on cannot be abandoned.
+While filtering requests this affects waiting for an inbound connection,
+which is the one operation that blocks indefinitely: giving up on it does
+not reach
+.IR fw ,
+which stays waiting until a connection arrives.
+
+
diff --git a/fw/man/fwrules b/fw/man/fwrules
new file mode 100644
index 0000000..143ac08
--- /dev/null
+++ b/fw/man/fwrules
@@ -0,0 +1,224 @@
+.TH FWRULES 6
+.SH NAME
+fwrules \- firewall rule files
+.SH DESCRIPTION
+.IR Fw (8)
+decides what may cross a network by matching traffic against a file of
+rules.
+The file is an
+.IR ndb (6)
+file: one entry is one rule.
+.PP
+A rule set for a machine that may look up names and fetch pages, and do
+nothing else:
+.IP
+.EX
+allow=out proto=udp port=53
+allow=out proto=tcp port=53
+allow=out proto=tcp port=80
+allow=out proto=tcp port=443
+
+deny=* log=yes
+.EE
+.PP
+Rules are matched from the top, the first one that matches decides, and
+traffic matching none of them is denied.
+A file with no rules therefore permits nothing, and the last rule above
+changes nothing about what is allowed - it exists so that the refusals
+are written down instead of happening silently.
+.PP
+There is no rule permitting the replies to any of this, and none is
+needed: see
+.B STATE
+below.
+.SH ACTION
+Every rule begins with an action, whose value is the direction it
+governs:
+.TP
+.BI allow= dir
+permit.
+.TP
+.BI deny= dir
+refuse.
+.PP
+.I Dir
+is
+.BR out ,
+.BR in ,
+or
+.B *
+for either.
+.B Out
+is traffic begun from the side being protected;
+.B in
+is traffic begun toward it.
+That holds wherever the rule is enforced: on a gateway the protected
+side is the inside, and in a namespace it is the program, whose
+.B connect
+is
+.B out
+and whose
+.B announce
+is
+.BR in .
+.B Connect
+and
+.B announce
+are accepted as older spellings of
+.B out
+and
+.BR in .
+.SH ATTRIBUTES
+The rest of a rule says what it matches.
+An attribute that is absent does not constrain, so there is never a
+.B *
+to write:
+.TP
+.BI proto= name
+a protocol:
+.BR tcp ,
+.BR udp ,
+.BR icmp ,
+and so on.
+.TP
+.BI port= n
+the port at the far end.
+.TP
+.BI lport= n
+the port at this end.
+A program announcing a port is naming this end, so
+.B announce 17019
+is matched by
+.BR lport=17019 ,
+and by
+.B port=
+never - at that moment nobody has called, so there is no far end.
+.TP
+.BI ip= address
+the address at the far end, optionally carrying a
+.BI / mask
+suffix.
+IPv4 and IPv6 are written the usual way and need no distinguishing.
+.TP
+.BI ipmask= mask
+the mask, written separately, as
+.B /24
+or in full.
+.TP
+.B log=yes
+note every match of this rule in
+.BR /sys/log/fw .
+.PP
+An unrecognised attribute is an error, and
+.I fw
+refuses to start rather than run with it ignored: a mistyped constraint
+would otherwise silently widen the rule it was meant to narrow.
+.PP
+An entry may be spread over indented continuation lines, as any
+.IR ndb (6)
+entry may:
+.IP
+.EX
+allow=out
+ proto=tcp
+ port=443
+.EE
+.SH ORDER
+The first match decides, so a rule carving an exception out of a
+broader rule must come above it.
+This is right:
+.IP
+.EX
+deny=out ip=1.1.1.1
+allow=out proto=tcp port=443
+.EE
+.PP
+and this is not, because 1.1.1.1:443 matches the allow first and the
+deny is never reached:
+.IP
+.EX
+allow=out proto=tcp port=443
+deny=out ip=1.1.1.1
+.EE
+.PP
+Rules are numbered from one in the order they appear, and that is the
+number a refusal names in
+.BR /sys/log/fw .
+.SH STATE
+Connections are tracked, so a rule permitting traffic one way permits
+the replies without a second rule.
+A permitted packet records the protocol and both addresses and ports;
+anything matching that, either way round, passes without consulting the
+rules again.
+.PP
+UDP has no connections, so a flow is that same tuple and lasts 60
+seconds after the last packet.
+TCP lasts 300 seconds, everything else 30.
+ICMP has no ports, so its flows are the two addresses alone, which is
+enough for a reply to an echo to be recognised, but does not tie an
+ICMP error to the connection it is about.
+.PP
+When the rules change, connections the new rules forbid are dropped
+rather than left to finish: a block blocks.
+.SH EXAMPLES
+A gateway.
+The machines behind it may reach the web, one host is refused outright,
+and the only thing the internet may reach is a web server:
+.IP
+.EX
+# the exception first, or the allows below would match
+# 1.1.1.1:443 before this was ever reached
+deny=out ip=1.1.1.1
+
+# out: what the machines behind me may reach
+allow=out proto=udp port=53
+allow=out proto=tcp port=53
+allow=out proto=tcp port=80
+allow=out proto=tcp port=443
+
+# in: what the internet may reach here
+allow=in proto=tcp lport=443
+
+# and note anything else that tries, either way
+deny=* log=yes
+.EE
+.PP
+On a gateway facing the internet that last rule will log a great deal,
+since the internet knocks on every door constantly.
+Narrow it to
+.B deny=out
+if only the traffic from your own machines is worth recording.
+.PP
+A program that may resolve names and fetch pages over TLS, and nothing
+else:
+.IP
+.EX
+allow=out proto=udp port=53
+allow=out proto=tcp port=443
+.EE
+.PP
+A service that answers on one port and never calls out:
+.IP
+.EX
+allow=in proto=tcp lport=17019
+.EE
+.PP
+No network at all.
+An empty file permits nothing, so this is a complete rule set:
+.IP
+.EX
+# nothing
+.EE
+.SH FILES
+.TP
+.B /lib/fw
+rule sets
+.TP
+.B /lib/fw/example.ndb
+every attribute, with comments
+.SH "SEE ALSO"
+.IR fw (8),
+.IR ndb (6)
+.SH BUGS
+A rule cannot name which network card it applies to, so a machine
+filtering two cards needs a file for each.