Security Groups

A common new-user issue with OpenStack is failing to set an appropriate security group when launching an instance. As a result, the user is unable to contact the instance on the network.

Security groups are sets of IP filter rules that are applied to an instance's networking. They are project specific, and project members can edit the default rules for their group and add new rules sets. All projects have a "default" security group, which is applied to instances that have no other security group defined. Unless changed, this security group denies all incoming traffic.

 General Security Groups Configuration

The nova.conf option allow_same_net_traffic (which defaults to true) globally controls whether the rules apply to hosts that share a network. When set to true, hosts on the same subnet are not filtered and are allowed to pass all types of traffic between them. On a flat network, this allows all instances from all projects unfiltered communication. With VLAN networking, this allows access between instances within the same project. If allow_same_net_traffic is set to false, security groups are enforced for all connections. In this case, it is possible for projects to simulate allow_same_net_traffic by configuring their default security group to allow all traffic from their subnet.

[Tip]Tip

As noted in the previous chapter, the number of rules per security group is controlled by the quota_security_group_rules, and the number of allowed security groups per project is controlled by the quota_security_groups quota.

 End-User Configuration of Security Groups

Security groups for the current project can be found on the OpenStack dashboard under Access & Security. To see details of an existing group, select the edit action for that security group. Obviously, modifying existing groups can be done from this edit interface. There is a Create Security Group button on the main Access & Security page for creating new groups. We discuss the terms used in these fields when we explain the command-line equivalents.

 Setting with nova command

From the command line, you can get a list of security groups for the project you're acting in using the nova command:

$ nova secgroup-list
+---------+-------------+
| Name    | Description |
+---------+-------------+
| default | default     |
| open    | all ports   |
+---------+-------------+

To view the details of the "open" security group:

$ nova secgroup-list-rules open
+-------------+-----------+---------+-----------+--------------+
| IP Protocol | From Port | To Port | IP Range  | Source Group |
+-------------+-----------+---------+-----------+--------------+
| icmp        | -1        | 255     | 0.0.0.0/0 |              |
| tcp         | 1         | 65535   | 0.0.0.0/0 |              |
| udp         | 1         | 65535   | 0.0.0.0/0 |              |
+-------------+-----------+---------+-----------+--------------+

These rules are all "allow" type rules, as the default is deny. The first column is the IP protocol (one of icmp, tcp, or udp), and the second and third columns specify the affected port range. The fourth column specifies the IP range in CIDR format. This example shows the full port range for all protocols allowed from all IPs.

When adding a new security group, you should pick a descriptive but brief name. This name shows up in brief descriptions of the instances that use it where the longer description field often does not. Seeing that an instance is using security group http is much easier to understand than bobs_group or secgrp1.

As an example, let's create a security group that allows web traffic anywhere on the Internet. We'll call this group global_http, which is clear and reasonably concise, encapsulating what is allowed and from where. From the command line, do:

$ nova secgroup-create \
         global_http "allow web traffic from the Internet"
+-------------+-------------------------------------+
| Name        | Description                         |
+-------------+-------------------------------------+
| global_http | allow web traffic from the Internet |
+-------------+-------------------------------------+

This creates the empty security group. To make it do what we want, we need to add some rules:

$ nova secgroup-add-rule <secgroup> <ip-proto> <from-port> <to-port> <cidr>
$ nova secgroup-add-rule global_http tcp 80 80 0.0.0.0/0
+-------------+-----------+---------+-----------+--------------+
| IP Protocol | From Port | To Port | IP Range  | Source Group |
+-------------+-----------+---------+-----------+--------------+
| tcp         | 80        | 80      | 0.0.0.0/0 |              |
+-------------+-----------+---------+-----------+--------------+

Note that the arguments are positional, and the from-port and to-port arguments specify the allowed local port range connections. These arguments are not indicating source and destination ports of the connection. More complex rule sets can be built up through multiple invocations of nova secgroup-add-rule. For example, if you want to pass both http and https traffic, do this:

$ nova secgroup-add-rule global_http tcp 443 443 0.0.0.0/0
+-------------+-----------+---------+-----------+--------------+
| IP Protocol | From Port | To Port | IP Range  | Source Group |
+-------------+-----------+---------+-----------+--------------+
| tcp         | 443       | 443     | 0.0.0.0/0 |              |
+-------------+-----------+---------+-----------+--------------+

