[[ch-reference-firewall]]
== Firewall Reference

The firewall component of the Symbiosis system serves to protect the
system by controlling its inbound and outbound connections.  It
comprises of a set of rules, and automatic whitelist and blacklist
generation.

The firewall should be configured over SFTP as the *admin* user, and
any changes made will take affect immediately.

[[s-firewall-normal-rules]]
=== Allowing and denying access to services
(((Firewall, accessing services)))

All usual firewall configuration can be carried out by creating and
deleting files in [directory]'/etc/symbiosis/firewall/'.  In this
directory there are a number of subdirectories.  Permissions for
inbound connections are stored in
[directory]'/etc/symbiosis/firewall/incoming.d/', and outbound
connections in [directory]'/etc/symbiosis/firewall/outgoing.d/'.  

These files are all of the format +number-name+.  The number
determines the position of the rule in the firewall, the name is the
name of the service that we wish to permit.  These names are stored in
'/etc/services'.  There are also names that do not correspond to
services, which are documented in the next section.

Additionally if the name is not known then the file format can be
+number-number+ where the first number specifies the position of the
rule in the firewall, and the second number is the port that should be
opened.  For example, the files '10-http' and '10-80' achieve the same
effect.

Finally, each file can contain a list of hostnames or IP addresses to
which that rule will apply, one per line.  For example, if addresses
were added to an incoming rule, named 'incoming.d/10-accept', all
connections *from* those addresses would be *accepted*.  If a file
were added named 'outgoing.d/20-reject' and address added to that
file, then outgoing connections *to* those addresses would be
*rejected*.

For example, to allow an incoming connection to arrive at your
machine, and be accepted, on port 22, you would create the file
'/etc/symbiosis/firewall/incoming.d/10-ssh'.  The firewall will update
as soon as the file has been created, so no commands are needed to be
run.

If you were wishing to ensure that your host would only accept
incoming SSH requests from your office you might create the same file
with the contents +office.my-brilliant-site.com+.

This would ensure that when the firewall was generated incoming
connections on the SSH port would be accepted from the host
+office.my-brilliant-site.com+ but not from anywhere else.  

[NOTE]
====================================================
If hostnames, rather than IP addresses are used, then they are
translated to IP addresses at the time the firewall is generated using
DNS.  If the IP address of a hostname changes, then the firewall may
not function as intended until any cached DNS entries have expired,
and the firewall has been regenerated.
====================================================


[[s-firewall-special-rules]]
=== Predefined special rules
(((Firewall, predefined rules)))

There are a number of rules that don't naturally fit the convention
described above.  This list describes rules that have been written
specially for Symbiosis to cope with these situations.  Each rule
described below can be used in both [directory]'incoming.d/' and
[directory]'outgoing.d/', and for both IPv4 and IPv6 addresses, unless
otherwise specified.

These rules are used in the same way as those described in the
previous chapter.  Files are added in the [directory]'incoming.d/' or
[directory]'outgoing.d/' directory with the name prefixed by a number
giving the position of the rule.  The files can contain addresses or
hostnames, one per line, against which the rule should be applied.

accept::  Accept all connections.  Uses the @iptables@ +ACCEPT+ target.

allow::   Alias of *accept*.

blacklist:: Alias of *reject*.

collector:: Permit TCP connections on port 1919.

dns:: Accept incoming TCP and UDP connections from port 53 to
high-numbered, unprivileged ports.  Designed to allow replies to DNS
queries.  This rule can be removed in favour of *related*.  This is
for *incoming* connections only.

drop:: Drop all connections.  Uses the @iptables@ +DROP+ target.

essential-icmpv6:: Accept ICMPv6 packets that are essential for IPv6
networking to operate.  Without this rule the machine IPv6 networking
*will not work*.  It permits ICMPv6 types destination-unreachable,
packet-too-big, parameter-problem, router-solicitation,
router-advertisement, neighbor-solicitation, and
neighbor-advertisement.  This is *IPv6* only.

