diff options
Diffstat (limited to 'fw/man')
| -rw-r--r-- | fw/man/fw | 482 | ||||
| -rw-r--r-- | fw/man/fwrules | 224 |
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. |
