IPSec plugin

Written for: v2.0-vpp18.10

The IPSec plugin allows to configure security policy databases and security associations to the VPP, and also handles relations between the SPD and SA or between SPD and an assigned interface. Note that the IPSec tunnel interfaces are not a part of IPSec plugin (their configuration is handled in VPP interface plugin).

Security policy database

Security policy database (SPD) specifies policies that determine the disposition of all the inbound or outbound IP traffic from either the host or the security gateway. The SPD is bound to an SPD interface and contains a list of policy entries (security table). Every policy entry points to VPP security association.

Model

Security policy database is defined in the common IPSec model. The generated object is defined as SecurityPolicyDatabase.

Key format:

config/vpp/v2/ipsec/spd/<index>

The SPD defines its own unique index within VPP. The user has an option to set its own index (it is not generated in the VPP, as for example for access lists) in uint32 range. The index is a mandatory field in the model because it serves as a unique identifier also in the vpp-agent and is a part of the SPD key as well. The attention has to be paid defining an index in the model. Despite the field is a string format, it only accepts plain numbers. Attempt to set any non-numeric characters ends up with an error.

Every policy entry has field sa_index. This is the security association reference in the security policy database. The field is mandatory, missing value causes an error during configuration.

The SPD defines two bindings: the security association (for every entry) and the interface. The interface binding is important since VPP needs to create an empty SPD first, which cannot be done without it. All the policy entries are configured after that, where the SA is expected to exist. Since every security policy database entry is configured independently, vpp-agent can configure IPSec SPD only partially (depending on available binding).

All the binding can be resolved by the vpp-agent.

Configuration

How to configure the security policy database:

1. Using Key-value database: put proto-modeled data with the correct key for SPD.

Key:

/vnf-agent/vpp1/config/vpp/ipsec/v2/spd/<index>

Example value:

{
  "index":"1",
  "interfaces": [
    { "name": "tap1" }
  ],
  "policy_entries": [
    {
      "priority": 10,
      "is_outbound": false,
      "remote_addr_start": "10.0.0.1",
      "remote_addr_stop": "10.0.0.1",
      "local_addr_start": "10.0.0.2",
      "local_addr_stop": "10.0.0.2",
      "action": 3,
      "sa_index": "20"
    },
    {
      "priority": 10,
      "is_outbound": true,
      "remote_addr_start": "10.0.0.1",
      "remote_addr_stop": "10.0.0.1",
      "local_addr_start": "10.0.0.2",
      "local_addr_stop": "10.0.0.2",
      "action": 3,
      "sa_index": "10"
    }
  ]
}

Use etcdctl to put compacted key-value entry:

etcdctl put /vnf-agent/vpp1/config/vpp/ipsec/v2/spd/1 '{"index":"1","interfaces":[{"name":"tap1"}],"policy_entries":[{"priority":10,"is_outbound":false,"remote_addr_start":"10.0.0.1","remote_addr_stop":"10.0.0.1","local_addr_start":"10.0.0.2","local_addr_stop":"10.0.0.2","action":3,"sa_index":"20"},{"priority":10,"is_outbound":true,"remote_addr_start":"10.0.0.1","remote_addr_stop":"10.0.0.1","local_addr_start":"10.0.0.2","local_addr_stop":"10.0.0.2","action":3,"sa_index":"10"}]}'

2. Using REST:

IPSec currently does not support REST.

3. Using GRPC:

  • Prepare the IPSec SPD data:
import (
    "github.com/ligato/vpp-agent/api/models/vpp"
    "github.com/ligato/vpp-agent/api/models/vpp/ipsec"
)

spd := ipsec.SecurityPolicyDatabase{
        Index: "1",
        Interfaces: []*ipsec.SecurityPolicyDatabase_Interface{
            {
                Name: "if1",
            }
        },
        PolicyEntries: []*ipsec.SecurityPolicyDatabase_PolicyEntry{
            {
                Priority:        10,
                IsOutbound:      false,
                RemoteAddrStart: "10.0.0.1",
                RemoteAddrStop:  "10.0.0.1",
                LocalAddrStart:  "10.0.0.2",
                LocalAddrStop:   "10.0.0.2",
                Action:          3,
                SaIndex:         "1",
            },
        },
    }
  • Prepare the GRPC config data:
import (
    "github.com/ligato/vpp-agent/api/configurator"
    "github.com/ligato/vpp-agent/api/models/vpp"
)

config := &configurator.Config{
        VppConfig: &vpp.ConfigData{
            IpsecSpds: []*ipsec.SecurityPolicyDatabase {
                spd,
            },  
        }
    }

The config data can be combined with any other VPP or Linux configuration.

  • Update the data via the GRPC using the client of the ConfigurationClient type (read more about how to prepare the GRPC connection and about other CRUD methods in the GRPC tutorial):
import (
    "github.com/ligato/vpp-agent/api/configurator"
)

response, err := client.Update(context.Background(), &configurator.UpdateRequest{Update: config, FullResync: true})

The VPP CLI IPSec SPD commands:

The VPP cli has a command to show the SPD IPSec configuration: sh ipsec

Security associations

The VPP security association (SA) is a set of IPSec specifications negotiated between devices establishing and IPSec relationship. The SA includes preferences for the authentication type, IPSec protocol or encryption used when the IPSec connection is established.

Model

Security association is defined in the common IPSec model. The generated object is defined as SecurityAssociation.

Key format:

/vnf-agent/vpp1/config/vpp/ipsec/v2/sa/<index>

The SA uses the same indexing system as SPD. The index is a user-defined unique identifier of the security association in uint32 range. Similarly to SPD, the SA index is also defined as string type field in the model but can be set only to numerical values. Attempt to set other values causes processing errors.

The SA has no dependencies on other configuration types.

Configuration

How to configure the security association:

1. Using Key-value database: use proto-modeled data with the correct security association key.

Key:

/vnf-agent/vpp1/config/vpp/ipsec/v2/sa/<sa-index>

Example value:

{
  "index":"1",
  "spi": 1001,
  "protocol": 1,
  "crypto_alg": 1,
  "crypto_key": "4a506a794f574265564551694d653768",
  "integ_alg": 2,
  "integ_key": "4339314b55523947594d6d3547666b45764e6a58"
}

Use etcdctl to put compacted key-value entry:

etcdctl put /vnf-agent/vpp1/config/vpp/ipsec/v2/sa/1 '{"index":"1","spi":1001,"protocol":1,"crypto_alg":1,"crypto_key":"4a506a794f574265564551694d653768","integ_alg":2,"integ_key":"4339314b55523947594d6d3547666b45764e6a58"}'

2. Using REST:

IPSec currently does not support REST.

3. Using GRPC:

  • Prepare the IPSec SA data:
import (
    "github.com/ligato/vpp-agent/api/models/vpp"
    "github.com/ligato/vpp-agent/api/models/vpp/ipsec"
)

sa := ipsec.SecurityAssociation{
        Index:          "1",
        Spi:            1001,
        Protocol:       1,
        CryptoAlg:      1,
        CryptoKey:      "4a506a794f574265564551694d653768",
        IntegAlg:       2,
        IntegKey:       "4339314b55523947594d6d3547666b45764e6a58",
        EnableUdpEncap: true,
    }
  • Prepare the GRPC config data:
import (
    "github.com/ligato/vpp-agent/api/configurator"
    "github.com/ligato/vpp-agent/api/models/vpp"
)

config := &configurator.Config{
        VppConfig: &vpp.ConfigData{
            IpsecSas: []*ipsec.SecurityAssociation {
                sa,
            },  
        }
    }

The config data can be combined with any other VPP or Linux configuration.

  • Update the data via the GRPC using the client of the ConfigurationClient type (read more about how to prepare the GRPC connection and about other CRUD methods in the GRPC tutorial):
import (
    "github.com/ligato/vpp-agent/api/configurator"
)

response, err := client.Update(context.Background(), &configurator.UpdateRequest{Update: config, FullResync: true})

The VPP CLI IPSec SA commands:

Show the IPSec configuration with the VPP cli command: sh ipsec