Why can't I use the REJECT policy on my iptables OUTPUT chain?


Solution 1

REJECT is a target extension, while a chain policy must be a target. The man page says that (although it's not really clear), but some of what it says is flat wrong.

The policy can only be ACCEPT or DROP on built-in chains. If you want the effect of rejecting all the packets that don't match the previous rules, just make sure the last rule matches everything and adds a rule with a REJECT target extension. In other words, after adding all relevant rules, do iptables -t filter -A OUTPUT -j REJECT.

See the "what are the possible chain policies" thread on the netfilter list for more details.

Solution 2

I couldn't find it documented, but a reference here indicates that the only allowed policies are ACCEPTor DROP. This is confirmed by looking at the source of libiptc (which is responsible for manipulating the rules) around line 2429, where the code has

2429         if (strcmp(policy, LABEL_ACCEPT) == 0)
2430                 c->verdict = -NF_ACCEPT - 1;
2431         else if (strcmp(policy, LABEL_DROP) == 0)
2432                 c->verdict = -NF_DROP - 1;
2433         else {
2434                 errno = EINVAL;
2435                 return 0;
2436         }

The original thread suggests the best thing to do is add REJECT at the end of the chain which should be iptables -A OUTPUT -j REJECT.

Note that the code just before this is:

2423         if (!iptcc_is_builtin(c)) {
2424                 DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain);
2425                 errno = ENOENT;
2426                 return 0;
2427         }

So you can't set the policy on a User Defined chain at all.

Solution 3

REJECT on OUTPUT makes no sense; a REJECT will return an ICMP packet which would need to traverse a network.

Add a new -j LOG as your last rule (therefore before the DROP policy) to see what gets that far in the OUTPUT chain.

ND Geek
Author by

ND Geek

I support library software in the Hesburgh Libraries, mostly writing automation scripts. In my spare time, I enjoy video games, board games, playing and watching baseball and hockey, watching college football, and teaching my kids to enjoy as many of these activities as I can.

Updated on June 28, 2022


  • ND Geek
    ND Geek less than a minute

    I currently have my OUTPUT chain set to DROP. I'd like to change it to REJECT, so that I have a clue that it's my firewall stopping me from getting somewhere rather than a problem with whatever service I'm attempting to access (immediate reject instead of timing out). However, iptables doesn't seem to care for this. If I manually edit my saved rules file and try to restore it, I get iptables-restore v1.4.15: Can't set policy 'REJECT' on 'OUTPUT' line 22: Bad policy name and it refuses to load the rules. If I attempt to set this manually (iptables -P OUTPUT REJECT), I get iptables: Bad policy name. Run 'dmesg' for more information. but there's no output in dmesg.

    I've confirmed the appropriate rule is compiled into the kernel and I've rebooted to ensure it's loaded:

    # CONFIG_IP_NF_MATCH_TTL is not set

    (Asterisks added to highlight applicable rule)

    Everything I can find states that REJECT is a valid policy/target (in general), but I can't find anything that says it's not valid for the INPUT, FORWARD, or OUTPUT chains. My Google-fu isn't helping. I'm on Gentoo, if that makes any difference. Anyone here have any insight?

    • bahamat
      bahamat almost 10 years
      Can you show the iptables rule(s) in question?
  • Shawn J. Goff
    Shawn J. Goff almost 10 years
    That command in the thread is incorrect; -p is for matching on a protocol; he meant -A like my answer says.
  • ND Geek
    ND Geek almost 10 years
    Couldn't the REJECT ICMP packet return on the lo interface? I agree that a LOG is useful for troubleshooting, but what I was really hoping for is a way to remind me that "Oh, yeah...that's probably being blocked by my DROP iptables default" instead of troubleshoots for 5 minutes asks co-worker to access XYZ server realizes it's probably local, which is my most common approach, since my typical workday rarely hits things I haven't opened a hole for already. Of course maybe I need to keep that in mind better, but a flat REJECT is more obvious.
  • ND Geek
    ND Geek almost 10 years
    That makes sense, and a generic REJECT at the end should work. Out of curiosity, is the target extension definition somewhere fairly obvious and I just missed it, or is that one of the poorly documented bits?
  • ND Geek
    ND Geek almost 10 years
    That's pretty interesting. The curiosity in me wonders if there's a reason behind it, or if that's just how things are, possibly for simplicity's sake (simpler code means fewer possible spots for vulnerabilities after all). If I were even a moderate developer I might be tempted to hack it in locally, but since I'm not, and given it's a piece of security, I'm not gonna touch it.
  • Aaron D. Marasco
    Aaron D. Marasco almost 10 years
    I don't think you would want the ethX interface to generate traffic on the lo interface for many reasons. They are very independent; you can easily make chains apply to one and not the other.
  • StarNamer
    StarNamer almost 10 years
    Reading the whole man page, it's clear that REJECT is a target extension, but the man page is very long so "TL;DR" tends to apply. It also implies that DROP, ACCEPT and QUEUE are valid policy targets; from the current code, QUEUE isn't!