Bug 249275 - New netgraph nodetype: ng_antispoof
Summary: New netgraph nodetype: ng_antispoof
Status: Closed Overcome By Events
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.1-RELEASE
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-net (Nobody)
Depends on:
Reported: 2020-09-12 09:38 UTC by Markus Stoff
Modified: 2020-09-15 04:45 UTC (History)
0 users

See Also:

New netgraph node type: ng_antispoof (83.39 KB, patch)
2020-09-12 09:38 UTC, Markus Stoff
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Stoff 2020-09-12 09:38:32 UTC
Created attachment 217912 [details]
New netgraph node type: ng_antispoof

This introduces a new netgraph node type that prevents the upstream network from spoofing ethernet and IP addresses. It is called 'ng_antispoof' (name is open for debate, of course).

What it does:

It validates the upstream address each packet against a set of rules. If at least one rule matches, the packet is passed through, otherwise it is blocked.

Each rule consists of a ethernet address and a IP or IPv6 address (in a simplified point of view).

How it works:

Each node provides three hooks:

- 'filter':     Where to connect the upstream node to be protected (e.g. a jail, a VM, ...).
- 'downstream': Downstream node (e.g. a bridge device, the internet, ...).
- 'nomatch':    Useful for debugging with tcpdump. If connected, blocked traffic is forwarded on this hook instead of being discarded. This is output only, traffic arriving on this hook is immediately discarded.

          ___               +----------------+
     __.(     ).__          |                |
    ( downstream  )<------->|                |         
     .._ ( ) _ _..          |                |         I==========I
                            |  ng_antispoof  |<------->I  filter  I
                            |                |         I==========I
      nomatch <-------------|                |         
                            |                |

Use Case:

Prevent VNET jails from spoofing IP/MAC addresses while using pf(4) as the firewall on the host system.


Given a virtual network interface 'host_if' on the host system and 'jail_if' in a VNET enabled jail named 'malicious', restrict the jail to IP '' on the MAC '1a:00:de:ad:be:ef':

  # Create ng_antispoof node and wire everything together
  ngctl mkpeer jail_if: antispoof ether filter
  ngctl name jail_if:ether as
  ngctl connect as: host_if: downstream ether

  # Add filter rule
  ngctl msg as: addinet '{ ether=1a:00:de:ad:be:ef ip_addr= }'

More Details:

Currently filter rules for IP and IPv6 address types can be created. The maximum number of rules is 65535 (UINT16_MAX).

  # For IPv4, subnets can be provided in CIDR or netmask notation
  ngctl msg as: addinet '{ ether=0a:00:de:ad:be:ef ip_addr= }'
  ngctl msg as: addinet '{ ether=0a:00:de:ad:be:ef ip_addr= }'
  ngctl msg as: addinet '{ ether=0a:00:de:ad:be:ef ip_addr= ip_mask= }'

  # For IPv6, subnets can be provided in CIDR notation
  ngctl msg as: addinet6 '{ ether=0a:00:de:ad:be:ef ip6_addr=::1 }'
  ngctl msg as: addinet6 '{ ether=0a:00:de:ad:be:ef ip6_addr=1:2::/32 }'

Open Questions:

- Is it correct to add the IPv6 parsing type should be added to ng_parse?
- Should the IPv4 and IPv6 prefix types for CIDR notation also go into ng_parse? 
- What is the idiomatic way to provide tests for kernel modules?
- Should VLAN tags be filtered as well (currently all VLAN tags are ignored)?
  - Filtering only the outermost tag would probably be the sensible approach here?
  - Should a single rule filter a single VID, a range of VIDs or a list of (ranges) of VIDs?
Comment 1 Markus Stoff 2020-09-13 09:40:39 UTC
Please let me also have your thoughts at review D26420.
Comment 2 Markus Stoff 2020-09-15 04:45:26 UTC
The proposed functionality is already provided by ng_bpf(4).