Despite only outputting the newly added rule, this operation is additive:

$ nova secgroup-list-rules global_http
+-------------+-----------+---------+-----------+--------------+
| IP Protocol | From Port | To Port | IP Range  | Source Group |
+-------------+-----------+---------+-----------+--------------+
| tcp         | 80        | 80      | 0.0.0.0/0 |              |
| tcp         | 443       | 443     | 0.0.0.0/0 |              |
+-------------+-----------+---------+-----------+--------------+

The inverse operation is called secgroup-delete-rule, using the same format. Whole security groups can be removed with secgroup-delete.

To create security group rules for a cluster of instances, you want to use SourceGroups.

SourceGroups are a special dynamic way of defining the CIDR of allowed sources. The user specifies a SourceGroup (security group name) and then all the users' other instances using the specified SourceGroup are selected dynamically. This dynamic selection alleviates the need for individual rules to allow each new member of the cluster.

The code is structured like this: nova secgroup-add-group-rule <secgroup> <source-group> <ip-proto> <from-port> <to-port>. An example usage is shown here:

$ nova secgroup-add-group-rule cluster global-http tcp 22 22

The "cluster" rule allows SSH access from any other instance that uses the global-http group.

 Setting with neutron command

If your environment is using Neutron, you can configure security groups settings using the neutron command. Get a list of security groups for the project you are acting in, by using following command:

$ neutron security-group-list
+--------------------------------------+---------+-------------+
| id                                   | name    | description |
+--------------------------------------+---------+-------------+
| 6777138a-deb7-4f10-8236-6400e7aff5b0 | default | default     |
| 750acb39-d69b-4ea0-a62d-b56101166b01 | open    | all ports   |
+--------------------------------------+---------+-------------+

To view the details of the "open" security group:

$ neutron security-group-show open
+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field                | Value                                                                                                                                                                                                                                                                                                                                  |
+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| description          | all ports                                                                                                                                                                                                                                                                                                                              |
| id                   | 750acb39-d69b-4ea0-a62d-b56101166b01                                                                                                                                                                                                                                                                                                   |
| name                 | open                                                                                                                                                                                                                                                                                                                                   |
| security_group_rules | {"remote_group_id": null, "direction": "egress", "remote_ip_prefix": null, "protocol": null, "tenant_id": "607ec981611a4839b7b06f6dfa81317d", "port_range_max": null, "security_group_id": "750acb39-d69b-4e0-a62d-b56101166b01", "port_range_min": null, "ethertype": "IPv4", "id": "361a1b62-95dd-46e1-8639-c3b2000aab60"}           |
|                      | {"remote_group_id": null, "direction": "ingress", "remote_ip_prefix": "0.0.0.0/0", "protocol": "udp", "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": 65535, "security_group_id": "750acb9-d69b-4ea0-a62d-b56101166b01", "port_range_min": 1, "ethertype": "IPv4", "id": "496ba8b7-d96e-4655-920f-068a3d4ddc36"}    |
|                      | {"remote_group_id": null, "direction": "ingress", "remote_ip_prefix": "0.0.0.0/0", "protocol": "icmp", "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": null, "security_group_id": "750acb9-d69b-4ea0-a62d-b56101166b01", "port_range_min": null, "ethertype": "IPv4", "id": "50642a56-3c4e-4b31-9293-0a636759a156"} |
|                      | {"remote_group_id": null, "direction": "egress", "remote_ip_prefix": null, "protocol": null, "tenant_id": "607ec981611a4839b7b06f6dfa81317d", "port_range_max": null, "security_group_id": "750acb39-d69b-4e0-a62d-b56101166b01", "port_range_min": null, "ethertype": "IPv6", "id": "f46f35eb-8581-4ca1-bbc9-cf8d0614d067"}           |
|                      | {"remote_group_id": null, "direction": "ingress", "remote_ip_prefix": "0.0.0.0/0", "protocol": "tcp", "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": 65535, "security_group_id": "750acb9-d69b-4ea0-a62d-b56101166b01", "port_range_min": 1, "ethertype": "IPv4", "id": "fb6f2d5e-8290-4ed8-a23b-c6870813c921"}    |
| tenant_id            | 607ec981611a4839b7b06f6dfa81317d                                                                                                                                                                                                                                                                                                       |
+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

