Skip to content
Docs
How to configure network ACLs

How to configure network ACLs

Note
Network ACLs are available for the OVN NIC type, the OVN network and the Bridge network (with some exceptions; see Bridge limitations).

▶ Watch on YouTube (opens in a new tab)

Network ACLs define rules for controlling traffic:

  • Between instances connected to the same network
  • To and from other networks

Network ACLs can be assigned directly to the NIC of an instance, or to a network. When assigned to a network, the ACL applies indirectly to all NICs connected to that network.

When an ACL is assigned to multiple instance NICs, either directly or indirectly, those NICs form a logical port group. You can use the name of that ACL to refer to that group in the traffic rules of other ACLs. For more information, see: Subject name selectors (ACL groups).

List ACLs

CLI | API

To list all ACLs, run:

lxc network acl list

To list all ACLs, query the GET /1.0/network-acls endpoint:

lxc query --request GET /1.0/network-acls

You can also use recursion to list the ACLs with a higher level of detail:

lxc query --request GET /1.0/network-acls?recursion=1

Show an ACL

CLI | API

To show details about a specific ACL, run:

lxc network acl show <ACL-name>

Example:

lxc network acl show my-acl

For details about a specific ACL, query the GET /1.0/network-acls/{ACL-name} endpoint`:

lxc query --request GET /1.0/network-acls/{ACL-name}

Example:

lxc query --request GET /1.0/network-acls/my-acl

Create an ACL

Name requirements

Network ACL names must meet the following requirements:

  • Must be between 1 and 63 characters long.
  • Can contain only ASCII letters (a–z, A–Z), numbers (0–9), and dashes (-).
  • Cannot begin with a digit or a dash.
  • Cannot end with a dash.

Instructions

CLI | API

To create an ACL, run:

lxc network acl create <ACL-name> [user.KEY=value ...]
  • You must provide an ACL name that meets the Name requirements.
  • You can optionally provide one or more custom user keys to store metadata or other information.

ACLs have no rules upon creation via command line, so as a next step, add rules to the ACL. You can also edit the ACL configuration, or assign the ACL to a network or NIC.

Another way to create ACLs from the command line is to provide a YAML configuration file:

lxc network acl create <ACL-name> < <filename.yaml>

This file can include any other ACL properties, including the egress and ingress properties for defining ACL rules. See the second example in the set below.

Examples

Create an ACL with the name my-acl and an optional custom user key:

lxc network acl create my-acl user.my-key=my-value

Create an ACL using a YAML configuration file:

First, create a file named config.yaml with the following content:

description: Allow web traffic from internal network
config:
  user.owner: devops
ingress:
  - action: allow
    description: Allow HTTP/HTTPS from internal
    protocol: tcp
    source: "@internal"
    destination_port: "80,443"
    state: enabled

Note that the custom user keys are stored under the config property.

The following command creates an ACL from that file’s configuration:

lxc network acl create my-acl < config.yaml

To create an ACL, query the POST /1.0/network-acls endpoint:

lxc query --request POST /1.0/network-acls --data '{
  "name": "<ACL-name>",
  "config": {
    "user.<custom-key-name>": "<custom-key-value>"
  },
  "description": "<description of the ACL>",
  "egress": [{<egress rule object>}, {<another egress rule object>, ...}],
  "ingress": [{<ingress rule object>}, {<another ingress rule object>, ...}]
}'
  • You must provide an ACL name that meets the Name requirements.
  • You can optionally provide one or more custom config.user.* keys to store metadata or other information.
  • The ingress and egress lists contain rules for inbound and outbound traffic. See ACL rules for details.

Examples

Create an ACL with the name my-acl, a custom user key of my-key, and a description:

lxc query --request POST /1.0/network-acls --data '{
  "name": "my-acl",
  "config": {
    "user.my-key": "my-value"
  },
  "description": "Web servers"
}'

Create an ACL with the name my-acl and an ingress rule:

lxc query --request POST /1.0/network-acls --data '{
  "name": "my-acl",
  "ingress": [
    {
      "action": "drop",
      "state": "enabled"
    }
  ]
}'

ACL properties

ACLs have the following properties:

config

User-provided free-form key/value pairs

Key: config
Type: string set
Required: no

The only supported keys are user.* custom keys.

description

Description of the network ACL

Key: description
Type: string
Required: no

egress

Egress traffic rules

Key: egress
Type: rule list
Required: no

ingress

Ingress traffic rules

Key: ingress
Type: rule list
Required: no

name

Unique name of the network ACL in the project

Key: name
Type: string
Required: yes

ACL rules

Each ACL contains two lists of rules:

  • Rules in the egress list apply to outbound traffic from the NIC.
  • Rules in the ingress list apply to inbound traffic to the NIC.

For both egress and ingress, the rule configuration looks like this:

YAML | JSON

action: <allow|reject|drop>
description: <description>
destination: <destination-IP-range>
destination_port: <destination-port-number>
icmp_code: <ICMP-code>
icmp_type: <ICMP-type>
protocol: <icmp4|icmp6|tcp|udp>
source: <source-of-traffic>
source_port: <source-port-number>
state: <enabled|disabled|logged>
{
  "action": "<allow|reject|drop>",
  "description": "<description>",
  "destination": "<destination-IP-range>",
  "destination_port": "<destination-port-number>",
  "icmp_code": "<ICMP-code>",
  "icmp_type": "<ICMP-type>",
  "protocol": "<icmp4|icmp6|tcp|udp>",
  "source": "<source-of-traffic>",
  "source_port": "<source-port-number>",
  "state": "<enabled|disabled|logged>"
}
  • The action property is required.
  • The state property defaults to "enabled" if unset.
  • The source and destination properties can be specified as one or more CIDR blocks, IP ranges, or selectors. If left empty, they match any source or destination. Comma-separate multiple values.
  • If the protocol is unset, it matches any protocol.
  • The "destination_port" and "source_port" properties and "icmp_code" and "icmp_type" properties are mutually exclusive sets. Although both sets are shown in the same rule above to demonstrate the syntax, they never appear together in practice.
  • The "state" is "enabled" by default. The "logged" value is used to log traffic to a rule.

For more information, see: Rule properties.

Add a rule

CLI | API

To add a rule to an ACL, run:

lxc network acl rule add <ACL-name> <egress|ingress> [properties...]

Example

Add an egress rule with an action of drop to my-acl:

lxc network acl rule add my-acl egress action=drop

There is no specific endpoint for adding a rule. Instead, you must edit the full ACL, which contains the egress and ingress lists.

Remove a rule

CLI | API

To remove a rule from an ACL, run:

lxc network acl rule remove <ACL-name> <egress|ingress> [properties...]

You must either specify all properties needed to uniquely identify a rule or add --force to the command to delete all matching rules.

There is no specific endpoint for removing a rule. Instead, you must edit the full ACL, which contains the egress and ingress lists.

Edit a rule

You cannot edit a rule directly. Instead, you must edit the full ACL, which contains the egress and ingress lists.

Rule ordering and application of actions

ACL rules are defined as lists, but their order within the list does not affect how they are applied.

LXD automatically prioritizes rules based on the action property, in the following order:

When you assign multiple ACLs to a NIC, you do not need to coordinate rule order across them. As soon as a rule matches, its action is applied and no further rules are evaluated.

Rule properties

ACL rules have the following properties:

action

Action to take for matching traffic

Key: action
Type: string
Required: yes

Possible values are allow, reject, and drop.

description

Description of the rule

Key: description
Type: string
Required: no

destination

Comma-separated list of destinations

Key: destination
Type: string
Required: no

Destinations can be specified as CIDR or IP ranges, destination subject name selectors (for egress rules), or be left empty for any.

destination_port

Destination ports or port ranges

Key: destination_port
Type: string
Required: no

This option is valid only if the protocol is udp or tcp. Specify a comma-separated list of ports or port ranges (start-end inclusive), or leave the value empty for any.

icmp_code

ICMP message code

Key: icmp_code
Type: string
Required: no

This option is valid only if the protocol is icmp4 or icmp6. Specify the ICMP code number, or leave the value empty for any.

icmp_type

Type of ICMP message

Key: icmp_type
Type: string
Required: no

This option is valid only if the protocol is icmp4 or icmp6. Specify the ICMP type number, or leave the value empty for any.

protocol

Protocol to match

Key: protocol
Type: string
Required: no

Possible values are icmp4, icmp6, tcp, and udp. Leave the value empty to match any protocol.

source

Comma-separated list of sources

Key: source
Type: string
Required: no

Sources can be specified as CIDR or IP ranges, source subject name selectors (for ingress rules), or be left empty for any.

source_port

Source ports or port ranges

Key: source_port
Type: string
Required: no

This option is valid only if the protocol is udp or tcp. Specify a comma-separated list of ports or port ranges (start-end inclusive), or leave the value empty for any.

state

State of the rule

Key: state
Type: string
Default: enabled
Required: yes

Possible values are enabled, disabled, and logged.

Use selectors in rules

Note
This feature is supported only for the OVN NIC type and the OVN network.

In ACL rules, the source and destination properties support using selectors instead of CIDR blocks or IP ranges. You can only use selectors in the source of ingress rules, and in the destination of egress rules.

Using selectors allows you to define rules for groups of instances instead of managing lists of IP addresses or subnets manually.

There are two types of selectors:

  • subject name selectors (ACL groups)
  • network subject selectors

Subject name selectors (ACL groups)

When an ACL is assigned to multiple instance NICs, either directly or through their networks, those NICs form a logical port group. You can use the name of that ACL as a subject name selector to refer to that group in the egress and ingress lists of other ACLs.

For example, if you have an ACL with the name my-acl, you can specify the group of instance NICs that are assigned this ACL as an egress or ingress rule’s source by setting source to my-acl.

Network subject selectors

Use network subject selectors to define rules based on the network that the traffic is coming from or going to.

All network subject selectors begin with the @ symbol. There are two special network subject selectors called @internal and @external. They represent the network’s local and external traffic, respectively.

Here’s an example ACL rule (in YAML) that allows all internal traffic with the specified destination port:

ingress:
  - action: allow
    description: Allow HTTP/HTTPS from internal
    protocol: tcp
    source: "@internal"
    destination_port: "80,443"
    state: enabled

If your network supports network peers, you can reference traffic to or from the peer connection by using a network subject selector in the format @<network-name>/<peer-name>. Example:

source: "@my-network/my-peer"

When using a network subject selector, the network that has the ACL assigned to it must have the specified peer connection.

Log traffic

ACL rules are primarily used to control network traffic between instances and networks. However, they can also be used to log specific types of traffic, which is useful for monitoring or testing rules before enabling them.

To configure a rule so that it only logs traffic, configure its state to logged when you add the rule or edit the ACL.

View logs

CLI | API

To display the logs for all logged rules in an ACL, run:

lxc network acl show-log <ACL-name>

To display the logs for all logged rules in an ACL, query the GET /1.0/network-acls/{ACL-name}/log endpoint:

lxc query --request GET /1.0/network-acls/{ACL-name}/log

Example

lxc query --request GET /1.0/network-acls/my-acl/log

Note
If your attempt to view logs returns no data, that means either:

  • No logged rules have matched any traffic yet.
  • The ACL does not contain any rules with a state of logged.

When displaying logs for an ACL, LXD intentionally displays all existing logs for that ACL, including logs from formerly logged rules that are no longer set to log traffic. Thus, if you see logs from an ACL rule, that does not necessarily mean that its `state