established:: Permit connections that are already established.  Uses
the @iptables@ +ESTABLISHED+ target.

ftp:: Permit TCP connections on both ports 20 and 21, i.e. ftp and
ftp-data.

icmp:: Permit all ICMP connections.  This *IPv4* only.

icmpv6::  Permit all ICMP6 connections.  This is *IPv6* only.

imager:: Permit TCP connections on port 5000.

new:: Permit new connections.

ping:: Permit ICMP types echo-request, echo-reply, and ttl-exceeded,
for allowing the machine to be pinged, and show up on traceroutes.

reject:: Reject all connections.  Uses the @iptables@ +REJECT+ target.
For TCP connections a TCP reset is sent.  Otherwise it returns port
unreachable.

reject-www-data:: Rejects all outgoing connections that are started by
the *www-data* user.  *N.B.* if addresses are put in this file, they
will be *not* rejected, which is the reverse of how every other rule
functions.  See <<s-firewall-www-data-rule>> for more information.

related:: Accept new connections, but only if they are associated with
an existing one, for example DNS queries, or FTP data transfer.

whitelist:: Alias of *accept*.

These rules are all contained in
[directory]'/usr/share/symbiosis/firewall/rule.d/'.  It is perfectly
possible to write your own rules based on those in this directory, but
they should be kept in
[directory]'/usr/local/share/symbiosis/firewall/rule.d/'.

[[s-firewall-example]]
=== An example firewall
(((Firewall, example configuration)))

This example should be read in conjunction with the previous sections.
A machine has the following firewall rules defined for its incoming
connections.

 * 'incoming.d/00-related'
 * 'incoming.d/00-established'
 * 'incoming.d/05-essential-icmpv6'
 * 'incoming.d/05-ping'
 * 'incoming.d/07-ssh' which contains +1.2.3.4+, and
   +2001:41c8:1:dead:beef::/64+ on separate lines.
 * 'incoming.d/10-http'
 * 'incoming.d/20-25'
 * 'incoming.d/99-reject'
 * 'incoming.d/100-666'

This would set up a firewall that would do the following tests, in
order:

  1. Accepted all packets from *established* connections. 
  2. Accepted all packets from *related* connections
  3. Accepted all ICMPv6 packets required for IPv6 connectivity.
  4. Accepted ICMP/ICMPv6 packets required for pings and traceroutes.
  5. Accepted new TCP/UDP connections to port 22 (SSH), but only from 1.2.3.4
     or addresses in the 2001:41c8:1:dead:beef::/64 netblock.
  6. Accepted new TCP/UDP connections to port 666.  Note that this rule comes
     before '10-http', even though it is called '100-666'.  This is because the
     order is given by the ASCII rather than numerical value of the filename.
  7. Accepted new TCP/UDP connections to port 80 (HTTP).
  8. Accepted new TCP/UDP connections to port 25 (SMTP).
  9. Rejected anything that had not been accepted yet.

These rules would be installed for IPv4 and IPv6 connections using @iptables@
and @ip6tables@ respectively.  To inspect the firewall rules at any given time,
you can run +sudo iptables -L -v -n+ which will return the current firewall
status.  In this example, the rules would look like this.