These rules are all "allow" type rules, as the default is deny. This example shows the full port range for all protocols allowed from all IPs. This section describes the most common security-group-rule parameters:

direction

The direction in which the security group rule is applied. Valid values are ingress or egress.

remote_ip_prefix

This attribute value matches the specified IP prefix as the source IP address of the IP packet.

protocol

The protocol that is matched by the security group rule. Valid values are null, tcp, udp, icmp, and icmpv6.

port_range_min

The minimum port number in the range that is matched by the security group rule. If the protocol is TCP or UDP, this value must be less than or equal to the port_range_max attribute value. If the protocol is ICMP or ICMPv6, this value must be an ICMP or ICMPv6 type, respectively.

port_range_max

The maximum port number in the range that is matched by the security group rule. The port_range_min attribute constrains the port_range_max attribute. If the protocol is ICMP or ICMPv6, this value must be an ICMP or ICMPv6 type, respectively.

ethertype

Must be IPv4 or IPv6, and addresses represented in CIDR must match the ingress or egress rules.

When adding a new security group, you should pick a descriptive but brief name. This name shows up in brief descriptions of the instances that use it where the longer description field often does not. Seeing that an instance is using security group http is much easier to understand than bobs_group or secgrp1.

This example creates a security group that allows web traffic anywhere on the Internet. We'll call this group global_http, which is clear and reasonably concise, encapsulating what is allowed and from where. From the command line, do:

$ neutron security-group-create \
         global_http --description "allow web traffic from the Internet"
Created a new security_group:
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field                | Value                                                                                                                                                                                                                                                                                                                         |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| description          | allow web traffic from the Internet                                                                                                                                                                                                                                                                                           |
| id                   | c6d78d56-7c56-4c82-abcb-05aa9839d1e7                                                                                                                                                                                                                                                                                          |
| name                 | global_http                                                                                                                                                                                                                                                                                                                   |
| security_group_rules | {"remote_group_id": null, "direction": "egress", "remote_ip_prefix": null, "protocol": null, "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": null, "security_group_id": "c6d78d56-7c56-4c82-abcb-05aa9839d1e7", "port_range_min": null, "ethertype": "IPv4", "id": "b2e56b3a-890b-48d3-9380-8a9f6f8b1b36"} |
|                      | {"remote_group_id": null, "direction": "egress", "remote_ip_prefix": null, "protocol": null, "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": null, "security_group_id": "c6d78d56-7c56-4c82-abcb-05aa9839d1e7", "port_range_min": null, "ethertype": "IPv6", "id": "153d84ba-651d-45fd-9015-58807749efc5"} |
| tenant_id            | 341f49145ec7445192dc3c2abc33500d                                                                                                                                                                                                                                                                                              |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Immediately after create, the security group has only an allow egress rule. To make it do what we want, we need to add some rules:

$ neutron security-group-rule-create [-h]
                                     [-f {html,json,json,shell,table,value,yaml,yaml}]
                                     [-c COLUMN] [--max-width <integer>]
                                     [--noindent] [--prefix PREFIX]
                                     [--request-format {json,xml}]
                                     [--tenant-id TENANT_ID]
                                     [--direction {ingress,egress}]
                                     [--ethertype ETHERTYPE]
                                     [--protocol PROTOCOL]
                                     [--port-range-min PORT_RANGE_MIN]
                                     [--port-range-max PORT_RANGE_MAX]
                                     [--remote-ip-prefix REMOTE_IP_PREFIX]
                                     [--remote-group-id REMOTE_GROUP]
                                     SECURITY_GROUP
$ neutron security-group-rule-create --direction ingress --ethertype IPv4 --protocol tcp --port-range-min 80 --port-range-max 80 --remote-ip-prefix 0.0.0.0/0 global_http
Created a new security_group_rule:
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| direction         | ingress                              |
| ethertype         | IPv4                                 |
| id                | 88ec4762-239e-492b-8583-e480e9734622 |
| port_range_max    | 80                                   |
| port_range_min    | 80                                   |
| protocol          | tcp                                  |
| remote_group_id   |                                      |
| remote_ip_prefix  | 0.0.0.0/0                            |
| security_group_id | c6d78d56-7c56-4c82-abcb-05aa9839d1e7 |
| tenant_id         | 341f49145ec7445192dc3c2abc33500d     |
+-------------------+--------------------------------------+

