[[!comment format=mdwn
 username="david"
 avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
 subject="giving up on Firewall persistence"
 date="2019-08-11T11:29:07Z"
 content="""
I ran out of time/motivation to do this \"right\", so I just hardcoded all the things, and made a new module called IPTables

[[!format haskell \"\"\"
module Propellor.Property.SiteSpecific.Tethera.IPTables (
  systemdUnits
  , rules
  ) where

import Propellor.Base
import qualified Propellor.Property.File as File


systemdUnits :: Property UnixLike  
systemdUnits = combineProperties \"systemd units for iptables\" $ props
                & unitFile \"iptables\"
                & unitFile \"ip6tables\"                
  where
    unitDir = \"/etc/systemd/system\"
    unitFile baseName = combineProperties (\"systemd units for \" ++ baseName) $ props
                & File.hasContent (unitDir ++ \"/\"++baseName++\".service\")
                [
                  \"[Unit]\"
                , \"Description=Packet Filtering Framework\"
                , \"DefaultDependencies=no\"
                , \"After=systemd-sysctl.service\"
                , \"Before=sysinit.target\"
                , \"[Service]\"
                , \"Type=oneshot\"
                , \"ExecStart=/sbin/\"++baseName++\"-restore -n /etc/iptables/\"++baseName++\".rules\"
                , \"ExecReload=/sbin/\"++baseName++\"-restore -n /etc/iptables/\"++baseName++\".rules\"
                , \"ExecStop=/usr/local/bin/flush-\"++baseName++\".sh\"
                , \"RemainAfterExit=yes\"
                , \"[Install]\"
                , \"WantedBy=multi-user.target\"
                ]
                & File.hasContent fipSh
                [
                  \"#!/bin/sh\"
                , baseName ++ \" -F INPUT\"
                , baseName ++ \" -F FORWARD\"
                , baseName ++ \" -F OUTPUT\"
                , baseName ++ \" -P INPUT ACCEPT\"
                , baseName ++ \" -P FORWARD ACCEPT\"
                , baseName ++ \" -P OUTPUT ACCEPT\"
                ]
                & File.mode fipSh 0o0755
      where
            fipSh = \"/usr/local/bin/flush-\"++baseName++\".sh\"


-- this currently makes the possibly bad assumption that the same rule
-- file will work for both v4 and v6
rules :: Property UnixLike
rules  = combineProperties \"systemd units for iptables\" $ props
         & ruleFile \"iptables\"
         & ruleFile \"ip6tables\"                
  where
    ruleDir = \"/etc/iptables\"
    ruleFile baseName = combineProperties (baseName ++ \" rules\") $ props
                        & File.hasContent (ruleDir ++ \"/\"++baseName++\".rules\")

                        [ \"*filter\"
                        , \":INPUT ACCEPT [0:0]\"
                        , \":FORWARD ACCEPT [0:0]\"
                        , \":OUTPUT ACCEPT [0:0]\"
                        , \"-A INPUT -m conntrack --ctstate INVALID -j DROP\"
                        , \"-A INPUT -i lo -j ACCEPT\"
                        , \"-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT\"
                        , \"-A INPUT -p icmp -j ACCEPT\"
                        , \"-6 -A INPUT -p ipv6-icmp -j ACCEPT\"
                        , \"-6 -A INPUT -m state --state NEW -m udp -p udp -s fe80::/10 --dport 546 -j ACCEPT\"
                        , \"-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT\"
                        , \"-A INPUT -j DROP\"
                        , \"-A FORWARD -j DROP\"
                        , \"-A OUTPUT -o lo -j ACCEPT\"
                        , \"-A OUTPUT -j ACCEPT\"
                        , \"COMMIT\"
                        ]
                        `requires` File.dirExists ruleDir
\"\"\"]]
"""]]
