How are `vti` and `xfrm` iproute2 interfaces supposed to be configured and used with xfrm states and policies


XFRM states and policies enable configuring IPsec encryption without a virtual interface. The vti and xfrm interface types, however, I think make it possible to route traffic through a virtual interface to enable routing policy-based encryption. I am not sure how to configure these interfaces alongside XFRM states and policies to support this functionality.

The vti and xfrm interface types lists the following link parameters:

$ ip link help type vti
Usage: ... vti  [ remote ADDR ]
                [ local ADDR ]
                [ [i|o]key KEY ]
                [ dev PHYS_DEV ]
                [ fwmark MARK ]

Where:  ADDR := { IP_ADDRESS }
        KEY  := { DOTTED_QUAD | NUMBER }
        MARK := { 0x0..0xffffffff }

$ ip link help type xfrm
Usage: ... xfrm dev [ PHYS_DEV ] [ if_id IF-ID ]
                [ external ]

Where: IF-ID := { 0x1..0xffffffff }

What do these parameters mean exactly (the documentation on them is lacking) and how do they relate to XFRM state and policy definitions?

XFRM states and policies have the following parameter list (from man page):

       ip xfrm state { add | update } ID [ ALGO-LIST ] [ mode MODE ] [ mark MARK [ mask
               MASK ] ] [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ replay-seq
               SEQ ] [ replay-oseq SEQ ] [ replay-seq-hi SEQ ] [ replay-oseq-hi SEQ ] [
               flag FLAG-LIST ] [ sel SELECTOR ] [ LIMIT-LIST ] [ encap ENCAP ] [ coa
               ADDR[/PLEN] ] [ ctx CTX ] [ extra-flag EXTRA-FLAG-LIST ] [ output-mark OUT‐
               PUT-MARK [ mask MASK ] ] [ if_id IF-ID ] [ tfcpad LENGTH ]

       ip xfrm policy { add | update } SELECTOR dir DIR [ ctx CTX ] [ mark MARK [ mask
               MASK ] ] [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRI‐
               ORITY ] [ flag FLAG-LIST ] [ if_id IF-ID ] [ LIMIT-LIST ] [ TMPL-LIST ]

An example usage of these two in relation to XFRM states and policies could also help clarify this subject.

Best Answer

Don't bother with VTIs if you have XFRM interfaces available. The latter are way more flexible and their configuration is simple and logical (the strongSwan docs have a list of other advantages of XFRM interfaces).

Basically, configure the same if_id (a 32-bit number) on the interface and the policies and SAs to associate them. This allows the use of multiple unrelated policies/SAs with a single interface but also using separate interfaces for in-/outbound traffic or even per SA. Note that the XFRM interfaces don't even have to be in the same network namespaces as the policies and SAs. I don't think setting a physical interface currently has an effect, so that can be omitted. And external sets the interface into "collect metadata" mode, which allows one interface per namespace to act as a catch-all (e.g. allowing an eBPF program attached to it to set the if_id for a packet dynamically to select different SAs).

Just for completeness, VTIs are associated with policies and SAs via IP addresses and marks. The configuration of the latter is a bit weird as it's done via [i|o]key parameter (reusing parameters that were originally defined for GRE interfaces). The remote and local addresses have to match those on the SAs (a single wildcard VTI can be created that has remote and the marks on SAs and policies have to match as well (except for the inbound SA, which does not require the mark).

Related Question