Diff

mod_firewall/README.markdown @ 1803:4d73a1a6ba68

Convert all wiki pages to Markdown
author Kim Alvefur <zash@zash.se>
date Fri, 28 Aug 2015 18:03:58 +0200
parent 1782:29f3d6b7ad16
child 2002:ce991c678370
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_firewall/README.markdown	Fri Aug 28 18:03:58 2015 +0200
@@ -0,0 +1,300 @@
+---
+labels:
+- 'Stage-Alpha'
+summary: 'A rule-based stanza filtering module'
+...
+
+------------------------------------------------------------------------
+
+**Note:** mod\_firewall is in its very early stages. This documentation
+is liable to change, and some described functionality may be missing,
+incomplete or contain bugs. Feedback is welcome in the comments section
+at the bottom of this page.
+
+------------------------------------------------------------------------
+
+Introduction
+============
+
+A firewall is an invaluable tool in the sysadmin's toolbox. However
+while low-level firewalls such as iptables and pf are incredibly good at
+what they do, they are generally not able to handle application-layer
+rules.
+
+The goal of mod\_firewall is to provide similar services at the XMPP
+layer. Based on rule scripts it can efficiently block, bounce, drop,
+forward, copy, redirect stanzas and more! Furthermore all rules can be
+applied and updated dynamically at runtime without restarting the
+server.
+
+Details
+=======
+
+mod\_firewall loads one or more scripts, and compiles these to Lua code
+that reacts to stanzas flowing through Prosody. The firewall script
+syntax is unusual, but straightforward.
+
+A firewall script is dominated by rules. Each rule has two parts:
+conditions, and actions. When a stanza matches all of the conditions,
+all of the actions are executed in order.
+
+Here is a simple example to block stanzas from spammer@example.com:
+
+    FROM: spammer@example.com
+    DROP.
+
+FROM is a condition, and DROP is an action. This is about as simple as
+it gets. How about heading to the other extreme? Let's demonstrate
+something more complex that mod\_firewall can do for you:
+
+    %ZONE myorganisation: staff.myorg.example, support.myorg.example
+
+    ENTERING: myorganisation
+    KIND: message
+    TIME: 12am-9am, 5pm-12am, Saturday, Sunday
+    REPLY=Sorry, I am afraid our office is closed at the moment. If you need assistance, please call our 24-hour support line on 123-456-789.
+
+This rule will reply with a short message whenever someone tries to send
+a message to someone at any of the hosts defined in the 'myorganisation'
+outside of office hours.
+
+Firewall rules should be written to a `ruleset.pfw` file. Multiple such
+rule files can be specified in the configuration using:
+
+    firewall_scripts = { "path/to/ruleset.pfw" }
+
+Conditions
+----------
+
+All conditions must come before any action in a rule block. The
+condition name is followed by a colon (':'), and the value to test for.
+
+A condition can be preceded or followed by `NOT` to negate its match.
+For example:
+
+    NOT FROM: user@example.com
+    KIND NOT: message
+
+### Zones
+
+A 'zone' is one or more hosts or JIDs. It is possible to match when a
+stanza is entering or leaving a zone, while at the same time not
+matching traffic passing between JIDs in the same zone.
+
+Zones are defined at the top of a script with the following syntax (they
+are not part of a rule block):
+
+    %ZONE myzone: host1, host2, user@host3, foo.bar.example
+
+A host listed in a zone also matches all users on that host (but not
+subdomains).
+
+The following zone-matching conditions are supported:
+
+  Condition    Matches
+  ------------ ------------------------------------------
+  `ENTERING`   When a stanza is entering the named zone
+  `LEAVING`    When a stanza is leaving the named zone
+
+### Stanza matching
+
+  Condition   Matches
+  ----------- ------------------------------------------------------------------------------------------------------------------------------------------------------------
+  `KIND`      The kind of stanza. May be 'message', 'presence' or 'iq'
+  `TYPE`      The type of stanza. This varies depending on the kind of stanza. See 'Stanza types' below for more information.
+  `PAYLOAD`   The stanza contains a child with the given namespace. Useful for determining the type of an iq request, or whether a message contains a certain extension.
+  `INSPECT`   The node at the specified path exists or matches a given string. This allows you to look anywhere inside a stanza. See below for examples and more.
+
+#### Stanza types
+
+  Stanza     Valid types
+  ---------- ------------------------------------------------------------------------------------------
+  iq         get, set, result, error
+  presence   *available*, unavailable, probe, subscribe, subscribed, unsubscribe, unsubscribed, error
+  message    normal, chat, groupchat, headline, error
+
+**Note:** The type 'available' for presence does not actually appear in
+the protocol. Available presence is signalled by the omission of a type.
+Similarly, a message stanza with no type is equivalent to one of type
+'normal'. mod\_firewall handles these cases for you automatically.
+
+#### INSPECT
+
+INSPECT takes a 'path' through the stanza to get a string (an attribute
+value or text content). An example is the best way to explain. Let's
+check that a user is not trying to register an account with the username
+'admin'. This stanza comes from [XEP-0077: In-band
+Registration](http://xmpp.org/extensions/xep-0077.html#example-4):
+
+    <iq type='set' id='reg2'>
+      <query xmlns='jabber:iq:register'>
+        <username>bill</username>
+        <password>Calliope</password>
+        <email>bard@shakespeare.lit</email>
+      </query>
+    </iq>
+
+    KIND: iq
+    TYPE: set
+    PAYLOAD: jabber:iq:register
+    INSPECT: {jabber:iq:register}query/username#=admin
+    BOUNCE=not-allowed The username 'admin' is reserved.
+
+That weird string deserves some explanation. It is a path, divided into
+segments by '/'. Each segment describes an element by its name,
+optionally prefixed by its namespace in curly braces ('{...}'). If the
+path ends with a '\#' then the text content of the last element will be
+returned. If the path ends with '@name' then the value of the attribute
+'name' will be returned.
+
+INSPECT is somewhat slower than the other stanza matching conditions. To
+minimise performance impact, always place it below other faster
+condition checks where possible (e.g. above we first checked KIND, TYPE
+and PAYLOAD matched before INSPECT).
+
+### Sender/recipient matching
+
+  Condition   Matches
+  ----------- -------------------------------------------------------
+  `FROM`      The JID in the 'from' attribute matches the given JID
+  `TO`        The JID in the 'to' attribute matches the given JID
+
+These conditions both accept wildcards in the JID when the wildcard
+expression is enclosed in angle brackets ('\<...\>'). For example:
+
+    # All users at example.com
+    FROM: <*>@example.com
+
+    # The user 'admin' on any subdomain of example.com
+    FROM: admin@<*.example.com>
+
+You can also use [Lua's pattern
+matching](http://www.lua.org/manual/5.1/manual.html#5.4.1) for more
+powerful matching abilities. Patterns are a lightweight
+regular-expression alternative. Simply contain the pattern in double
+angle brackets. The pattern is automatically anchored at the start and
+end (so it must match the entire portion of the JID).
+
+    # Match admin@example.com, and admin1@example.com, etc.
+    FROM: <<admin%d*>>@example.com
+
+**Note:** It is important to know that 'example.com' is a valid JID on
+its own, and does **not** match 'user@example.com'. To perform domain
+whitelists or blacklists, use Zones.
+
+**Note:** Some chains execute before Prosody has performed any
+normalisation or validity checks on the to/from JIDs on an incoming
+stanza. It is not advisable to perform access control or similar rules
+on JIDs in these chains (see the chain documentation for more info).
+
+### Time and date
+
+#### TIME
+
+Matches stanzas sent during certain time periods.
+
+  Condition   Matches
+  ----------- -------------------------------------------------------------------------------------------
+  TIME        When the current server local time is within one of the comma-separated time ranges given
+
+    TIME: 10pm-6am, 14:00-15:00
+    REPLY=Zzzz.
+
+#### DAY
+
+It is also possible to match only on certain days of the week.
+
+  Condition   Matches
+  ----------- -----------------------------------------------------------------------------------------------------
+  DAY         When the current day matches one, or falls within a rage, in the given comma-separated list of days
+
+Example:
+
+    DAY: Sat-Sun, Wednesday
+    REPLY=Sorry, I'm out enjoying life!
+
+### Rate-limiting
+
+It is possible to selectively rate-limit stanzas, and use rules to
+decide what to do with stanzas when over the limit.
+
+First, you must define any rate limits that you are going to use in your
+script. Here we create a limiter called 'normal' that will allow 2
+stanzas per second, and then we define a rule to bounce messages when
+over this limit. Note that the `RATE` definition is not part of a rule
+(multiple rules can share the same limiter).
+
+    %RATE normal: 2 (burst 3)
+
+    KIND: message
+    LIMIT: normal
+    BOUNCE=policy-violation (Sending too fast!)
+
+The 'burst' parameter on the rate limit allows you to spread the limit
+check over a given time period. For example the definition shown above
+will allow the limit to be temporarily surpassed, as long as it is
+within the limit after 3 seconds. You will almost always want to specify
+a burst factor.
+
+Both the rate and the burst can be fractional values. For example a rate
+of 0.1 means only one event is allowed every 10 seconds.
+
+The LIMIT condition actually does two things; first it counts against
+the given limiter, and then it checks to see if the limiter over its
+limit yet. If it is, the condition matches, otherwise it will not.
+
+  Condition   Matches
+  ----------- --------------------------------------------------------------------------------------------------
+  `LIMIT`     When the named limit is 'used up'. Using this condition automatically counts against that limit.
+
+**Note:** Reloading mod\_firewall resets the current state of any
+limiters.
+
+Actions
+-------
+
+Actions come after all conditions in a rule block. There must be at
+least one action, though conditions are optional.
+
+An action without parameters ends with a full-stop/period ('.'), and one
+with parameters uses an equals sign ('='):
+
+    # An action with no parameters:
+    DROP.
+
+    # An action with a parameter:
+    REPLY=Hello, this is a reply.
+
+### Route modification
+
+The most common actions modify the stanza's route in some way. Currently
+the first matching rule to do so will halt further processing of actions
+and rules (this may change in the future).
+
+  Action                  Description
+  ----------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------
+  `PASS.`                 Stop executing actions and rules on this stanza, and let it through this chain.
+  `DROP.`                 Stop executing actions and rules on this stanza, and discard it.
+  `REDIRECT=jid`          Redirect the stanza to the given JID.
+  `REPLY=text`            Reply to the stanza (assumed to be a message) with the given text.
+  `BOUNCE.`               Bounce the stanza with the default error (usually service-unavailable)
+  `BOUNCE=error`          Bounce the stanza with the given error (MUST be a defined XMPP stanza error, see [RFC6120](http://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions).
+  `BOUNCE=error (text)`   As above, but include the supplied human-readable text with a description of the error
+  `COPY=jid`              Make a copy of the stanza and send the copy to the specified JID.
+
+### Stanza modification
+
+These actions make it possible to modify the content and structure of a
+stanza.
+
+  Action                   Description
+  ------------------------ ------------------------------------------------------------------------
+  `STRIP=name`             Remove any child elements with the given name in the default namespace
+  `STRIP=name namespace`   Remove any child elements with the given name and the given namespace
+  `INJECT=xml`             Inject the given XML into the stanza as a child element
+
+### Informational
+
+  Action          Description
+  --------------- ------------------------------------------------------------------------------------------------------------------------
+  `LOG=message`   Logs the given message to Prosody's log file. Optionally prefix it with a log level in square brackets, e.g. `[debug]`