More complex rule sets can be built up through multiple invocations of neutron security-group-rule-create. For example, if you want to pass both http and https traffic, do this:

$ neutron security-group-rule-create --direction ingress --ethertype ipv4 --protocol tcp --port-range-min 443 --port-range-max 443 --remote-ip-prefix 0.0.0.0/0 global_http
Created a new security_group_rule:
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| direction         | ingress                              |
| ethertype         | IPv4                                 |
| id                | c50315e5-29f3-408e-ae15-50fdc03fb9af |
| port_range_max    | 443                                  |
| port_range_min    | 443                                  |
| protocol          | tcp                                  |
| remote_group_id   |                                      |
| remote_ip_prefix  | 0.0.0.0/0                            |
| security_group_id | c6d78d56-7c56-4c82-abcb-05aa9839d1e7 |
| tenant_id         | 341f49145ec7445192dc3c2abc33500d     |
+-------------------+--------------------------------------+

Despite only outputting the newly added rule, this operation is additive:

$ neutron security-group-show global_http
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field                | Value                                                                                                                                                                                                                                                                                                                                |
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| description          | allow web traffic from the Internet                                                                                                                                                                                                                                                                                                  |
| id                   | c6d78d56-7c56-4c82-abcb-05aa9839d1e7                                                                                                                                                                                                                                                                                                 |
| name                 | global_http                                                                                                                                                                                                                                                                                                                          |
| security_group_rules | {"remote_group_id": null, "direction": "egress", "remote_ip_prefix": null, "protocol": null, "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": null, "security_group_id": "c6d78d56-7c56-4c82-abcb-05aa9839d1e7", "port_range_min": null, "ethertype": "IPv6", "id": "153d84ba-651d-45fd-9015-58807749efc5"}        |
|                      | {"remote_group_id": null, "direction": "ingress", "remote_ip_prefix": "0.0.0.0/0", "protocol": "tcp", "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": 80, "security_group_id": "c6d78d56-7c56-4c82-abcb-05aa9839d1e7", "port_range_min": 80, "ethertype": "IPv4", "id": "88ec4762-239e-492b-8583-e480e9734622"}   |
|                      | {"remote_group_id": null, "direction": "egress", "remote_ip_prefix": null, "protocol": null, "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": null, "security_group_id": "c6d78d56-7c56-4c82-abcb-05aa9839d1e7", "port_range_min": null, "ethertype": "IPv4", "id": "b2e56b3a-890b-48d3-9380-8a9f6f8b1b36"}        |
|                      | {"remote_group_id": null, "direction": "ingress", "remote_ip_prefix": "0.0.0.0/0", "protocol": "tcp", "tenant_id": "341f49145ec7445192dc3c2abc33500d", "port_range_max": 443, "security_group_id": "c6d78d56-7c56-4c82-abcb-05aa9839d1e7", "port_range_min": 443, "ethertype": "IPv4", "id": "c50315e5-29f3-408e-ae15-50fdc03fb9af"} |
| tenant_id            | 341f49145ec7445192dc3c2abc33500d                                                                                                                                                                                                                                                                                                     |
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

The inverse operation is called security-group-rule-delete, specifying security-group-rule ID. Whole security groups can be removed with security-group-delete.

To create security group rules for a cluster of instances, use RemoteGroups.

RemoteGroups are a dynamic way of defining the CIDR of allowed sources. The user specifies a RemoteGroup (security group name) and then all the users' other instances using the specified RemoteGroup are selected dynamically. This dynamic selection alleviates the need for individual rules to allow each new member of the cluster.

The code is similar to the above example of security-group-rule-create. To use RemoteGroup, specify --remote-group-id instead of --remote-ip-prefix. For example:

$ neutron security-group-rule-create --direction ingress \
        --ethertype IPv4 --protocol tcp --port-range-min 22 --port-range-max 22 --remote-group-id global_http cluster

The "cluster" rule allows SSH access from any other instance that uses the global-http group.

Questions? Discuss on ask.openstack.org
Found an error? Report a bug against this page

loading table of contents...