From 4442053d0e41838af0670f38e86e1bd7aa426e3a Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 19 Mar 2015 23:04:35 +0100 Subject: cd: initial commit --- cd.nix | 102 ++++++++ modules/base-cac-CentOS-7-64bit.nix | 27 ++ modules/exim-cd.nix | 473 ++++++++++++++++++++++++++++++++++++ modules/iptables-cd.nix | 75 ++++++ modules/networking-cd.nix | 14 ++ 5 files changed, 691 insertions(+) create mode 100644 cd.nix create mode 100644 modules/base-cac-CentOS-7-64bit.nix create mode 100644 modules/exim-cd.nix create mode 100644 modules/iptables-cd.nix create mode 100644 modules/networking-cd.nix diff --git a/cd.nix b/cd.nix new file mode 100644 index 000000000..47bd4c869 --- /dev/null +++ b/cd.nix @@ -0,0 +1,102 @@ +{ config, pkgs, ... }: + +{ + imports = + [ + + ./modules/base-cac-CentOS-7-64bit.nix + ./modules/exim-cd.nix + #./modules/ejabberd-cd.nix # XXX echtes modul + ./modules/iptables-cd.nix + ./modules/networking-cd.nix + ./modules/retiolum.nix + ]; + + # "Developer 2" plan has two vCPUs. + nix.maxJobs = 2; + + + environment.systemPackages = with pkgs; [ + htop + iftop + iotop + nethogs + rxvt_unicode.terminfo + tcpdump + ]; + + security.rtkit.enable = false; + + services.cron.enable = false; + + #services.ejabberd-cd = { + # enable = true; + # #virtualHosts = ''"jabber.viljetic.de", "viljetic.de"''; + #}; + + services.journald.extraConfig = '' + SystemMaxUse=1G + RuntimeMaxUse=128M + ''; + + services.ntp.enable = false; + + services.openssh = { + enable = true; + hostKeys = [ + # XXX bits here make no science + { bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; } + ]; + permitRootLogin = "yes"; + }; + + services.retiolum = { + enable = true; + hosts = ./hosts; + privateKeyFile = "/etc/nixos/secrets/cd.retiolum.rsa_key.priv"; + connectTo = [ + "fastpoke" + "pigstarter" + "ire" + ]; + }; + + sound.enable = false; + + # TODO base + time.timeZone = "UTC"; + + # TODO replace by ./modules/cd-users.nix + users.extraGroups = { + + # ● systemd-tmpfiles-setup.service - Create Volatile Files and Directories + # Loaded: loaded (/nix/store/2l33gg7nmncqkpysq9f5fxyhlw6ncm2j-systemd-217/example/systemd/system/systemd-tmpfiles-setup.service) + # Active: failed (Result: exit-code) since Mon 2015-03-16 10:29:18 UTC; 4s ago + # Docs: man:tmpfiles.d(5) + # man:systemd-tmpfiles(8) + # Process: 19272 ExecStart=/nix/store/2l33gg7nmncqkpysq9f5fxyhlw6ncm2j-systemd-217/bin/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev (code=exited, status=1/FAILURE) + # Main PID: 19272 (code=exited, status=1/FAILURE) + # + # Mar 16 10:29:17 cd systemd-tmpfiles[19272]: [/usr/lib/tmpfiles.d/legacy.conf:26] Unknown group 'lock'. + # Mar 16 10:29:18 cd systemd-tmpfiles[19272]: Two or more conflicting lines for /var/log/journal configured, ignoring. + # Mar 16 10:29:18 cd systemd-tmpfiles[19272]: Two or more conflicting lines for /var/log/journal/7b35116927d74ea58785e00b47ac0f0d configured, ignoring. + # Mar 16 10:29:18 cd systemd[1]: systemd-tmpfiles-setup.service: main process exited, code=exited, status=1/FAILURE + # Mar 16 10:29:18 cd systemd[1]: Failed to start Create Volatile Files and Directories. + # Mar 16 10:29:18 cd systemd[1]: Unit systemd-tmpfiles-setup.service entered failed state. + # Mar 16 10:29:18 cd systemd[1]: systemd-tmpfiles-setup.service failed. + # warning: error(s) occured while switching to the new configuration + lock.gid = 10001; + + }; + users.extraUsers = + { + root = { + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEieAihh+o208aeCA14fAtjzyZN/nrpOJt2vZ5VYZp69 deploy@wu" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDYv5OkVrnerkzJwgi7ol7HzcWJf4oWCJTX84trFX5vgJXu1zMvSe+koY8xpnMOd7WHF2wgsjjrFlMuixTrfMPc/OjvG2N1TlnvzlFD8ivTW/AJzDwNxT//niqAYAZ9kmb8e/zE/SyNHSKZcyEKGiiW2+YW9wWHPYRP/XiNEjLP3BeTGScMwWr001V/8m7ne4SGHrE1FbHbHqaBXgqUFgnvzMY3CsfDafODZlj5xSMNGHyLGNNKvu3YR1crcAjbQrBXBdwaArThFxp+e2uWrnffshlks6WtRyR1AFVjc/gxEG74Axq1AHY6EJm2Fw/JdFNiYQ7yyQZHS9bZJYjgnWF tv@nomic" + ]; + }; + }; + users.mutableUsers = false; + +} diff --git a/modules/base-cac-CentOS-7-64bit.nix b/modules/base-cac-CentOS-7-64bit.nix new file mode 100644 index 000000000..42ab481b3 --- /dev/null +++ b/modules/base-cac-CentOS-7-64bit.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: + +{ + boot.loader.grub.device = "/dev/sda"; + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + + boot.initrd.availableKernelModules = [ + "ata_piix" + "vmw_pvscsi" + ]; + + fileSystems."/" = { + device = "/dev/centos/root"; + fsType = "xfs"; + }; + + fileSystems."/boot" = { + device = "/dev/sda1"; + fsType = "xfs"; + }; + + swapDevices = [ + { device = "/dev/centos/swap"; } + ]; +} + diff --git a/modules/exim-cd.nix b/modules/exim-cd.nix new file mode 100644 index 000000000..b28f39437 --- /dev/null +++ b/modules/exim-cd.nix @@ -0,0 +1,473 @@ +{ config, pkgs, ... }: + +let + inherit (builtins) toFile; + inherit (pkgs.lib.attrsets) mapAttrs; + inherit (pkgs.lib.strings) concatMapStringsSep; +in + +{ + services.exim = + let + retiolumHostname = "${config.networking.hostName}.retiolum"; + + internet-aliases = [ + { from = "tomislav@viljetic.de"; to = "tv@wu.retiolum"; } + + # (mindestens) lisp-stammtisch und elli haben die: + { from = "tv@viljetic.de"; to = "tv@wu.retiolum"; } + + { from = "tv@destroy.dyn.shackspace.de"; to = "tv@wu.retiolum"; } + + { from = "mirko@viljetic.de"; to = "mv@cd.retiolum"; } + + # TODO killme (wo wird die benutzt?) + { from = "tv@cd.retiolum"; to = "tv@wu.retiolum"; } + + { from = "postmaster@krebsco.de"; to = "tv@wu.retiolum"; } + ]; + + system-aliases = [ + { from = "mailer-daemon"; to = "postmaster"; } + { from = "postmaster"; to = "root"; } + { from = "nobody"; to = "root"; } + { from = "hostmaster"; to = "root"; } + { from = "usenet"; to = "root"; } + { from = "news"; to = "root"; } + { from = "webmaster"; to = "root"; } + { from = "www"; to = "root"; } + { from = "ftp"; to = "root"; } + { from = "abuse"; to = "root"; } + { from = "noc"; to = "root"; } + { from = "security"; to = "root"; } + { from = "root"; to = "tv"; } + ]; + + to-lsearch = concatMapStringsSep "\n" ({ from, to }: "${from}: ${to}"); + lsearch = + mapAttrs (name: set: toFile name (to-lsearch set)) { + inherit internet-aliases; + inherit system-aliases; + }; + in + { + enable = true; + config = + '' + primary_hostname = ${retiolumHostname} + + # HOST_REDIR contains the real destinations for "local_domains". + #HOST_REDIR = /etc/exim4/host_redirect + + + # Domains not listed in local_domains need to be deliverable remotely. + # XXX We abuse local_domains to mean "domains, we're the gateway for". + domainlist local_domains = @ : localhost + #: viljetic.de : SHACK_REDIR_HOSTNAME + domainlist relay_to_domains = + hostlist relay_from_hosts = <; 127.0.0.1 ; ::1 ; 10.243.13.37 + + acl_smtp_rcpt = acl_check_rcpt + acl_smtp_data = acl_check_data + + # av_scanner = clamd:/tmp/clamd + # spamd_address = 127.0.0.1 783 + + # tls_advertise_hosts = * + # tls_certificate = /etc/ssl/exim.crt + # tls_privatekey = /etc/ssl/exim.pem + # (debian) tls_verify_certificates (to check client certs) + + # daemon_smtp_ports = 25 : 465 : 587 + # tls_on_connect_ports = 465 + + # qualify_domain defaults to primary_hostname + # qualify_recipient defaults to qualify_domain + + # allow_domain_literals + + never_users = root + + host_lookup = * + + # ident callbacks for all incoming SMTP calls + rfc1413_hosts = * + rfc1413_query_timeout = 5s + + # sender_unqualified_hosts = + # recipient_unqualified_hosts = + + # percent_hack_domains = + + # arch & debian + #ignore_bounce_errors_after = 2d + #timeout_frozen_after = 7d + # debian + #smtp_banner = $smtp_active_hostname ESMTP Exim $version_number $tod_full + #freeze_tell = postmaster + #trusted_users = uucp + # arch + #split_spool_directory = true + + log_selector = -queue_run +address_rewrite +all_parents +queue_time + log_file_path = syslog + syslog_timestamp = false + syslog_duplication = false + + begin acl + + acl_check_rcpt: + # Accept if the source is local SMTP (i.e. not over TCP/IP). + # We do this by testing for an empty sending host field. + accept hosts = : + # arch & debian: + control = dkim_disable_verify + + deny message = Restricted characters in address + domains = +local_domains + local_parts = ^[.] : ^.*[@%!/|] + + deny message = Restricted characters in address + domains = !+local_domains + local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ + + accept local_parts = postmaster + domains = +local_domains + + ## feature RETIOLUM_MAIL + #accept + # hosts = *.retiolum + # domains = *.retiolum + # control = dkim_disable_verify + + #require verify = sender + + accept hosts = +relay_from_hosts + control = submission + # debian: control = submission/sender_retain + # arch & debian: + control = dkim_disable_verify + + accept authenticated = * + control = submission + control = dkim_disable_verify + + accept message = relay not permitted 2 + recipients = lsearch;${lsearch.internet-aliases} + + require message = relay not permitted + domains = +local_domains : +relay_to_domains + + require + message = unknown user + verify = recipient/callout + + # deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text + # dnslists = black.list.example + # + # warn dnslists = black.list.example + # add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain + # log_message = found in $dnslist_domain + + # Client SMTP Authorization (csa) checks on the sending host. + # Such checks do DNS lookups for special SRV records. + # require verify = csa + + accept + + + acl_check_data: + # see av_scanner + #deny malware = * + # message = This message contains a virus ($malware_name). + + # Add headers to a message if it is judged to be spam. Before enabling this, + # you must install SpamAssassin. You may also need to set the spamd_address + # option above. + # + # warn spam = nobody + # add_header = X-Spam_score: $spam_score\n\ + # X-Spam_score_int: $spam_score_int\n\ + # X-Spam_bar: $spam_bar\n\ + # X-Spam_report: $spam_report + + # feature HELO_REWRITE + # XXX note that the public ip (162.219.5.183) resolves to viljetic.de + warn + sender_domains = viljetic.de : shackspace.de + set acl_m_special_dom = $sender_address_domain + + accept + + + begin routers + + # feature RETIOLUM_MAIL + retiolum: + debug_print = "R: retiolum for $local_part@$domain" + driver = manualroute + domains = ! ${retiolumHostname} : *.retiolum + transport = retiolum_smtp + route_list = ^.* $0 byname + no_more + + internet_aliases: + debug_print = "R: internet_aliases for $local_part@$domain" + driver = redirect + data = ''${lookup{$local_part@$domain}lsearch{${lsearch.internet-aliases}}} + + dnslookup: + debug_print = "R: dnslookup for $local_part@$domain" + driver = dnslookup + domains = ! +local_domains + transport = remote_smtp + ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 + # if ipv6-enabled then instead use: + # ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1 + + # (debian) same_domain_copy_routing = yes + # (debian) ignore private rfc1918 and APIPA addresses + # (debian) ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 : 192.168.0.0/16 :\ + # 172.16.0.0/12 : 10.0.0.0/8 : 169.254.0.0/16 :\ + # 255.255.255.255 + + # Fail and bounce if the router does not find the domain in the DNS. + # I.e. no more routers are tried. + # There are a few cases where a dnslookup router will decline to accept an + # address; if such a router is expected to handle "all remaining non-local + # domains", then it is important to set no_more. + no_more + + # XXX this is only used because these "well known aliases" goto tv@cd.retiolum + # TODO bounce everything, there is no @cd.retiolum + system_aliases: + debug_print = "R: system_aliases for $local_part@$domain" + driver = redirect + data = ''${lookup{$local_part}lsearch{${lsearch.system-aliases}}} + + # TODO this is only b/c mv here... send mv's mails somewhere else... + local_user: + debug_print = "R: local_user for $local_part@$domain" + driver = accept + check_local_user + # local_part_suffix = +* : -* + # local_part_suffix_optional + transport = home_maildir + cannot_route_message = Unknown user + + begin transports + + retiolum_smtp: + driver = smtp + retry_include_ip_address = false + # serialize_hosts = TODO-all-slow-hosts + + remote_smtp: + driver = smtp + # debian has also stuff for tls, headers_rewrite and more here + + # feature HELO_REWRITE + # XXX note that the public ip (162.219.5.183) resolves to viljetic.de + helo_data = ''${if eq{$acl_m_special_dom}{} \ + {$primary_hostname} \ + {$acl_m_special_dom} } + + home_maildir: + driver = appendfile + maildir_format + maildir_use_size_file + directory = $home/Maildir + directory_mode = 0700 + delivery_date_add + envelope_to_add + return_path_add + + begin retry + *.retiolum * F,42d,1m + * * F,2h,15m; G,16h,1h,1.5; F,4d,6h + + begin rewrite + begin authenticators + ''; + + + # group = mail + # mode = 0660 + + + #address_pipe: + # driver = pipe + # return_output + # + #address_file: + # driver = appendfile + # delivery_date_add + # envelope_to_add + # return_path_add + # + #address_reply: + # driver = autoreply + + + #maildrop_pipe: + # debug_print = "T: maildrop_pipe for $local_part@$domain" + # driver = pipe + # path = "/bin:/usr/bin:/usr/local/bin" + # command = "/usr/bin/maildrop" + # return_path_add + # delivery_date_add + # envelope_to_add + + + + + + ##begin retry + # Address or Domain Error Retries + + # Our host_redirect destinations might be offline a lot. + # TODO define fallback destinations(?) + #lsearch;${lsearch.internet-aliases} * F,42d,1m + + + ## begin rewrite + + # just in case (shackspace.de should already do this) + #tv@shackspace.de tv@SHACK_REDIR_HOSTNAME T + + + ## begin authenticators + #PLAIN: + # driver = plaintext + # server_set_id = $auth2 + # server_prompts = : + # server_condition = Authentication is not yet configured + # server_advertise_condition = ''${if def:tls_in_cipher } + + #LOGIN: + # driver = plaintext + # server_set_id = $auth1 + # server_prompts = <| Username: | Password: + # server_condition = Authentication is not yet configured + # server_advertise_condition = ''${if def:tls_in_cipher } + + + + }; + +} + +# config = '' +# primary_hostname = ${retiolumHostname} +# domainlist local_domains = @ : localhost +# domainlist relay_to_domains = *.retiolum +# hostlist relay_from_hosts = <; 127.0.0.1 ; ::1 +# +# acl_smtp_rcpt = acl_check_rcpt +# acl_smtp_data = acl_check_data +# +# host_lookup = * +# rfc1413_hosts = * +# rfc1413_query_timeout = 5s +# +# log_file_path = syslog +# syslog_timestamp = false +# syslog_duplication = false +# +# begin acl +# +# acl_check_rcpt: +# accept hosts = : +# control = dkim_disable_verify +# +# deny message = Restricted characters in address +# domains = +local_domains +# local_parts = ^[.] : ^.*[@%!/|] +# +# deny message = Restricted characters in address +# domains = !+local_domains +# local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ +# +# accept local_parts = postmaster +# domains = +local_domains +# +# #accept +# # hosts = *.retiolum +# # domains = *.retiolum +# # control = dkim_disable_verify +# +# #require verify = sender +# +# accept hosts = +relay_from_hosts +# control = submission +# control = dkim_disable_verify +# +# accept authenticated = * +# control = submission +# control = dkim_disable_verify +# +# require message = relay not permitted +# domains = +local_domains : +relay_to_domains +# +# require verify = recipient +# +# accept +# +# +# acl_check_data: +# accept +# +# +# begin routers +# +# retiolum: +# driver = manualroute +# domains = ! ${retiolumHostname} : *.retiolum +# transport = remote_smtp +# route_list = ^.* $0 byname +# no_more +# +# nonlocal: +# debug_print = "R: nonlocal for $local_part@$domain" +# driver = redirect +# domains = ! +local_domains +# allow_fail +# data = :fail: Mailing to remote domains not supported +# no_more +# +# local_user: +# # debug_print = "R: local_user for $local_part@$domain" +# driver = accept +# check_local_user +# # local_part_suffix = +* : -* +# # local_part_suffix_optional +# transport = home_maildir +# cannot_route_message = Unknown user +# +# +# begin transports +# +# remote_smtp: +# driver = smtp +# +# home_maildir: +# driver = appendfile +# maildir_format +# directory = $home/Maildir +# directory_mode = 0700 +# delivery_date_add +# envelope_to_add +# return_path_add +# # group = mail +# # mode = 0660 +# +# begin retry +# *.retiolum * F,42d,1m +# * * F,2h,15m; G,16h,1h,1.5; F,4d,6h +# +# begin rewrite +# +# begin authenticators +# ''; +# }; +#} diff --git a/modules/iptables-cd.nix b/modules/iptables-cd.nix new file mode 100644 index 000000000..70736e49d --- /dev/null +++ b/modules/iptables-cd.nix @@ -0,0 +1,75 @@ +{ config, pkgs, ... }: + +{ + # + # iptables + # + networking.firewall.enable = false; + system.activationScripts.iptables = + let + log = false; + when = c: f: if c then f else ""; + in + '' + ip4tables() { ${pkgs.iptables}/sbin/iptables "$@"; } + ip6tables() { ${pkgs.iptables}/sbin/ip6tables "$@"; } + ipXtables() { ip4tables "$@" && ip6tables "$@"; } + + # XXX This fails with the original CAC CentOS 7 kernel. + if ipXtables -vL >/dev/null; then + + # + # nat + # + + # reset tables + ipXtables -t nat -F + ipXtables -t nat -X + + # + ipXtables -t nat -A PREROUTING -j REDIRECT ! -i retiolum -p tcp --dport ssh --to-ports 0 + ipXtables -t nat -A PREROUTING -j REDIRECT -p tcp --dport 11423 --to-ports ssh + + # + # filter + # + + # reset tables + ipXtables -P INPUT DROP + ipXtables -P FORWARD DROP + ipXtables -F + ipXtables -X + + # create custom chains + ipXtables -N Retiolum + + # INPUT + ipXtables -A INPUT -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED + ipXtables -A INPUT -j ACCEPT -i lo + ipXtables -A INPUT -j ACCEPT -p tcp --dport ssh -m conntrack --ctstate NEW + #ipXtables -A INPUT -j ACCEPT -p tcp --dport http -m conntrack --ctstate NEW + ipXtables -A INPUT -j ACCEPT -p tcp --dport tinc -m conntrack --ctstate NEW + ipXtables -A INPUT -j ACCEPT -p tcp --dport smtp -m conntrack --ctstate NEW + #ipXtables -A INPUT -j ACCEPT -p tcp --dport xmpp-client -m conntrack --ctstate NEW + #ipXtables -A INPUT -j ACCEPT -p tcp --dport xmpp-server -m conntrack --ctstate NEW + + ipXtables -A INPUT -j Retiolum -i retiolum + ${when log "ipXtables -A INPUT -j LOG --log-level info --log-prefix 'INPUT DROP '"} + + # FORWARD + ${when log "ipXtables -A FORWARD -j LOG --log-level info --log-prefix 'FORWARD DROP '"} + + # Retiolum + ip4tables -A Retiolum -j ACCEPT -p icmp --icmp-type echo-request + ip6tables -A Retiolum -j ACCEPT -p ipv6-icmp -m icmp6 --icmpv6-type echo-request + + + ${when log "ipXtables -A Retiolum -j LOG --log-level info --log-prefix 'REJECT '"} + ipXtables -A Retiolum -j REJECT -p tcp --reject-with tcp-reset + ip4tables -A Retiolum -j REJECT -p udp --reject-with icmp-port-unreachable + ip4tables -A Retiolum -j REJECT --reject-with icmp-proto-unreachable + ip6tables -A Retiolum -j REJECT -p udp --reject-with icmp6-port-unreachable + ip6tables -A Retiolum -j REJECT + fi + ''; +} diff --git a/modules/networking-cd.nix b/modules/networking-cd.nix new file mode 100644 index 000000000..215e20829 --- /dev/null +++ b/modules/networking-cd.nix @@ -0,0 +1,14 @@ +{...}: +{ + networking.hostName = "cd"; + networking.interfaces.enp2s1.ip4 = [ + { + address = "162.219.7.216"; + prefixLength = 24; + } + ]; + networking.defaultGateway = "162.219.7.1"; + networking.nameservers = [ + "8.8.8.8" + ]; +} -- cgit v1.2.3