0

Right now I'm trying to figure out how to set up some IPv6 rules on a server of mine. My requirements are to disallow input echo-requests to the loopback device and local IP addresses (in this case, link-local), as well as open up ports 22, 80, and 443. Everything works great for IPv4, but I'm having an issue with ip6tables following the chain order for INPUT it seems. Here's what I have now:

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p icmpv6 -m icmpv6 --icmpv6-type echo-request -j ACCEPT
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -j REJECT
-A FORWARD -j REJECT --reject-with icmp6-port-unreachable
-A OUTPUT -p icmpv6 --icmpv6-type echo-request -d ::1/128 -j REJECT --reject-with icmp6-port-unreachable
-A OUTPUT -p icmpv6 --icmpv6-type echo-request -d fe80::/64 -j REJECT --reject-with icmp6-port-unreachable
-A OUTPUT -j ACCEPT
COMMIT

Currently my culprit line is -A INPUT -j REJECT. My expectations are it will do an implicit deny of everything not listed above in the chain. This doesn't seem to be the case though, and seems to behave differently than plain old iptables with IPv4 rules. Can someone enlighten me on the solution here? This is an Ubuntu 14.04 server

  • What’s not being stopped? And won’t you accept all echo-requests with input rule 4? – Guy Jan 5 '18 at 0:50
3

Let's see what your rules are trying to do first, to see why they might not be working:

-A INPUT -i lo -j ACCEPT

All traffic arriving at the loopback interface will be processed, including ICMPv6 traffic.

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT

Pretty normal.

-A INPUT -p icmpv6 -m icmpv6 --icmpv6-type echo-request -j ACCEPT

This rule, as written, will only allow ping requests (to any interface): any other ICMPv6 packets will be denied by the explicit REJECT at the end.

-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -j REJECT
-A FORWARD -j REJECT --reject-with icmp6-port-unreachable

Pretty normal.

-A OUTPUT -p icmpv6 --icmpv6-type echo-request -d ::1/128 -j REJECT --reject-with icmp6-port-unreachable
-A OUTPUT -p icmpv6 --icmpv6-type echo-request -d fe80::/64 -j REJECT --reject-with icmp6-port-unreachable

These rules will only prevent your host from sending pings to the localhost and link-local network addresses (also, the link-local address range is a /10.)

-A OUTPUT -j ACCEPT

Pretty normal.

However, you said: "My requirements are to disallow input echo-requests to the loopback device and local IP addresses (in this case, link-local) [...]". Your rules as written are almost the opposite of what you wanted for this requirement. As well, it's usually better to put input filters on the input side, as that's where most people are going to look for stuff like this, and it will be effective for all traffic, not just traffic that your computer is sending.

I would recommend writing your rule chains as follows:

-A INPUT -i lo -p icmpv6 -m icmpv6 --icmpv6-type echo-request -j REJECT --reject-with icmp6-port-unreachable
-A INPUT -d fe80::/10 -p icmpv6 -m icmpv6 --icmpv6-type echo-request -j REJECT --reject-with icmp6-port-unreachable
-A INPUT -p icmpv6 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -j REJECT
-A FORWARD -j REJECT --reject-with icmp6-port-unreachable

Some observations about the rewritten rules:

  1. I prefer to put REJECT rules in front of ACCEPT rules, and narrower filters in front of wider filters so that I don't accidentally allow something through because it was allowed by a wider filter. It isn't a hard-and-fast rule, but it helps me to visualize what's going on a bit easier.
  2. The OUTPUT chain is not needed anymore because the rules are handled in the INPUT chain instead.
  3. Although you have it as a requirement, I'm not certain why you want to disallow pings to the loopback interface as only the local computer can send to that interface. This is only an observation, though: if you have a particular need to do this, that's fine.
| improve this answer | |
  • Hi Erik, I read what you said and played around with what your rules. Thank you for the correction on the CIDR notation for link-locals, I had forgotten what it was. I have my reasons to disallow ping to my LO and local network, so your observation there is accurate and correct. I looked at what you said about my input echo-requests req, and I made a blunder, output rules is what I want. The mods I made to your rules were remove the INPUT rule for link-local, and add that and the LO rule to the output chain. It seems it all works now after that! – stratacast1 Jan 5 '18 at 21:33
  • I'm glad it works. I use link-local filters so infrequently that I had to look up the subnet for them as well! – ErikF Jan 5 '18 at 22:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.