--------------------------------------------------
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target    prot opt in out source          destination
    0     0 ACCEPT    all  --  lo *   0.0.0.0/0       0.0.0.0/0
   13  1012 whitelist all  --  *  *   0.0.0.0/0       0.0.0.0/0
    0     0 blacklist all  --  *  *   0.0.0.0/0       0.0.0.0/0
    0     0 ACCEPT    all  --  *  *   0.0.0.0/0       0.0.0.0/0 state ESTABLISHED
    0     0 ACCEPT    all  --  *  *   0.0.0.0/0       0.0.0.0/0 state RELATED
    0     0 ACCEPT    icmp --  *  *   0.0.0.0/0       0.0.0.0/0 icmp type 8
    0     0 ACCEPT    icmp --  *  *   0.0.0.0/0       0.0.0.0/0 icmp type 0
    0     0 ACCEPT    icmp --  *  *   0.0.0.0/0       0.0.0.0/0 icmp type 11
    0     0 ACCEPT    tcp  --  *  *   1.2.3.4         0.0.0.0/0 tcp dpt:22
    0     0 ACCEPT    udp  --  *  *   1.2.3.4         0.0.0.0/0 udp dpt:22
    0     0 ACCEPT    tcp  --  *  *   0.0.0.0/0       0.0.0.0/0 tcp dpt:80
    0     0 ACCEPT    udp  --  *  *   0.0.0.0/0       0.0.0.0/0 udp dpt:80
    0     0 ACCEPT    tcp  --  *  *   0.0.0.0/0       0.0.0.0/0 tcp dpt:666
    0     0 ACCEPT    udp  --  *  *   0.0.0.0/0       0.0.0.0/0 udp dpt:666
    0     0 ACCEPT    tcp  --  *  *   0.0.0.0/0       0.0.0.0/0 tcp dpt:25
    0     0 ACCEPT    udp  --  *  *   0.0.0.0/0       0.0.0.0/0 udp dpt:25
    0     0 REJECT    all  --  *  *   0.0.0.0/0       0.0.0.0/0 reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target    prot opt in out source          destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target    prot opt in out source          destination
    0     0 ACCEPT    all  --  *  lo  0.0.0.0/0       0.0.0.0/0
    7  1388 ACCEPT    all  --  *  *   0.0.0.0/0       0.0.0.0/0 state ESTABLISHED
    0     0 ACCEPT    all  --  *  *   0.0.0.0/0       0.0.0.0/0 state RELATED
    0     0 REJECT    all  --  *  *   0.0.0.0/0       0.0.0.0/0 owner UID match 33 reject-with icmp-port-unreachable

Chain blacklist (1 references)
 pkts bytes target    prot opt in out source          destination
    0     0 REJECT    all  --  *  *   71.63.72.4      0.0.0.0/0 reject-with icmp-port-unreachable
    0     0 REJECT    all  --  *  *   61.145.118.190  0.0.0.0/0 reject-with icmp-port-unreachable

Chain whitelist (1 references)
 pkts bytes target    prot opt in out source           destination
   13  1012 ACCEPT    all  --  *  *   212.110.163.132 0.0.0.0/0
--------------------------------------------------

This listing shows how the rules in the files under
[directory]'/etc/symbiosis/firewall/' are translated into @iptables@
rules.  It also shows that by default all connections on the loopback
interface *lo* are permitted, and that the whitelist and blacklist
tables have references in the +INPUT+, i.e. incoming, table before the
rules defined in [directory]'/etc/symbiosis/firewall/incoming.d/' are
applied.

IPv6 rules follow the same format, and can be checked by running +sudo
ip6tables -L -v -n+.

[[s-firewall-www-data-rule]]
=== Allowing web applications to make remote connections

By default the firewall contains the rule
'outgoing.d/50-reject-www-data', which is designed to reject outgoing
connections made by the web server.  This prevents many ways of
infecting a machine with malicious software following a compromise in
a web application.  

Following establishing that a web application has security flaws,
hackers will attempt to trick the application into downloading their
software onto the machine.  Once downloaded the software is used in
various ways, for example to participate in denial of service attacks,
or to access confidential data on the machine.  Thus this rule is a
basic defence against vulnerable web applications being exploited, and
is a good thing to have in place.

However there are legitimate cases when a web application might need
to make such a connection.  For example, if you have an application
which needs to make outgoing HTTP connections to update RSS or Twitter
feeds, you will need to either add permitted addresses to the file, or
remove it completely.

