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.4.1
+Version:             0.4.2
 Synopsis:            Static checking of iptables rules
 License:             BSD3
 License-file:        LICENSE
diff --git a/src/Iptables/Parser.hs b/src/Iptables/Parser.hs
--- a/src/Iptables/Parser.hs
+++ b/src/Iptables/Parser.hs
@@ -68,7 +68,7 @@
     chainDescr :: GenParser Char [Chain] ()
     chainDescr = do
         char ':'
-        chainName <- many1 (alphaNum <|> char '-')
+        chainName <- chainNameParser
         spaces
         chainPolicyRaw <- many1 (letter <|> char '-')
         chainPolicy <- case chainPolicyRaw of
@@ -99,7 +99,7 @@
             return $ Counters packets bytes
         string "-A"
         spaces
-        chainName <- many1 (alphaNum <|> char '-')
+        chainName <- chainNameParser
         spaces
         matches <- many ruleOption
         string "-j"
@@ -280,14 +280,14 @@
             return $ TDNat addr rand persist
 
         rUChain = try $ do
-            chainName <- many1 (alphaNum <|> char '-')
+            chainName <- chainNameParser
             chains_ <- getState
             when (not $ chainName `elem` map cName chains_) $
                 fail $ chainName ++ " is not name of real chain"
             return $ TUChain chainName
 
         rUnknown = do
-            targetName <- many1 (alphaNum <|> char '-')
+            targetName <- chainNameParser
             opts <- option [] (char ' ' >> fmap words (many $ noneOf "\n"))
             return $ TUnknown targetName opts
 
@@ -424,3 +424,6 @@
         "icmp-admin-prohibited" -> return RTAdminProhibited
         "tcp-reset" -> return RTTcpReset
         a -> fail $ "Unknown reject type: " ++ a
+
+chainNameParser :: GenParser Char st String
+chainNameParser = many1 (alphaNum <|> char '-' <|> char '_')
