From 90bec1e9593c7d0f99204d6a6ef8682672018ccb Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Thu, 30 Oct 2014 22:11:14 +0100 Subject: added firewall properties --- src/Propellor/Property/Firewall.hs | 79 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/Propellor/Property/Firewall.hs (limited to 'src/Propellor/Property/Firewall.hs') diff --git a/src/Propellor/Property/Firewall.hs b/src/Propellor/Property/Firewall.hs new file mode 100644 index 00000000..1e8eb815 --- /dev/null +++ b/src/Propellor/Property/Firewall.hs @@ -0,0 +1,79 @@ +-- |Properties for configuring firewall (iptables) rules +module Propellor.Property.Firewall where + +import Data.Monoid +import Data.Char +import Data.List + +import Propellor +import Utility.SafeCommand +import qualified Propellor.Property.Apt as Apt +import qualified Propellor.Property.Network as Network + +installed :: Property +installed = Apt.installed ["iptables"] + +addRule :: Rule -> Property +addRule rule = property ("adding firewall rule: " <> show rule) addIpTable + where + addIpTable = liftIO $ do + let r = toIpTable rule + exist <- boolSystem "/sbin/iptables" (chk r) + if exist then + return NoChange + else ifM (boolSystem "/sbin/iptables" (add r)) + ( return MadeChange , return FailedChange) + add params = (Param "-A") : params + chk params = (Param "-C") : params + +toIpTable :: Rule -> [CommandParam] +toIpTable rule = map Param ((show $ ruleChain rule) : + (toIpTableArg (ruleRules rule)) ++ [ "-j" , show $ ruleTarget rule ]) + +toIpTableArg :: Rules -> [String] +toIpTableArg NoRule = [] +toIpTableArg (Proto proto) = ["-p", map toLower $ show proto] +toIpTableArg (Port port) = ["--dport", show port] +toIpTableArg (PortRange (f,t)) = ["--dport", show f ++ ":" ++ show t] +toIpTableArg (IFace iface) = ["-i", show iface] +toIpTableArg (Ctstate states) = ["-m", "conntrack","--ctstate", concat $ intersperse "," (map show states)] +toIpTableArg (r :- r') = toIpTableArg r <> toIpTableArg r' + +data Rule = Rule { + ruleChain :: Chain + ,ruleTarget :: Target + ,ruleRules :: Rules + } deriving (Eq, Show, Read) + +data Chain = INPUT | OUTPUT | FORWARD + deriving (Eq,Show,Read) + +data Target = ACCEPT | REJECT | DROP | LOG + deriving (Eq,Show,Read) + +data Proto = TCP | UDP | ICMP + deriving (Eq,Show,Read) + +type Port = Int + +data ConnectionState = ESTABLISHED | RELATED | NEW | INVALID + deriving (Eq,Show,Read) + +data Rules = NoRule + | Proto Proto + -- ^There is actually some order dependency between proto and port so this should be a specific + -- data type with proto + ports + | Port Port + | PortRange (Port,Port) + | IFace Network.Interface + | Ctstate [ ConnectionState ] + | Rules :- Rules -- ^Combine two rules + deriving (Eq,Show,Read) + +infixl 0 :- + +instance Monoid Rules where + mempty = NoRule + mappend = (:-) + + -- cgit v1.2.3