For example, to permit access to +search.twitter.com+, add that
address to the file 'outgoing.d/50-reject-www-data' to permit it.

Adding addresses to this file will *permit* outgoing connections to
those addresses.

[[s-firewall-custom-additions]]
=== Making custom additions to your firewall
(((Firewall, adding custom rules)))

The Symbiosis firewall package should allow you to carry out the most
common tasks, simply by creating files named after the services you
wish to permit or deny.

However there are times when you might wish to make your own custom
additions, and for this purpose the firewall package allows you to run
an unlimited number of custom scripts/programs once it has loaded the
rules - these scripts may perform arbitrary actions, but will be most
typically used to update the firewall rules, via the @iptables@ or
@ip6tables@ commands.

The program @run-parts@ is used to execute scripts in
[directory]'/etc/symbiosis/firewall/local.d/', after the firewall has
finished loading.  This means that the scripts have to have to fulfil
the naming conditions described in the
http://manpages.debian.net/cgi-bin/man.cgi?query=run-parts&manpath=Debian+6.0+squeeze&format=html[run-parts(8)]
manual page.  Essentially the script should be marked executable, and
only contain alphanumeric characters in its name.

[WARNING]
==================================================
If any scripts in [directory]'local.d/' exit with a non-zero status the
firewall will be deemed to have failed in some way, and the firewall
will be restored to its prior state.
==================================================

[[s-firewall-blacklist]]
=== Blocking abusive remote hosts
(((Firewall, automatic blacklist)))

The 'symbiosis-firewall-blacklist' tool runs four times an hour, and
is designed to scan your server's logfiles for abusive behaviour from
malicious remote hosts.  Malicious activity which is detected will
result in the remote host being denied further access to your server.

Currently we regard malicious activity as:

 - Invalid SSH logins.
 - Invalid FTP logins.
 - Invalid SMTP/POP3/IMAP/ManageSieve logins.

Every 15 minutes various logfiles are scanned for certain patterns to
search for new malicious IPs, and the firewall is updated.

These patterns are defined in
[directory]'/etc/symbiosis/firewall/patterns.d/'.  For example, for SSH
the following pattern definition is used:
(((Firewall, patterns used for blacklisting IPs)))

---------------------------------------------------------
#
#  The logfile we look for matches within.
#
file = /var/log/auth.log <1>

#
#  Any matches will be denied access to these ports.
#
#  Comma-separated values are expected.
#
ports = 22 <2>


#
#  Patterns we'll match upon.
#
Failed password for invalid user [^ ]+ from __IP__ port [^ ]+ ssh2 <3>
Failed password for [^ ]+ from __IP__ port [^ ]+ ssh2
---------------------------------------------------------
<1> Is the file to search
<2> Are the ports to block
<3> Are the regular expressions to look for, where +++__IP__+++ is a
    pre-defined regular expression that matches both IPv4 and IPv6
    addresses.

If an IP matches one of those patterns in the period since the last
check was made, it is added to the blacklist.

Disabling the firewall completely will disable the blacklisting
behaviour, but you might also wish to disable that separately.

To do this, login over SFTP as *admin* and create the file
'/etc/symbiosis/firewall/blacklist/disabled'.  This will immediately
disable and clear the blacklist.

NOTE: IPv6 addresses are masked to a /64, which is the smallest
assignment of addresses recommended for an end site.


[[s-firewall-whitelist]]
=== Whitelisting "known-good" IP addresses
(((Firewall, automatic whitelist)))

The 'symbiosis-firewall-whitelist' tool runs once per hour, and is
designed to perform the opposite task to the
'symbiosis-firewall-blacklist' script - in short it is designed to
ensure that any remote host which has successfully connected to your
server in the past isn't (accidentally) blacklisted in the future.

Every hour the script will examine the successful logins which have
been observed recently.  Each IP address which has successfully been
the source of a login attempt will be permitted access to the system
on a global basis, and will thus not be locked out.

