2

I am unable to filter Neighbor Advertisement packets based on a target address field, which is known as a 'tgt' field in this type of packets.

A message when some device with a MAC aa:bb:cc:dd:ee:ff is trying to use the address 2001:ffff:1002:51:: looks like this in Wireshark:

src: fe80::aabb:ccff:fedd:eeff dst: ff02::1 proto: ICMPv6 (type 136) info: Neighbor Advertisement 2001:ffff:1002:51:: (rtr) is at aa:bb:cc:dd:ee:ff

Same packet in tcpdump:

16:57:40.303118 IP6 fe80::aabb:ccff:fedd:eeff > ff02::1: ICMP6, neighbor advertisement, tgt is 2001:ffff:1002:51::, length 32

Turns out there is no way to filter these with ip6tables, because it doesn't provide an option to specify the tgt field in the icmpv6 proto. The absence of such makes preventing NDP poisoning attacks difficult on Linux-based routers. Back in 2010, there was someone in the netfilter mailing list who made an assumption about possible existence of a tool called ndptables as an alternative for arptables used for IPv4, but this idea failed.

I am aware of SEcure Neighbor Discovery (SEND) that could be used for that, but I can't find any decent information on how to configure it on Debian or Ubuntu.

What should be used to filter these packets on a router running Linux?

Diana
  • 46
  • 3
  • 1
    SEND is mostly not used, as most enterprise networking equipment has their own techniques for mitigating NDP spoofing, and many do not support SEND. Check the documentation for your routers and L3 switches to see what is available to you. If you're trying to use Linux as a router, there are some userspace SEND tools you can try, but again it's mostly not used.... – Michael Hampton Aug 19 '19 at 07:56
  • My company don't use any L3 hardware switches, hence all the routing, load balancing and firewall operations are performed on Linux servers with 40g links. Someone on Freenode ##networking has suggested that currently, NDP MAC/IP filtering lacks implementation on Linux, but it's still possible to craft that filter with a `u32` iptables extension. I will try to make it if there are no better suggestions. – Diana Aug 19 '19 at 15:33

1 Answers1

-1

I personally use ipv6 and ipv4 in dual stack but you can always block ipv6 icmpv6 with firehol for example.

ipv6 interface any v6interop proto icmpv6
  policy drop

If you dont want to use firehol try to check what are the ip6tables rules generated by this helper. More info Firehol doc

Edit based on comments

I got your point and did some researches, let me share that with you:

How to block icmpv6 traffic based on Target Address (tgt)

First of all lets capture a packet that we want to block (136 = Neighbor Advertisement icmpv6 packets)

tcpdump -ttt -vvv -xx -n -i eno1 "icmp6 && ip6[40] == 136"

As result i got this packet for example

 00:00:05.054822 IP6 (class 0xe0, hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::2ff:ffff:feff:fffe > fe80::ec4:7aff:fed9:7d0e: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is fe80::2ff:ffff:feff:fffe, Flags [router, solicited, override]
          destination link-address option (2), length 8 (1): 00:ff:ff:ff:ff:fe
        0x0000:  00ff ffff fffe
        0x0000:  0cc4 7ad9 7d0e 00ff ffff fffe 86dd 6e00
        0x0010:  0000 0020 3aff fe80 0000 0000 0000 02ff
        0x0020:  ffff feff fffe fe80 0000 0000 0000 0ec4
        0x0030:  7aff fed9 7d0e 8800 8f7a e000 0000 fe80
        0x0040:  0000 0000 0000 02ff ffff feff fffe 0201
        0x0050:  00ff ffff fffe

IPv6 IP is 40 bytes long so icmpv6 start with 8800 8f7a e000 0000 and icmpv6 body comes after with fe80 0000 0000 0000 02ff ffff feff fffe. The last part according to the RFC is the Target Address or tgt.

Now lets see how to filter these packets with ip6tables. I descovered two interesting netfilter modules, string and u32. I didnt figured out how to filter with string module but u32 works perfectly.

Assuming tgt you want to block is fe80::2ff:ffff:feff:fffe ip6tables rule would be something like this

ip6tables -I INPUT 1 -p icmpv6 --icmpv6-type neighbor-advertisement -m u32 --u32 "48=0xfe800000 && 52=0x00000000 && 56=0x02ffffff && 60=0xfefffffe" -j LOG --log-prefix "Bad neighbor-advertisement tgt:"

Note that i dont want to block it, just log given packet to see if rule match.

Aug 20 09:45:24 squanchy kernel: Bad neighbor-advertisement tgIN=eno1 OUT= MAC=0c:c4:7a:d9:7d:0e:00:ff:ff:ff:ff:fe:86:dd SRC=fe80:0000:0000:0000:02ff:ffff:feff:fffe DST=fe80:0000:0000:0000:0ec4:7aff:fed9:7d0e LEN=72 TC=224 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=136 CODE=0

Again i run firehol on my server so logs are little different from what you are going to see with raw ip6tables

P.S be aware that the rule here is based on tgt and not the source address that appears to be the same as tgt field.

vx3r
  • 368
  • 2
  • 9
  • 1
    I can't find anything in the question that suggests disabling or blocking IPv6 is an acceptable answer. – Michael Hampton Aug 19 '19 at 07:57
  • @MichaelHampton how about _What should be used to filter these packets on a router running Linux?_ and by saying _block_ it mean block `ipv6 icmpv6` packets, see firehol doc. Please avoid to down vote without reading carefully information provided – vx3r Aug 19 '19 at 08:10
  • 1
    I read your answer and your new comment carefully, and I am convinced that you misunderstood the question. He does not want to filter all ICMPv6 packets. Because your answer is wrong, the downvotes are appropriate. – Michael Hampton Aug 19 '19 at 17:59
  • please see edited answer – vx3r Aug 20 '19 at 08:10
  • That's great, I've upvoted your answer because it provides a possible solution to the problem after the edit, however my votes aren't being counted for now. You also could've deleted the irrelevant part of the answer in the edit so it doesn't mess with a general idea. – Diana Aug 20 '19 at 16:14
  • 1
    To be nitpicking, a determined attacker could insert an extension header before the upper layer header to avoid being detected correctly by the u32 match (which assumes here the upper layer header always starts at byte 40). Using nft (nftables)'s raw payload with `@th` probably avoids this problem because `@th` would start directly at the upper layer header (icmpv6 here), so an extension header wouldn't interfere. – A.B Sep 08 '19 at 23:00