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:
- 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.
- The OUTPUT chain is not needed anymore because the rules are handled in the INPUT chain instead.
- 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.