diff options
Diffstat (limited to 'roles/common/templates')
23 files changed, 617 insertions, 390 deletions
diff --git a/roles/common/templates/etc/apt/preferences.j2 b/roles/common/templates/etc/apt/preferences.j2 index ba10834..39b610e 100644 --- a/roles/common/templates/etc/apt/preferences.j2 +++ b/roles/common/templates/etc/apt/preferences.j2 @@ -1,38 +1,38 @@ # {{ ansible_managed }} # Do NOT edit this file directly! -# Install updates as soon as they're available -Package: * -Pin: release a={{ ansible_lsb.codename }}-updates -Pin-Priority: 990 +## Install updates as soon as they're available +#Package: * +#Pin: release o=Debian, n={{ ansible_lsb.codename }}-updates +#Pin-Priority: 990 {% if 'backports' in group_names -%} # Automatically packages from backports (those manually installed) Package: * -Pin: release a={{ ansible_lsb.codename }}-backports +Pin: release o=Debian Backports, n={{ ansible_lsb.codename }}-backports Pin-Priority: 200 {% endif %} -{% if 'non-free' in group_names -%} +{% if inventory_hostname_short in non_free_packages.keys() -%} # Automatically upgrade non-free firmwares (when manually installed) -Package: firmware-linux-nonfree +Package: {{ non_free_packages[inventory_hostname_short] | join (' ') }} +Pin: release o=Debian Pin-Priority: 200 {% endif %} -{% if ansible_processor[0] | search('^(Genuine)?Intel.*') and - not (ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen') -%} +{% if ansible_processor[1] is search('^(Genuine)?Intel.*') and not ansible_virtualization_role == 'guest' and ansible_lsb.major_release | int < 12 -%} # Automatically upgrade the microcode (when manually installed) Package: intel-microcode iucode-tool -Pin: version * +Pin: release o=Debian Pin-Priority: 200 {% endif %} # Never, ever install things from contrib or non-free unless they have been # whitelisted above Package: * Pin: release c=contrib Pin-Priority: -1 Package: * Pin: release c=non-free Pin-Priority: -1 diff --git a/roles/common/templates/etc/apt/sources.list.j2 b/roles/common/templates/etc/apt/sources.list.j2 index 5788ade..f524f2f 100644 --- a/roles/common/templates/etc/apt/sources.list.j2 +++ b/roles/common/templates/etc/apt/sources.list.j2 @@ -1,13 +1,13 @@ # {{ ansible_managed }} # Do NOT edit this file directly! # vim: set filetype=debsources : -deb http://ftp.se.debian.org/debian/ {{ ansible_lsb.codename }} main{% if 'non-free' in group_names or (ansible_processor[0] | search("^(Genuine)?Intel.*") and not (ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen')) %} contrib non-free{% endif %} +deb https://deb.debian.org/debian {{ ansible_lsb.codename }} main{% if inventory_hostname_short in non_free_packages.keys() or (ansible_processor[1] is search("^(Genuine)?Intel.*") and not ansible_virtualization_role == 'guest' and ansible_lsb.major_release | int < 12) %} contrib non-free{% endif %}{% if ansible_lsb.major_release | int >= 12 %} non-free-firmware{% endif %} -deb http://security.debian.org/ {{ ansible_lsb.codename }}/updates main{% if 'non-free' in group_names or (ansible_processor[0] | search("^(Genuine)?Intel.*") and not (ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen')) %} contrib non-free{% endif %} +deb https://deb.debian.org/debian-security {{ ansible_lsb.codename }}{% if ansible_lsb.major_release | int < 11 %}/updates{% else %}-security{% endif %} main{% if inventory_hostname_short in non_free_packages.keys() or (ansible_processor[1] is search("^(Genuine)?Intel.*") and not ansible_virtualization_role == 'guest' and ansible_lsb.major_release | int < 12) %} contrib non-free{% endif %}{% if ansible_lsb.major_release | int >= 12 %} non-free-firmware{% endif %} -deb http://ftp.se.debian.org/debian/ {{ ansible_lsb.codename }}-updates main +deb https://deb.debian.org/debian {{ ansible_lsb.codename }}-updates main{% if ansible_lsb.major_release | int >= 12 %} non-free-firmware{% endif %} {% if 'backports' in group_names -%} -deb http://ftp.debian.org/debian/ {{ ansible_lsb.codename }}-backports main +deb https://deb.debian.org/debian {{ ansible_lsb.codename }}-backports main {% endif %} diff --git a/roles/common/templates/etc/bacula/bacula-fd.conf.j2 b/roles/common/templates/etc/bacula/bacula-fd.conf.j2 index a47bb90..d0af395 100644 --- a/roles/common/templates/etc/bacula/bacula-fd.conf.j2 +++ b/roles/common/templates/etc/bacula/bacula-fd.conf.j2 @@ -1,41 +1,46 @@ # # Default Bacula File Daemon Configuration file # -# For Bacula release 5.2.6 (21 February 2012) -- debian jessie/sid +# For Bacula release 9.6.7 (10 December 2020) -- debian bullseye/sid +# +# There is not much to change here except perhaps the +# File daemon Name to +# +# +# Copyright (C) 2000-2020 Kern Sibbald +# License: BSD 2-Clause; see file LICENSE-FOSS +# # # List Directors who are permitted to contact this File daemon # -{% for dir in groups['bacula-dir'] | sort %} +{% for dir in groups['bacula_dir'] | sort %} Director { Name = {{ hostvars[dir].inventory_hostname_short }}-dir @|"sed -n '/^{{ hostvars[dir].inventory_hostname_short }}-dir\\s/ {s//Password = /p; q}' /etc/bacula/passwords-fd" } # Send all messages except skipped files back to Director Messages { Name = Standard director = {{ hostvars[dir].inventory_hostname_short }}-dir = all, !skipped, !restored } {% endfor %} # # "Global" File daemon configuration specifications # FileDaemon { # define myself Name = {{ inventory_hostname_short }}-fd Working Directory = /var/lib/bacula - Pid Directory = /var/run/bacula + Pid Directory = /run/bacula Maximum Concurrent Jobs = 20 - FDAddress = 127.0.0.1 - FDPort = 9112 - FDSourceAddress = 127.0.0.1 -{% if 'bacula-dir' not in group_names or 'bacula-sd' not in group_names %} - Heartbeat Interval = 60s -{% endif %} + FDAddress = {{ ipsec[inventory_hostname_short] }} + FDPort = 9102 + SDConnectTimeout = 5 min PKI Signatures = Yes # Enable Data Signing PKI Encryption = Yes # Enable Data Encryption PKI Keypair = /etc/bacula/ssl/{{ inventory_hostname_short }}.pem # Public and Private Keys PKI Master Key = /etc/bacula/ssl/master.pem # ONLY the Public Key } diff --git a/roles/common/templates/etc/clamav/freshclam.conf.j2 b/roles/common/templates/etc/clamav/freshclam.conf.j2 new file mode 100644 index 0000000..650a2b3 --- /dev/null +++ b/roles/common/templates/etc/clamav/freshclam.conf.j2 @@ -0,0 +1,31 @@ +# Automatically created by the clamav-freshclam postinst +# Comments will get lost when you reconfigure the clamav-freshclam package + +DatabaseOwner clamav +UpdateLogFile /var/log/clamav/freshclam.log +LogVerbose false +LogSyslog false +LogFacility LOG_LOCAL6 +LogFileMaxSize 0 +LogRotate true +LogTime true +Foreground false +Debug false +MaxAttempts 5 +DatabaseDirectory /var/lib/clamav +DNSDatabaseInfo current.cvd.clamav.net +ConnectTimeout 30 +ReceiveTimeout 30 +TestDatabases yes +ScriptedUpdates yes +CompressLocalDatabase no +Bytecode true +NotifyClamd /etc/clamav/clamd.conf +# Check for new database 24 times a day +Checks 24 +DatabaseMirror db.{{ geoip | default('local') }}.clamav.net +{% if geoip is defined and ansible_default_ipv6 %} +DatabaseMirror db.{{ geoip }}.ipv6.clamav.net +{% endif %} +DatabaseMirror database.clamav.net +DatabaseMirror db.other.clamav.net diff --git a/roles/common/templates/etc/default/debsecan.j2 b/roles/common/templates/etc/default/debsecan.j2 deleted file mode 100644 index 71fee1c..0000000 --- a/roles/common/templates/etc/default/debsecan.j2 +++ /dev/null @@ -1,17 +0,0 @@ -# Configuration file for debsecan. Contents of this file should -# adhere to the KEY=VALUE shell syntax. This file may be edited by -# debsecan's scripts, but your modifications are preserved. - -# If true, enable daily reports, sent by email. -REPORT=true - -# For better reporting, specify the correct suite here, using the code -# name (that is, "sid" instead of "unstable"). -SUITE={{ ansible_lsb.codename }} - -# Mail address to which reports are sent. -MAILTO=admin@fripost.org - -# The URL from which vulnerability data is downloaded. Empty for the -# built-in default. -SOURCE= diff --git a/roles/common/templates/etc/fail2ban/jail.local.j2 b/roles/common/templates/etc/fail2ban/jail.local.j2 index a34cb70..3cd19cc 100644 --- a/roles/common/templates/etc/fail2ban/jail.local.j2 +++ b/roles/common/templates/etc/fail2ban/jail.local.j2 @@ -1,93 +1,46 @@ # {{ ansible_managed }} # Do NOT edit this file directly! [DEFAULT] # Destination email address used solely for the interpolations in # jail.{conf,local} configuration files. destemail = admin@fripost.org -# Specify chain where jumps would need to be added in iptables-* actions -chain = fail2ban +# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban +# will not ban a host which matches an address in this list. Several addresses +# can be defined using space (and/or comma) separator. +ignoreip = 127.0.0.0/8, ::1, {{ ipsec_subnet }} -# Choose default action. -action = %(action_)s +banaction = nftables-allports -# Don't ban ourselves. -ignoreip = 127.0.0.0/8 {{ groups.all | sort | join(' ') }} +# must match nftables.conf's blackholes timeouts +bantime = 10m # # JAILS # -[ssh] - -enabled = true -port = {{ ansible_ssh_port|default('22') }} -filter = sshd -logpath = /var/log/auth.log -maxretry = 5 - -[ssh-ddos] - -enabled = true -port = {{ ansible_ssh_port|default('22') }} -filter = sshd-ddos -logpath = /var/log/auth.log -maxretry = 2 - - -# Generic filter for pam. Has to be used with action which bans all ports -# such as iptables-allports, shorewall -[pam-generic] - -enabled = true -# pam-generic filter can be customized to monitor specific subset of 'tty's -filter = pam-generic -# port actually must be irrelevant but lets leave it all for some possible uses -port = anyport -banaction = iptables-allports -logpath = /var/log/auth.log -maxretry = 6 +[sshd] +enabled = true -{% if 'MX' in group_names %} [postfix] +enabled = {{ 'MX' in group_names }} -enabled = true -port = smtp -filter = postfix -logpath = /var/log/mail.log -maxretry = 10 -{% endif %} - - -{% if 'IMAP' in group_names %} [dovecot] +enabled = {{ 'IMAP' in group_names }} -enabled = true -port = imap2,imap3,imaps,pop3,pop3s -filter = dovecot -logpath = /var/log/mail.log -{% endif %} - - -{% if 'MSA' in group_names %} -[sasl] - -enabled = true -port = submission -filter = postfix-sasl -logpath = /var/log/mail.warn -{% endif %} - +[postfix-sasl] +enabled = {{ 'MSA' in group_names }} -{% if 'webmail' in group_names %} -[roundcube] +[roundcube-auth] +enabled = {{ 'webmail' in group_names }} +logpath = /var/log/roundcube/errors.log -enabled = true -port = http,https -filter = roundcube -logpath = /var/log/roundcube/errors -{% endif %} +[nextcloud] +enabled = {{ 'nextcloud' in group_names }} +port = http,https +filter = nextcloud +logpath = /var/log/nextcloud/nextcloud.log # vim: set filetype=dosini : diff --git a/roles/common/templates/etc/ipsec.conf.j2 b/roles/common/templates/etc/ipsec.conf.j2 new file mode 100644 index 0000000..eaa9a08 --- /dev/null +++ b/roles/common/templates/etc/ipsec.conf.j2 @@ -0,0 +1,45 @@ +# {{ ansible_managed }} +# Do NOT edit this file directly! + +config setup + charondebug = "dmn 0, lib 0, cfg 0, ike 0, enc 0, net 0" + +conn %default + keyexchange = ikev2 + keyingtries = %forever + ike = aes256gcm16-prfsha384-ecp384! + esp = aes256gcm16-ecp384! +{% if 'NATed' not in group_names %} + mobike = no +{% endif %} +{% if 'DynDNS' in group_names %} + leftallowany = yes +{% endif %} + leftauth = pubkey + left = %defaultroute + leftsubnet = {{ ipsec[inventory_hostname_short] | ansible.utils.ipv4 }}/32 + leftid = {{ inventory_hostname }} + leftsigkey = {{ inventory_hostname_short }}.pem + leftfirewall = no + lefthostaccess = yes + rightauth = pubkey + auto = route + dpdaction = hold + inactivity = 30m + modeconfig = push + +{% for host in groups.all | difference([inventory_hostname]) | sort %} + +conn {{ hostvars[host].inventory_hostname_short }} + right = {{ hostvars[host].inventory_hostname }} +{% if 'DynDNS' in hostvars[host].group_names %} + rightallowany = yes +{% endif %} + rightsigkey = {{ hostvars[host].inventory_hostname_short }}.pem + rightsubnet = {{ ipsec[ hostvars[host].inventory_hostname_short ] | ansible.utils.ipv4 }}/32 + reqid = {{ ipsec[ hostvars[host].inventory_hostname_short ].replace(":",".").split(".")[-1] }} +{% if 'NATed' not in group_names and 'NATed' in hostvars[host].group_names %} + mobike = yes +{% endif %} + +{%- endfor %} diff --git a/roles/common/templates/etc/ipsec.secrets.j2 b/roles/common/templates/etc/ipsec.secrets.j2 new file mode 100644 index 0000000..6ed670d --- /dev/null +++ b/roles/common/templates/etc/ipsec.secrets.j2 @@ -0,0 +1,5 @@ +# {{ ansible_managed }} +# Do NOT edit this file directly! + +# Our VPN uses RSA only. +: RSA {{ inventory_hostname_short }}.key diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2 deleted file mode 100644 index 8792771..0000000 --- a/roles/common/templates/etc/iptables/services.j2 +++ /dev/null @@ -1,81 +0,0 @@ -# {{ ansible_managed }} -# Do NOT edit this file directly! -# -# direction protocol destination port source port -# (in|out|inout)[46]? (tcp|udp|..) (port|port:port|port,port) (port|port:port|port,port) - -out tcp 80,443 # HTTP/HTTPS -out tcp 9418 # GIT -out udp 53 # DNS -out udp 67 # DHCP -out tcp 22 # SSH -{% if 'NTP-master' in group_names %} -in udp 123 # NTP -out udp 123 # NTP -{% else %} -out udp 123 123 # NTP -{% endif %} - -in tcp {{ ansible_ssh_port|default('22') }} # SSH -{% if 'LDAP-provider' in group_names %} -in tcp 636 # LDAPS -{% elif 'MX' in group_names or 'lists' in group_names %} -out tcp 636 # LDAPS -{% endif %} -{% if 'MX' in group_names %} -in tcp 25 # SMTP -{% if 'MDA' not in group_names %} -out tcp {{ postfix_instance.IMAP.port }} -{% endif %} -{% if 'lists' not in group_names %} -out tcp {{ postfix_instance.lists.port }} -{% endif %} -{% endif %} -{% if 'out' in group_names %} -{% if groups.all | difference([inventory_hostname]) %} -in tcp {{ postfix_instance.out.port }} -{% endif %} -out tcp 25 # SMTP -{% else %} -out tcp {{ postfix_instance.out.port }} -{% endif %} -{% if 'IMAP' in group_names %} -in tcp 993 # IMAPS -in tcp 4190 # MANAGESIEVE -{% endif %} -{% if 'MDA' in group_names and 'MX' not in group_names %} -in tcp {{ postfix_instance.IMAP.port }} -{% endif %} -{% if 'lists' in group_names and 'MX' not in group_names %} -in tcp {{ postfix_instance.lists.port }} -{% endif %} -{% if 'MSA' in group_names %} -in tcp 587 # SMTP-AUTH -{% endif %} -{% if 'webmail' in group_names or 'lists' in group_names or 'wiki' in group_names %} -in tcp 80,443 # HTTP/HTTPS -{% endif %} -{% if 'webmail' in group_names and 'IMAP' not in group_names %} -out tcp 993 # IMAP -out tcp 4190 # MANAGESIEVE -{% endif %} -{% if 'bacula-dir' in group_names and groups.all | difference(groups['bacula-dir']) %} -out tcp 9102 # BACULA-FD -{% elif groups['bacula-dir'] | difference([inventory_hostname]) %} -in tcp 9102 # BACULA-FD -{% endif %} -{% if 'bacula-sd' in group_names and groups.all | difference(groups['bacula-sd']) %} -in tcp 9103 # BACULA-SD -{% elif groups['bacula-sd'] | difference([inventory_hostname]) %} -out tcp 9103 # BACULA-SD -{% endif %} -{% if 'munin-master' in group_names and groups.all | difference([inventory_hostname]) %} -out tcp 4949 # MUNIN -{% endif %} -{% if groups['munin-master'] | difference([inventory_hostname]) %} -in tcp 4949 # MUNIN -{% endif %} -{% if 'LDAP-provider' in group_names %} -out tcp 11371 # HKP -out tcp 43 # WHOIS -{% endif %} diff --git a/roles/common/templates/etc/munin/munin-node.conf.j2 b/roles/common/templates/etc/munin/munin-node.conf.j2 index de4098a..1aba053 100644 --- a/roles/common/templates/etc/munin/munin-node.conf.j2 +++ b/roles/common/templates/etc/munin/munin-node.conf.j2 @@ -1,51 +1,52 @@ # # Example config-file for munin-node # log_level 4 log_file /var/log/munin/munin-node.log -pid_file /var/run/munin/munin-node.pid +pid_file /run/munin/munin-node.pid background 1 setsid 1 user root group root # This is the timeout for the whole transaction. # Units are in sec. Default is 15 min # # global_timeout 900 # This is the timeout for each plugin. # Units are in sec. Default is 1 min # # timeout 60 # Regexps for files to ignore ignore_file [\#~]$ ignore_file DEADJOE$ ignore_file \.bak$ ignore_file %$ ignore_file \.dpkg-(tmp|new|old|dist)$ ignore_file \.rpm(save|new)$ ignore_file \.pod$ # Set this if the client doesn't report the correct hostname when -# telnetting to localhost, port 4949 +# telnetting to {{ ipsec[inventory_hostname_short] }}, port 4949 # host_name {{ inventory_hostname_short }} # A list of addresses that are allowed to connect. This must be a # regular expression, since Net::Server does not understand CIDR-style # network notation unless the perl module Net::CIDR is installed. You # may repeat the allow line as many times as you'd like -allow ^127\.0\.0\.1$ -allow ^::1$ +{% for host in groups['munin_master'] %} +allow ^{{ ipsec[ hostvars[host].inventory_hostname_short ] | ansible.utils.ipv4 | replace(".","\.") }}$ +{% endfor %} # Which address to bind to; -host 127.0.0.1 +host {{ ipsec[inventory_hostname_short] }} # And which port port 4994 diff --git a/roles/common/templates/etc/munin/plugin-conf.d/munin-node.j2 b/roles/common/templates/etc/munin/plugin-conf.d/munin-node.j2 index 6cfa3f9..ec471eb 100644 --- a/roles/common/templates/etc/munin/plugin-conf.d/munin-node.j2 +++ b/roles/common/templates/etc/munin/plugin-conf.d/munin-node.j2 @@ -19,77 +19,78 @@ env.MUNIN_MKTEMP /bin/mktemp -p /tmp/ $1 env.amavislog /var/log/mail.info [apt] user root [courier_mta_mailqueue] group daemon [courier_mta_mailstats] group adm [courier_mta_mailvolume] group adm [cps*] user root [df*] env.warning 92 env.critical 98 +env.exclude_re ^/run/user [exim_mailqueue] group adm, (Debian-exim) [exim_mailstats] group adm, (Debian-exim) env.logdir /var/log/exim4/ env.logname mainlog [fw_conntrack] user root [fw_forwarded_local] user root [hddtemp_smartctl] user root [hddtemp2] user root [if_*] user root [if_err_*] user nobody [ip_*] user root [ipmi_*] user root [mysql*] user root env.mysqlopts --defaults-file=/etc/mysql/debian.cnf -env.mysqluser debian-sys-maint +env.mysqluser root env.mysqlconnection DBI:mysql:mysql;mysql_read_default_file=/etc/mysql/debian.cnf [postfix_mailqueue_*] user postfix [postfix_stats_*] group adm [postfix_sasl_*] group adm [postfix_mailvolume2] group adm env.postmulti postfix{% for g in postfix_instance.keys() | sort %}{% if g in group_names %} postfix-{{ postfix_instance[g].name }}{% endif %}{% endfor %} [dovecot_logins] group adm [dovecot_stats_*] diff --git a/roles/common/templates/etc/network/if-up.d/ipsec.j2 b/roles/common/templates/etc/network/if-up.d/ipsec.j2 new file mode 100755 index 0000000..9f183d3 --- /dev/null +++ b/roles/common/templates/etc/network/if-up.d/ipsec.j2 @@ -0,0 +1,46 @@ +#!/bin/sh + +# A post-up/down hook to automatically create/delete a virtual subnet +# for IPsec (inet4 only). +# Copyright © 2016 Guilhem Moulin <guilhem@fripost.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set -ue +PATH=/usr/sbin:/usr/bin:/sbin:/bin + +# Ignore the loopback interface and non inet4 families. +[ "$IFACE" != lo -a "$ADDRFAM" = inet ] || exit 0 + +# Only the device with the default, globally-scoped route, is of +# interest here. +iface="$( ip -o route show to default scope global \ + | sed -nr '/^default via \S+ dev (\S+).*/ {s//\1/p;q}' )" +[ "$iface" = "$IFACE" ] || exit 0 + +vip="{{ ipsec[inventory_hostname_short] }}" +vsubnet="{{ ipsec_subnet }}" + +case "$MODE" in + start) ip address add "$vip/32" dev "$IFACE" scope global || true + # Nullroute the subnet used for IPsec to avoid data leaks + # in the absence of xfrm lookup (i.e., when there is no + # matching IPsec Security Association). + ip route replace prohibit "$vsubnet" proto static || true + ip route replace table 220 to "$vsubnet" dev "$IFACE" proto static src "$vip" || true + ;; + stop) ip route del table 220 to "$vsubnet" dev "$IFACE" proto static src "$vip" || true + ip route del prohibit "$vsubnet" proto static || true + ip address del "$vip/32" dev "$IFACE" scope global || true +esac diff --git a/roles/common/templates/etc/nftables.conf.j2 b/roles/common/templates/etc/nftables.conf.j2 new file mode 100755 index 0000000..f603ed9 --- /dev/null +++ b/roles/common/templates/etc/nftables.conf.j2 @@ -0,0 +1,238 @@ +#!/usr/sbin/nft -f + +define in-tcp-ports = { + {{ ansible_port|default(22) }} +{% if 'MX' in group_names %} + , 25 # SMTP +{% endif %} +{% if 'LDAP_provider' in group_names %} + , 636 # ldaps +{% endif %} +{% if 'IMAP' in group_names %} + , 993 # imaps + , 4190 # ManageSieve +{% endif %} +{% if 'MSA' in group_names %} + , 587 # submission [RFC4409] + , 465 # submission over TLS [RFC8314] +{% endif %} +{% if 'webmail' in group_names or 'lists' in group_names or 'wiki' in group_names or 'nextcloud' in group_names %} + , 80 # HTTP + , 443 # HTTP over SSL/TLS +{% endif %} +} + +define out-tcp-ports = { + 22 + , 80 # HTTP + , 443 # HTTP over SSL/TLS +{% if 'out' in group_names or 'MSA' in group_names %} + , 25 # SMTP +{% endif %} +{% if 'LDAP_provider' in group_names %} + , 11371 # OpenPGP HTTP Keyserver + , 43 # whois +{% elif 'MX' in group_names or 'lists' in group_names or 'nextcloud' in group_names %} + , 636 # ldaps +{% endif %} +{% if 'IMAP' in group_names %} + , 2703 # Razor2 +{% endif %} +} + + +############################################################################### + +flush ruleset + +table netdev filter { +{% for if in ansible_interfaces %} +{% if if != "lo" and ansible_facts[if].active %} +{% set addr = (ansible_facts[if].ipv4 | default({'address': '0.0.0.0'})).address %} + chain INGRESS-{{ if }} { + type filter hook ingress device {{ if }} priority -499 + policy accept + + # IPsec traffic (refined later in the filter rule) + ip saddr {{ ipsec_subnet }} ip daddr {{ ipsec[inventory_hostname_short] }} meta secpath exists accept + + # rate-limiting is done directly by the kernel (net.ipv4.icmp_{ratelimit,ratemask} runtime options) + icmp type { echo-reply, echo-request, destination-unreachable, time-exceeded } counter accept + icmpv6 type { echo-reply, echo-request, destination-unreachable, + packet-too-big, time-exceeded, parameter-problem } counter accept + + # accept neighbour discovery for autoconfiguration, RFC 4890 sec. 4.4.1 + ip6 hoplimit 255 icmpv6 type { 133,134,135,136,141,142 } counter accept + + # accept link-local multicast receiver notification messages + ip6 saddr fe80::/10 ip6 daddr ff02::/16 ip6 hoplimit 1 icmpv6 type { 130,131,132,143 } counter accept + + # drop all remaining ICMP/ICMPv6 traffic + meta l4proto { icmp, icmpv6 } counter drop + + # bogon filter (cf. RFC 6890 for non-global ip addresses) + define bogon = { + 0.0.0.0/8 # this host, on this network (RFC 1122 sec. 3.2.1.3) +{% if not addr | ansible.utils.ipaddr('10.0.0.0/8') %} + , 10.0.0.0/8 # private-use (RFC 1918) +{% endif %} + , 100.64.0.0/10 # shared address space (RFC 6598) + , 127.0.0.0/8 # loopback (RFC 1122, sec. 3.2.1.3) + , 169.254.0.0/16 # link local (RFC 3927) + , 172.16.0.0/12 # private-use (RFC 1918) + , 192.0.0.0/24 # IETF protocol assignments (RFC 6890 sec. 2.1) + , 192.0.2.0/24 # documentation (RFC 5737) +{% if not addr | ansible.utils.ipaddr('192.168.0.0/16') %} + , 192.168.0.0/16 # private-use (RFC 1918) +{% endif %} + , 198.18.0.0/15 # benchmarking (RFC 2544) + , 198.51.100.0/24 # documentation (RFC 5737) + , 203.0.113.0/24 # documentation (RFC 5737) + , 224.0.0.0/3 # multicast - class D 224.0.0.0/4 + class E 240.0.0.0/4 (RFC 1112 sec. 4) + , 255.255.255.255/32 # limited broadcast (RFC 0919 sec. 7) + } + + ip saddr $bogon counter drop + ip daddr $bogon counter drop + + # See also https://www.team-cymru.org/Services/Bogons/fullbogons-ipv6.txt + define bogon6 = { + ::1/128 # loopback address (RFC 4291) + , ::/128 # unspecified (RFC 4291) + , ::ffff:0:0/96 # IPv4-mapped address (RFC 4291) + , 100::/64 # discard-only address block (RFC 6666) + , 2001::/23 # IETF protocol assignments (RFC 2928) + , 2001::/32 # TEREDO (RFC 4380) + , 2001:2::/48 # benchmarking (RFC 5180) + , 2001:db8::/32 # documentation (RFC 3849) + , 2001:10::/28 # ORCHID (RFC 4843) + , 2002::/16 # 6to4 (RFC 3056) + , fc00::/7 # unique-local (RFC 4193) + , fe80::/10 # linked-scoped unicast (RFC 4291) + } + + ip6 saddr $bogon6 counter drop + ip6 saddr $bogon6 counter drop + } +{% endif %} +{% endfor %} +} + +table inet raw { + chain PREROUTING-stateless { + # XXX can't add that to the ingress hook as that happens before IP defragmentation + # so we don't have the TCP header in later fragments (we don't want to drop IP + # fragments, see https://blog.cloudflare.com/ip-fragmentation-is-broken/ ) + type filter hook prerouting priority -399 # > NF_IP_PRI_CONNTRACK_DEFRAG (-400) + policy accept + + # stateless filter for bogus TCP packets + tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop # null packet + tcp flags & (fin|psh|urg) == fin|psh|urg counter drop # XMAS packet + tcp flags & (syn|rst) == syn|rst counter drop + tcp flags & (fin|rst) == fin|rst counter drop + tcp flags & (fin|syn) == fin|syn counter drop + tcp flags & (fin|psh|ack) == fin|psh counter drop + } + + chain PREROUTING { + type filter hook prerouting priority -199 # > NF_IP_PRI_CONNTRACK (-200) + policy accept + + # stateful filter + ct state invalid counter drop + } +} + +table inet filter { + # blackholes (timeout must match /etc/fail2ban/jail.local) + set fail2ban { type ipv4_addr; timeout 10m; } + set fail2ban6 { type ipv6_addr; timeout 10m; } + + chain input { + type filter hook input priority 0 + policy drop + + iif lo accept + + meta l4proto esp accept + ip daddr {{ ipsec[inventory_hostname_short] }} jump ipsec-in + + # incoming ICMP/ICMPv6 traffic was filtered in the ingress chain already + meta l4proto { icmp, icmpv6 } counter accept + + # NTP (ntpd uses sport 123 but systemd-timesyncd does not) + udp sport 123 ct state related,established accept + +{% if groups.all | length > 1 %} + udp sport 500 udp dport 500 ct state new,related,established accept +{% if groups.NATed | length > 0 %} + udp sport 4500 udp dport 4500 ct state new,related,established accept +{% endif %} +{% endif %} + + udp sport 53 ct state related,established accept + tcp sport 53 ct state related,established accept +{% if 'dhclient' in group_names %} + ip version 4 udp sport 67 udp dport 68 ct state related,established accept + ip6 version 6 udp sport 547 udp dport 546 ct state related,established accept +{% endif %} + + ip saddr @fail2ban counter drop + ip6 saddr @fail2ban6 counter drop + + tcp dport $in-tcp-ports ct state related,established accept + tcp dport $in-tcp-ports ct state new counter accept + tcp sport $out-tcp-ports ct state related,established accept + } + + chain output { + type filter hook output priority 0 + policy drop + + oif lo accept + + meta l4proto esp accept + ip saddr {{ ipsec[inventory_hostname_short] }} jump ipsec-out + + meta l4proto { icmp, icmpv6 } counter accept + + # NTP (ntpd uses sport 123 but systemd-timesyncd does not) + udp dport 123 ct state new,related,established accept + +{% if groups.all | length > 1 %} + udp sport 500 udp dport 500 ct state new,related,established accept +{% if groups.NATed | length > 0 %} + udp sport 4500 udp dport 4500 ct state new,related,established accept +{% endif %} +{% endif %} + + udp dport 53 ct state new,related,established accept + tcp dport 53 ct state new,related,established accept +{% if 'dhclient' in group_names %} + ip version 4 udp sport 68 udp dport 67 ct state new,related,established accept + ip6 version 6 udp sport 546 udp dport 547 ct state new,related,established accept +{% endif %} + + tcp sport $in-tcp-ports ct state related,established accept + tcp dport $out-tcp-ports ct state related,established accept + tcp dport $out-tcp-ports ct state new counter accept + + meta l4proto tcp counter reject with tcp reset + meta l4proto udp counter reject + counter reject + } + + chain ipsec-in { +{% for h in ipsec.keys() | difference([inventory_hostname_short]) | sort %} + ip saddr {{ ipsec[h] }} ipsec in reqid {{ ipsec[h].replace(":",".").split(".")[-1] }} counter accept +{% endfor %} + log prefix "ipsec-in " drop + } + chain ipsec-out { +{% for h in ipsec.keys() | difference([inventory_hostname_short]) | sort %} + ip daddr {{ ipsec[h] }} ipsec out reqid {{ ipsec[h].replace(":",".").split(".")[-1] }} counter accept +{% endfor %} + log prefix "ipsec-out " drop + } +} diff --git a/roles/common/templates/etc/ntp.conf.j2 b/roles/common/templates/etc/ntp.conf.j2 index d46ba18..b76f0dd 100644 --- a/roles/common/templates/etc/ntp.conf.j2 +++ b/roles/common/templates/etc/ntp.conf.j2 @@ -1,63 +1,59 @@ # /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help driftfile /var/lib/ntp/ntp.drift +# Leap seconds definition provided by tzdata +leapfile /usr/share/zoneinfo/leap-seconds.list # Enable this if you want statistics to be logged. #statsdir /var/log/ntpstats/ statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable # You do need to talk to an NTP server or two (or three). -{% if 'NTP-master' in group_names %} # Use Stratum One Time Servers: # http://support.ntp.org/bin/view/Servers/StratumOneTimeServers -server ntp1.sp.se iburst -server ntp2.sp.se iburst -server ntp2.gbg.netnod.se iburst -server ntp1.sth.netnod.se iburst -server ntp2.sth.netnod.se iburst -{% else %} -# Sychronize to our (stratum 2) NTP server, to ensure our network has a -# consistent time. -# TODO: use to pubkey authentication to unsure an attacker doesn't -# impersonate our NTP server and gives us incorrect time. -server ntp.fripost.org iburst -server 0.se.pool.ntp.org iburst -server 1.se.pool.ntp.org iburst -{% endif %} +server sth1.ntp.se iburst +server sth2.ntp.se iburst +server gbg1.ntp.se iburst +server gbg2.ntp.se iburst +server ntp1.sp.se iburst +server ntp2.sp.se iburst # Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for # details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions> # might also be helpful. # # Note that "restrict" applies to both servers and clients, so a configuration # that might be intended to block requests from certain clients could also end # up blocking replies from your own upstream servers. # By default, exchange time with everybody, but don't allow configuration. -restrict -4 default limited kod nomodify notrap nopeer noquery -restrict -6 default limited kod nomodify notrap nopeer noquery +restrict -4 default kod notrap nomodify nopeer noquery limited +restrict -6 default kod notrap nomodify nopeer noquery limited # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1 +# Needed for adding pool entries +restrict source notrap nomodify noquery + # Clients from this (example!) subnet have unlimited access, but only if # cryptographically authenticated. #restrict 192.168.123.0 mask 255.255.255.0 notrust # If you want to provide time to your local subnet, change the next line. # (Again, the address is an example only.) #broadcast 192.168.123.255 # If you want to listen to time broadcasts on your local subnet, de-comment the # next lines. Please do this only if you trust everybody on the network! #disable auth #broadcastclient diff --git a/roles/common/templates/etc/postfix/main.cf.j2 b/roles/common/templates/etc/postfix/main.cf.j2 index 1b0bc4a..5ac7920 100644 --- a/roles/common/templates/etc/postfix/main.cf.j2 +++ b/roles/common/templates/etc/postfix/main.cf.j2 @@ -1,70 +1,48 @@ ######################################################################## # Nullmailer configuration # # {{ ansible_managed }} # Do NOT edit this file directly! -smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) -biff = no -readme_directory = no -mail_owner = postfix +smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) +biff = no +readme_directory = no +compatibility_level = 2 +smtputf8_enable = no myorigin = /etc/mailname myhostname = {{ ansible_fqdn }} mydomain = {{ ansible_domain }} append_dot_mydomain = no # This server is for internal use only mynetworks_style = host inet_interfaces = loopback-only # No local delivery mydestination = local_transport = error:5.1.1 Mailbox unavailable alias_maps = local_recipient_maps = # All aliases are virtual -default_database_type = cdb -virtual_alias_maps = cdb:/etc/aliases +default_database_type = lmdb +virtual_alias_maps = lmdb:/etc/aliases alias_database = $virtual_alias_maps # Forward everything to our internal outgoing proxy -{% if 'out' in group_names %} -relayhost = [127.0.0.1]:{{ postfix_instance.out.port }} -{% else %} -relayhost = [outgoing.fripost.org]:{{ postfix_instance.out.port }} -{% endif %} +relayhost = [{{ postfix_instance.out.addr | ansible.utils.ipaddr }}]:{{ postfix_instance.out.port }} relay_domains = -{% if 'out' in group_names %} -smtp_tls_security_level = none -smtp_bind_address = 127.0.0.1 -{% else %} -smtp_tls_security_level = encrypt -smtp_tls_cert_file = $config_directory/ssl/{{ ansible_fqdn }}.pem -smtp_tls_key_file = $config_directory/ssl/{{ ansible_fqdn }}.key -smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache -smtp_tls_policy_maps = cdb:$config_directory/tls_policy -smtp_tls_fingerprint_digest = sha256 -{% endif %} -smtpd_tls_security_level = none - -# Turn off all TCP/IP listener ports except that dedicated to -# samhain(8), which sadly cannot use pickup through the sendmail binary. -master_service_disable = !127.0.0.1:16132.inet inet +smtp_tls_security_level = none +smtpd_tls_security_level = none -{% set multi_instance = False %} -{%- for g in postfix_instance.keys() | sort -%} - {%- if g in group_names -%} - {%- if not multi_instance -%} - {%- set multi_instance = True -%} -## Other postfix instances +{% set instances = postfix_instance.keys() | intersect(group_names) | list %} +{%- if instances | length > 0 -%} +# Other postfix instances multi_instance_wrapper = $command_directory/postmulti -p -- multi_instance_enable = yes -multi_instance_directories = - {%- endif %} /etc/postfix-{{ postfix_instance[g].name }} - {%- endif %} -{% endfor %} +multi_instance_directories ={% for i in instances | sort %} /etc/postfix-{{ postfix_instance[i].name }}{% endfor %} +{% endif %} # vim: set filetype=pfmain : diff --git a/roles/common/templates/etc/postfix/master.cf.j2 b/roles/common/templates/etc/postfix/master.cf.j2 new file mode 100644 index 0000000..3954085 --- /dev/null +++ b/roles/common/templates/etc/postfix/master.cf.j2 @@ -0,0 +1,114 @@ +######################################################################## +# Postfix master process configuration file. For details on the format +# of the file, see the master(5) manual page (command: "man 5 master"). +# +# {{ ansible_managed }} +# Do NOT edit this file directly! +# +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (yes) (never) (100) +# ========================================================================== + +{% if inst is not defined %} +[127.0.0.1]:16132 inet n - y - - smtpd +{% elif inst == 'MX' %} +smtpd pass - - y - - smtpd +smtp inet n - y - 1 postscreen +tlsproxy unix - - y - 0 tlsproxy +dnsblog unix - - y - 0 dnsblog +{% elif inst == 'MSA' %} +submission inet n - y - - smtpd +submissions inet n - y - - smtpd + -o smtpd_tls_wrappermode=yes +{% if groups.webmail | difference([inventory_hostname]) | length > 0 %} +[{{ postfix_instance.MSA.addr }}]:{{ postfix_instance.MSA.port }} inet n - y - - smtpd + -o broken_sasl_auth_clients=no + -o smtpd_tls_security_level=none + -o smtpd_sasl_security_options=noanonymous + -o smtpd_sasl_exceptions_networks= + -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128{{ ipsec_subnet is defined | ternary(','+ipsec_subnet, '') }} + -o smtpd_peername_lookup=no +{% endif %} +{% elif inst in ['IMAP', 'out', 'lists'] %} +[{{ postfix_instance[inst].addr }}]:{{ postfix_instance[inst].port }} inet n - y - - smtpd + -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128{{ ipsec_subnet is defined | ternary(','+ipsec_subnet, '') }} + -o smtpd_peername_lookup=no +{% endif %} +pickup unix n - y 60 1 pickup +cleanup unix n - y - 0 cleanup +qmgr unix n - n 300 1 qmgr +tlsmgr unix - - y 1000? 1 tlsmgr +rewrite unix - - y - - trivial-rewrite +bounce unix - - y - 0 bounce +defer unix - - y - 0 bounce +trace unix - - y - 0 bounce +verify unix - - y - 1 verify +flush unix n - y 1000? 0 flush +proxymap unix - - n - - proxymap +proxywrite unix - - n - 1 proxymap +smtp unix - - y - - smtp +# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 +{% if inst is defined and inst == 'MSA' %} +smtp_verify unix - - y - - smtp + -o smtp_helo_name=noreply.$mydomain + -o smtp_tls_security_level=may + -o smtp_tls_ciphers=medium + -o smtp_tls_protocols=!SSLv2,!SSLv3 + -o smtp_tls_note_starttls_offer=yes + -o smtp_tls_session_cache_database=lmdb:$data_directory/smtp_tls_session_cache + -o smtp_tls_fingerprint_digest=sha256 + -o smtp_tls_policy_maps=lmdb:$config_directory/smtp_tls_policy +{% endif %} +relay unix - - y - - smtp +showq unix n - y - - showq +error unix - - y - - error +retry unix - - y - - error +discard unix - - y - - discard +local unix - n n - - local +virtual unix - n n - - virtual +lmtp unix - - y - - lmtp +anvil unix - - y - 1 anvil +scache unix - - y - 1 scache +{% if inst is defined and inst == 'MSA' %} +policyd-spf unix - n n - 0 spawn + user=policyd-spf argv=/usr/bin/policyd-spf +{% endif %} +{% if inst is defined and inst == 'MX' %} +reserved-alias unix - n n - - pipe + flags=Rhu user=nobody argv=/usr/local/bin/reserved-alias.pl ${sender} ${original_recipient} @fripost.org +{% endif %} +{% if inst is defined and inst == 'lists' %} +sympa unix - n n - - pipe + flags=Rhu user=sympa argv=/usr/local/bin/sympa-queue ${user} +{% endif %} + +{% if inst is defined and inst == 'out' %} +# Client part (lmtp) - amavis +amavisfeed unix - - y - 5 lmtp + -o lmtp_destination_recipient_limit=1000 + -o lmtp_send_xforward_command=yes + -o lmtp_data_done_timeout=1200s + -o disable_dns_lookups=yes + +# Server part (smtpd) - amavis +[127.0.0.1]:10025 inet n - y - - smtpd + -o content_filter= + -o smtpd_delay_reject=no + -o smtpd_client_restrictions=permit_mynetworks,reject + -o smtpd_helo_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_relay_restrictions=permit_mynetworks,reject + -o smtpd_data_restrictions=reject_unauth_pipelining + -o smtpd_end_of_data_restrictions= + -o smtpd_restriction_classes= + -o mynetworks_style=host + -o smtpd_error_sleep_time=0 + -o smtpd_soft_error_limit=1001 + -o smtpd_hard_error_limit=1000 + -o smtpd_client_connection_count_limit=0 + -o smtpd_client_connection_rate_limit=0 + -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters + -o local_header_rewrite_clients= + -o smtpd_authorized_xforward_hosts=127.0.0.0/8 +{% endif %} diff --git a/roles/common/templates/etc/postfix/tls_policy.j2 b/roles/common/templates/etc/postfix/tls_policy.j2 deleted file mode 100644 index 5ff7d26..0000000 --- a/roles/common/templates/etc/postfix/tls_policy.j2 +++ /dev/null @@ -1,25 +0,0 @@ -# {{ ansible_managed }} -# /!\ WARNING: smtp_tls_fingerprint_digest MUST be sha256! - -{% if 'out' not in group_names %} -[outgoing.fripost.org]:{{ postfix_instance.out.port }} fingerprint ciphers=high protocols=TLSv1.2 -{% for h in groups.out | sort %} - match={{ lookup('pipe', 'openssl x509 -in certs/postfix/'+h+'.pem -noout -fingerprint -sha256 | cut -d= -f2') }} -{% endfor %} -{% endif %} - -{% if 'MX' in group_names %} -{% if 'IMAP' not in group_names %} -[mda.fripost.org]:{{ postfix_instance.IMAP.port }} fingerprint ciphers=high protocols=TLSv1.2 -{% for h in groups.IMAP | sort %} - match={{ lookup('pipe', 'openssl x509 -in certs/postfix/'+h+'.pem -noout -fingerprint -sha256 | cut -d= -f2') }} -{% endfor %} -{% endif %} - -{% if 'lists' not in group_names %} -[lists.fripost.org]:{{ postfix_instance.lists.port }} fingerprint ciphers=high protocols=TLSv1.2 -{% for h in groups.lists | sort %} - match={{ lookup('pipe', 'openssl x509 -in certs/postfix/'+h+'.pem -noout -fingerprint -sha256 | cut -d= -f2') }} -{% endfor %} -{% endif %} -{% endif %} diff --git a/roles/common/templates/etc/rsyslog.d/postfix.conf.j2 b/roles/common/templates/etc/rsyslog.d/postfix.conf.j2 index 5acb56d..52f9ea3 100644 --- a/roles/common/templates/etc/rsyslog.d/postfix.conf.j2 +++ b/roles/common/templates/etc/rsyslog.d/postfix.conf.j2 @@ -1,17 +1,17 @@ # Create an additional socket in postfix's chroot in order not to break # mail logging when rsyslog is restarted. If the directory is missing, # rsyslog will silently skip creating the socket. $AddUnixListenSocket /var/spool/postfix/dev/log {% for g in postfix_instance.keys() | sort %} {% if g in group_names %} $AddUnixListenSocket /var/spool/postfix-{{ postfix_instance[g].name }}/dev/log {% endif %} {% endfor %} {% if 'MSA' in group_names %} # User of our Authenticated SMTP server can choose the envelope from and From: # header of their choice. As the SASL username is not logged in the mail # header, we keep a mapping Postfix's message ID -> SASL username in a separate # log file that is only rotated monthly. -if $programname == 'postfix-msa' and $syslogfacility-text == 'mail' and $msg contains 'sasl_username=' then /var/log/mail.sasl +if $programname == 'postfix-{{ postfix_instance.MSA.name }}' and $syslogfacility-text == 'mail' and $msg contains 'sasl_username=' then /var/log/mail.sasl {% endif %} diff --git a/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 b/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 deleted file mode 100644 index 74364c9..0000000 --- a/roles/common/templates/etc/stunnel/bacula-fd.conf.j2 +++ /dev/null @@ -1,62 +0,0 @@ -; ************************************************************************** -; * Global options * -; ************************************************************************** - -; setuid()/setgid() to the specified user/group in daemon mode -setuid = stunnel4 -setgid = stunnel4 - -; PID is created inside the chroot jail -pid = /var/run/stunnel4/bacula-fd.pid - -; Only log messages at severity warning (4) and higher -debug = 4 - -; ************************************************************************** -; * Service defaults may also be specified in individual service sections * -; ************************************************************************** - -; Certificate/key is needed in server mode and optional in client mode -cert = /etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem -key = /etc/stunnel/certs/{{ inventory_hostname_short }}-fd.key - -; Some performance tunings -socket = l:TCP_NODELAY=1 -socket = r:TCP_NODELAY=1 - -; Prevent MITM attacks -verify = 4 - -; Disable support for insecure protocols -options = NO_SSLv2 -options = NO_SSLv3 -options = NO_TLSv1 -options = NO_TLSv1.1 - -; These options provide additional security at some performance degradation -options = SINGLE_ECDH_USE -options = SINGLE_DH_USE - -; Select permitted SSL ciphers -ciphers = EECDH+AES:EDH+AES:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1 - -; ************************************************************************** -; * Service definitions (remove all services for inetd mode) * -; ************************************************************************** - -[{{ inventory_hostname_short }}-fd] -client = no -accept = 9102 -connect = 9112 -CAfile = /etc/stunnel/certs/bacula-dirs.pem - -{% if 'bacula-sd' not in group_names %} -[{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd] -client = yes -accept = 127.0.0.1:9113 -connect = {{ groups['bacula-sd'][0] }}:9103 -delay = yes -CAfile = /etc/stunnel/certs/{{ hostvars[ groups['bacula-sd'][0] ].inventory_hostname_short }}-sd.pem -{% endif %} - -; vim:ft=dosini diff --git a/roles/common/templates/etc/stunnel/munin-node.conf.j2 b/roles/common/templates/etc/stunnel/munin-node.conf.j2 deleted file mode 100644 index de6c156..0000000 --- a/roles/common/templates/etc/stunnel/munin-node.conf.j2 +++ /dev/null @@ -1,53 +0,0 @@ -; ************************************************************************** -; * Global options * -; ************************************************************************** - -; setuid()/setgid() to the specified user/group in daemon mode -setuid = stunnel4 -setgid = stunnel4 - -; PID is created inside the chroot jail -pid = /var/run/stunnel4/munin-node.pid - -; Only log messages at severity warning (4) and higher -debug = 4 - -; ************************************************************************** -; * Service defaults may also be specified in individual service sections * -; ************************************************************************** - -; Certificate/key is needed in server mode and optional in client mode -cert = /etc/stunnel/certs/munin-{{ inventory_hostname_short }}.pem -key = /etc/stunnel/certs/munin-{{ inventory_hostname_short }}.key - -; Some performance tunings -socket = l:TCP_NODELAY=1 -socket = r:TCP_NODELAY=1 - -; Prevent MITM attacks -verify = 4 - -; Disable support for insecure protocols -options = NO_SSLv2 -options = NO_SSLv3 -options = NO_TLSv1 -options = NO_TLSv1.1 - -; These options provide additional security at some performance degradation -options = SINGLE_ECDH_USE -options = SINGLE_DH_USE - -; Select permitted SSL ciphers -ciphers = EECDH+AES:EDH+AES:!MEDIUM:!LOW:!EXP:!aNULL:!eNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1 - -; ************************************************************************** -; * Service definitions (remove all services for inetd mode) * -; ************************************************************************** - -[munin-node] -client = no -accept = 4949 -connect = 127.0.0.1:4994 -CAfile = /etc/stunnel/certs/munin-master.pem - -; vim:ft=dosini diff --git a/roles/common/templates/etc/systemd/resolved.conf.d/local.conf.j2 b/roles/common/templates/etc/systemd/resolved.conf.d/local.conf.j2 new file mode 100644 index 0000000..044170a --- /dev/null +++ b/roles/common/templates/etc/systemd/resolved.conf.d/local.conf.j2 @@ -0,0 +1,11 @@ +[Resolve] +LLMNR=no +{% if ansible_processor[1] is search('^(Genuine)?Intel.*') and not ansible_virtualization_role == 'guest' %} +DNS=127.0.0.1 +# Quad9 +FallbackDNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net +{% else %} +# Quad9 +DNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net +{% endif %} +Domains=fripost.org diff --git a/roles/common/templates/etc/systemd/timesyncd.conf.d/fripost.conf.j2 b/roles/common/templates/etc/systemd/timesyncd.conf.d/fripost.conf.j2 new file mode 100644 index 0000000..f578cd9 --- /dev/null +++ b/roles/common/templates/etc/systemd/timesyncd.conf.d/fripost.conf.j2 @@ -0,0 +1,9 @@ +[Time] +# Sychronize to our (stratum 2) NTP server, to ensure our network has a +# consistent time. +{%- set ntp = [] -%} +{%- for host in groups['NTP_master'] -%} +{%- set _ = ntp.append(ipsec[ hostvars[host].inventory_hostname_short ]) -%} +{%- endfor %} + +NTP={{ ntp | join(' ') }} diff --git a/roles/common/templates/etc/unbound/unbound.conf.j2 b/roles/common/templates/etc/unbound/unbound.conf.j2 new file mode 100644 index 0000000..e75e66f --- /dev/null +++ b/roles/common/templates/etc/unbound/unbound.conf.j2 @@ -0,0 +1,32 @@ +# Unbound configuration file for Debian. +# +# See the unbound.conf(5) man page. +# +# See /usr/share/doc/unbound/examples/unbound.conf for a commented +# reference config file. + +remote-control: + control-enable: no + +server: + interface: 127.0.0.1 + root-hints: "/usr/share/dns/root.hints" + hide-identity: yes + hide-version: yes + prefetch: yes + qname-minimisation: yes + rrset-roundrobin: yes + use-caps-for-id: yes + + # RFC 1918 + private-address: 10.0.0.0/8 + private-address: 172.16.0.0/12 + private-address: 192.168.0.0/16 + private-address: 169.254.0.0/16 + private-address: fd00::/8 + private-address: fe80::/10 + +# +# The following line includes additional configuration files from the +# /etc/unbound/unbound.conf.d directory. +include-toplevel: "/etc/unbound/unbound.conf.d/*.conf" |