As with the automatic blacklist, IPv6 addresses are masked to a /64,
which is the smallest recommended assignment for an end site.

To disable the automatic whitelist, login over SFTP as *admin* and
create the file '/etc/symbiosis/firewall/whitelist.d/disabled'.  This
will immediately clear the whitelist, and prevent further updates.

You can add your own entries to the whitelist, which never expire, by
creating entries in the directory [directory]'/etc/symbiosis/firewall/whitelist.d/'.
Create the file '/etc/symbiosis/firewall/whitelist.d/<ip address>' and the specified
IP address will not be blacklisted, or refused access to your server.

[[s-syn-protection]]
=== SYN-ACK/ACK flood protection

Symbiosis now comes with basic SYN-ACK/ACK flood protection. These are simple
 but effective denial of service attacks, which can leave the network stack inundated.
https://en.wikipedia.org/wiki/SYN_flood[Wikipedia has an article on the matter for the curious]

To enable the protection, create the following file :

'/etc/symbiosis/firewall/incoming.d/00-syn-ack-flood-protection'

[[s-disabling-firewall]]
=== Disabling the firewall
(((Firewall, disabling)))

If you wish you may disable the firewall completely, allowing remote
users to connect to any service you have running upon your machine.

We'd not recommend that you disable the firewall, because it does provide
a increase in system security, but if you wish it is possible by
executing the following two commands:

------------------------------------------------------
touch /etc/symbiosis/firewall/disabled
sudo symbiosis-firewall flush
------------------------------------------------------

The presence of the disabled rule will not itself clear the firewall,
merely prevent further updates to it, which is why the +flush+ command
is needed.

=== Configuration layout
(((Firewall, configuration layout)))

All configuration of the firewall is conducted via the presence or
absence of files in a number of directories beneath
[directory]'/etc/symbiosis/firewall/'.  Actions and rules are all kept
under [directory]'/usr/share/symbiosis/firewall/'.

[directory]'/etc/symbiosis/firewall/blacklist.d/'::
  A persistent record of IP addresses which are blacklisted, such that
  no connections will be permitted from them.
'/etc/symbiosis/firewall/blacklist.d/disabled'::
  If this file is present, then the automatic blacklisting is
  disabled.
'/etc/symbiosis/firewall/disabled':: If this file is present then the
firewall will be disabled.  However this will not clear the firewall
rules.  See <<s-disabling-firewall>>.
[directory]'/etc/symbiosis/firewall/incoming.d/'::
  Settings related to the incoming connections your machine will
  receive.
[directory]'/etc/symbiosis/firewall/local.d/'::
  The place to add local customisations.
[directory]'/etc/symbiosis/firewall/outgoing.d/'::
  Settings related to the outgoing connections your machine is
  permitted to initiate.
[directory]'/etc/symbiosis/firewall/patterns.d/'::
  A collection of pattern files use by @symbiosis-firewall-blacklist@
  to automatically determine addresses to blacklist
[directory]'/etc/symbiosis/firewall/whitelist.d/'::
  A persistent record of IP addresses which are always allowed to
  connect to your server.
'/etc/symbiosis/firewall/whitelist.d/disabled'::
  If this file is present, then the automatic whitelisting is
  disabled.
[directory]'/usr/share/symbiosis/firewall/action.d/'::
  This directory contains the various actions that the
  @symbiosis-firewall@ uses to maintain the firewall.  If you wish to
  write your own actions, or change the ones that come with symbiosis,
  they should go in
  [directory]'/usr/local/share/symbiosis/firewall/action.d/'.
[directory]'/usr/share/symbiosis/firewall/rule.d/'::
  This directory contains the various pre-defined rules described in
  <<s-firewall-special-rules>>.  If you wish to add your own rules,
  or change the ones provided, they should go in
  [directory]'/usr/local/share/symbiosis/firewall/rule.d/'.

