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
andegress
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
anddestination
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
"destination_port"
and"source_port"
properties are only available when the"protocol"
for the rule is"tcp"
or"udp"
. - The
"icmp_code"
(opens in a new tab) and"icmp_type"
(opens in a new tab) properties are only available when the"protocol"
is"icmp4"
or"icmp6"
.
- The
- 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:
drop
reject
allow
- The default action for unmatched traffic (defaults to
reject
, see Configure default actions)
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
oflogged
.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