diff --git a/iptables-helpers.cabal b/iptables-helpers.cabal
--- a/iptables-helpers.cabal
+++ b/iptables-helpers.cabal
@@ -1,5 +1,5 @@
 Name:                iptables-helpers
-Version:             0.3
+Version:             0.4
 Synopsis:            Static checking of iptables rules
 License:             BSD3
 License-file:        LICENSE
@@ -17,16 +17,16 @@
                     Iptables.Parser
                     Iptables.Print
                     Iptables.Types
-  
+
     Build-depends:
                     base >=4 && <5,
                     parsec >= 2.1,
                     mtl >= 1.1,
                     safe >= 0.3,
                     containers >= 0.3 && < 0.4
-  
-  -- Other-modules:       
-  
-    Hs-Source-Dirs: src  
+
+  -- Other-modules:
+
+    Hs-Source-Dirs: src
 
     Ghc-options:    -Wall -fno-warn-unused-do-bind
diff --git a/src/Iptables.hs b/src/Iptables.hs
--- a/src/Iptables.hs
+++ b/src/Iptables.hs
@@ -165,7 +165,7 @@
     where
     scanRulesForLinks :: [Rule] -> [String]
     scanRulesForLinks [] = []
-    scanRulesForLinks (Rule _ (TUChain chainName) : rs') = chainName : scanRulesForLinks rs'
+    scanRulesForLinks (Rule _ _ (TUChain chainName) : rs') = chainName : scanRulesForLinks rs'
     scanRulesForLinks (_ : rs') = scanRulesForLinks rs'
 
 getChainByName :: String -> [Chain] -> Maybe Chain
@@ -175,14 +175,14 @@
 
 hasChainSNatTarget :: [Rule] -> Bool
 hasChainSNatTarget [] = False
-hasChainSNatTarget (Rule _ (TMasquerade _ _) : _) = True
-hasChainSNatTarget (Rule _ (TSNat _ _ _) : _) = True
+hasChainSNatTarget (Rule _ _ (TMasquerade _ _) : _) = True
+hasChainSNatTarget (Rule _ _ (TSNat _ _ _) : _) = True
 hasChainSNatTarget (_ : xs) = hasChainSNatTarget xs
 
 hasChainDNatTarget :: [Rule] -> Bool
 hasChainDNatTarget [] = False
-hasChainDNatTarget (Rule _ (TDNat _ _ _) : _) = True
-hasChainDNatTarget (Rule _ (TRedirect _ _) : _) = True
+hasChainDNatTarget (Rule _ _ (TDNat _ _ _) : _) = True
+hasChainDNatTarget (Rule _ _ (TRedirect _ _) : _) = True
 hasChainDNatTarget (_ : xs) = hasChainDNatTarget xs
 
 isFilterBuiltinChain :: String -> Bool
diff --git a/src/Iptables/Parser.hs b/src/Iptables/Parser.hs
--- a/src/Iptables/Parser.hs
+++ b/src/Iptables/Parser.hs
@@ -78,17 +78,25 @@
             a -> unexpected $ "unknown policy " ++ a
         spaces
         char '['
-        c1 <- many1 digit
+        packets <- fmap read $ many1 digit
         char ':'
-        c2 <- many1 digit
+        bytes <- fmap read $ many1 digit
         char ']'
         spaces
         st <- getState
         -- TODO: parse counters properly
-        setState $ Chain chainName chainPolicy (Counters (read c1) (read c2)) [] : st
+        setState $ Chain chainName chainPolicy (Counters packets bytes) [] : st
 
     rule :: GenParser Char [Chain] ()
     rule = do
+        counters <- option (Counters 0 0) $ do
+            char '['
+            packets <- fmap read $ many1 digit
+            char ':'
+            bytes <- fmap read $ many1 digit
+            char ']'
+            char ' '
+            return $ Counters packets bytes
         string "-A"
         spaces
         chainName <- many1 (alphaNum <|> char '-')
@@ -103,7 +111,7 @@
         many (noneOf "\n")
         spaces
         st <- getState
-        let rule_ = Rule matches target
+        let rule_ = Rule counters matches target
         let newState = addRuleToChain st chainName rule_
         setState newState
 
diff --git a/src/Iptables/Print.hs b/src/Iptables/Print.hs
--- a/src/Iptables/Print.hs
+++ b/src/Iptables/Print.hs
@@ -44,13 +44,13 @@
 printCounters :: Counters -> String
 printCounters (Counters a b) = "[" ++ show a ++ ":" ++ show b ++ "]"
 
-printRuleCanonical :: Rule -> String
-printRuleCanonical (Rule ruleOpts target) =
+printRuleForRun :: Rule -> String
+printRuleForRun (Rule _ ruleOpts target) =
     unwords (map printOption ruleOpts) ++ " "
     ++ printTarget target
 
 printRule :: (Rule, Int) -> String
-printRule (Rule ruleOpts target, lineNum) =
+printRule (Rule _ ruleOpts target, lineNum) =
     show lineNum ++ ". "
     ++ unwords (map printOption ruleOpts) ++ " "
     ++ printTarget target
diff --git a/src/Iptables/Types.hs b/src/Iptables/Types.hs
--- a/src/Iptables/Types.hs
+++ b/src/Iptables/Types.hs
@@ -4,8 +4,6 @@
 import Data.Set
 import Data.Word
 
--- Типы данных составлены по мануалу iptables
-
 data Iptables = Iptables { tFilter :: [Chain]
                          , tNat :: [Chain]
                          , tMangle :: [Chain]
@@ -18,20 +16,32 @@
                    , cCounters :: Counters
                    , cRules :: [Rule]
                    }
-                   deriving (Show, Eq)
+                   deriving (Show)
 
+-- | Discard counters
+instance Eq Chain where
+    (==) (Chain name1 policy1 _ rules1) (Chain name2 policy2 _ rules2) =
+        (name1 == name2) && (policy1 == policy2) && (rules1 == rules2)
+
 data Policy = ACCEPT
             | DROP
             | PUNDEFINED
             deriving (Show, Eq)
 
-data Counters = Counters Int Int
-              deriving (Show, Eq)
+data Counters = Counters { cPackets :: Integer
+                         , cBytes :: Integer
+                         }
+                         deriving (Show, Eq)
 
-data Rule = Rule { rOptions :: [RuleOption]
+data Rule = Rule { rCounters :: Counters
+                 , rOptions :: [RuleOption]
                  , rTarget :: RuleTarget
                  }
-                 deriving (Show, Eq)
+                 deriving (Show)
+
+-- | Discard counters
+instance Eq Rule where
+    (==) (Rule _ opts1 tar1) (Rule _ opts2 tar2) = (opts1 == opts2) && (tar1 == tar2)
 
 data RuleTarget = TAccept
                 | TDrop
