iptables -A
appends rules at the end of the ruleset whereas iptables -I
inserts the rule at a specific position in the ruleset as you've pointed out.
Looking at the man entry for iptables shows this:
-I, --insert chain [rulenum] rule-specification Insert one or more rules in the selected chain as the given rule number. So, if the rule
number is 1, the rule or rules are inserted at the head of the chain.
This is also the default if no rule number is specified.
And here is the reason why -I
worked for you and -A
doesn't. If you don't supply any rulenum, your rule is inserted at the very first position. That means in your case, that somewhere in your ruleset there must be a rule that's forbidding DNS packets (maybe a rule that forbids UDP generally?) because iptables processes all rules from the first to the last, applies the first matching and stops.
Btw, that's also the reason why you should put the rules that are intended to match most packets at the top: if you put the most used rule at the and, the packet is checked against each rule which may consume a lot of ressources.
And for the usage: You can savely use -A
when you want to append a rule at the end or when it doesn't matter where your rule will be. If you want your rule at a specific position, use -I
like this for example: iptables -I INPUT 6 -p tcp -j DROP
(this will add a DROP statement for all tcp packets addressed to the host itself on position 6 in the INPUT ruleset.)