# How to Create Security Group Rules

Source: https://docs.quake.ai/docs/network/how-to/create-security-group-rules
Markdown: https://docs.quake.ai/docs/network/how-to/create-security-group-rules.md

---

# How to create security group rules

Add rules to an existing security group to control which traffic can reach your instances. Rules define the protocol, port range, direction, and source for allowed traffic.

<PrerequisiteBlock methods={["console", "cli", "api"]}>

You need an existing [security group](/docs/network/how-to/create-security-group) to add rules to.

</PrerequisiteBlock>

## Understanding rules

Security group rules control traffic using these properties:

- **Protocol**: TCP, UDP, or ICMP (selected via the **Protocol** dropdown, which also offers presets and wildcards described below)
- **Port**: single port (for example, `22`) or range (for example, `80:160`; note the colon separator the live UI accepts, not a dash)
- **Direction**: Ingress (inbound) or Egress (outbound)
- **Source**: All traffic (`0.0.0.0/0`), a CIDR range, or another security group
- **Ether Type**: IPv4 or IPv6

The *default security group* allows all outbound traffic and all inbound traffic from other members of the same group. Custom groups start with only egress rules.

## Protocol dropdown contents

The Create Rule dialog's **Protocol** dropdown exposes ten options in the following order on the live the Console:

| Order | Option | Behavior |
|---|---|---|
| 1 | **Custom TCP Rule** | Free-form TCP rule; you set Port, Direction, Source. |
| 2 | **Custom UDP Rule** | Free-form UDP rule; same fields as above. |
| 3 | **Custom ICMP Rule** | Free-form ICMP rule (no port input). |
| 4 | **All Proto** | Wildcard: allow every protocol (TCP, UDP, ICMP, etc.) on the matched flow. |
| 5 | **All TCP** | Wildcard: allow every TCP port. |
| 6 | **All UDP** | Wildcard: allow every UDP port. |
| 7 | **All ICMP** | Wildcard: allow every ICMP type. |
| 8 | **SSH** | TCP/22 preset. Sets the protocol and hides the Port and Port Type fields. |
| 9 | **SMTP** | TCP/25 preset. Same hide-fields behavior. |
| 10 | **DNS** | TCP and UDP/53 preset. Same hide-fields behavior. |

The quickstart's [Create a security group](/docs/quickstart#3-create-a-security-group) section walks the SSH preset end-to-end against a live security group.



The wildcard options (**All Proto**, **All TCP**, **All UDP**, **All ICMP**) open a far broader surface than narrow port rules. Use them only when the source is tightly constrained (a specific CIDR or another security group), never paired with the `0.0.0.0/0` open-to-internet source.





**No HTTP or HTTPS preset.** The Cloud Console's Protocol dropdown does not include HTTP or HTTPS presets. For web traffic, use **Custom TCP Rule** with `Port` set to `80` (HTTP), `443` (HTTPS), or the range `80:443` to cover both. Other common ports follow the same pattern: `3306` (MySQL), `3389` (RDP), and so on.



## Add rules to a security group

<MethodTabs>
<Method label="Console">

<NoMoreButton />

1. Go to **Network** > **Security Groups**.
2. Find the security group. On its row, open the **Settings** gear icon dropdown and select **Create Rule**. Alternatively, click the group name to open its detail page and use the **Create Rule** button on the Rules section. The dialog title is **Create Rule**.
3. Check the dialog's defaults before you change anything. When it opens, **Protocol** is pre-selected to **Custom TCP Rule**, **Direction** to **Ingress**, **Ether Type** to **IPv4**, **Port Type** to **Custom**, and **Source** to **All Traffic** (`0.0.0.0/0`). Submitting without changes (after you set **Port**) creates a TCP ingress rule open to all sources, so adjust these fields if your rule needs different values.
4. Choose an option from the **Protocol** dropdown (see [Protocol dropdown contents](#protocol-dropdown-contents) above for the full list). Selecting a preset like **SSH**, **SMTP**, or **DNS** does not visibly fill the port: it hides the **Port Type** and **Port** fields and submits the rule with the built-in port for that preset (**SSH** uses TCP port 22, **SMTP** uses TCP port 25, and **DNS** uses TCP and UDP port 53). The chosen port appears in the **Rules** table after submission, for example `SSH (22)`.
5. For a custom rule, set the remaining fields:
   - **Direction**: `Ingress` or `Egress` (default `Ingress` on the SG detail page).
   - **Ether Type**: `IPv4` or `IPv6` (default `IPv4`).
   - **Port Type**: `Custom` for a literal port or range; the dropdown also offers preset port-type values that gate the Port input.
   - **Port**: single port like `22` or a range like `80:160`. The helper text reads `Enter port or port range(example: 80 or 80:160)`; note the colon separator.
   - **Source**: `All Traffic` (`0.0.0.0/0`), a specific CIDR, or another security group.
6. Select **OK** to create the rule.

Repeat for each rule you need. Common starting point: add SSH (port 22) for remote access.

</Method>
<Method label="CLI">

Allow SSH (port 22) from any source:

```bash
openstack security group rule create \
  --protocol tcp \
  --dst-port 22 \
  --remote-ip 0.0.0.0/0 \
  my-security-group
```

Allow HTTP (port 80):

```bash
openstack security group rule create \
  --protocol tcp \
  --dst-port 80 \
  --remote-ip 0.0.0.0/0 \
  my-security-group
```

Allow HTTPS (port 443):

```bash
openstack security group rule create \
  --protocol tcp \
  --dst-port 443 \
  --remote-ip 0.0.0.0/0 \
  my-security-group
```

Allow ICMP (ping):

```bash
openstack security group rule create \
  --protocol icmp \
  my-security-group
```



Restrict SSH to your IP for better security:
`openstack security group rule create --protocol tcp --dst-port 22 --remote-ip YOUR_IP/32 my-security-group`



</Method>
<Method label="API">

Allow SSH (port 22):

```bash
curl -X POST "$OS_NETWORK_URL/v2.0/security-group-rules" \
  -H "X-Auth-Token: $OS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "security_group_rule": {
      "security_group_id": "SECURITY_GROUP_ID",
      "direction": "ingress",
      "ethertype": "IPv4",
      "protocol": "tcp",
      "port_range_min": 22,
      "port_range_max": 22,
      "remote_ip_prefix": "0.0.0.0/0"
    }
  }'
```

Allow HTTP (port 80):

```bash
curl -X POST "$OS_NETWORK_URL/v2.0/security-group-rules" \
  -H "X-Auth-Token: $OS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "security_group_rule": {
      "security_group_id": "SECURITY_GROUP_ID",
      "direction": "ingress",
      "ethertype": "IPv4",
      "protocol": "tcp",
      "port_range_min": 80,
      "port_range_max": 80,
      "remote_ip_prefix": "0.0.0.0/0"
    }
  }'
```




```python
import openstack

conn = openstack.connect(cloud="rumble")

sg = conn.network.find_security_group("my-security-group")

for port in [22, 80, 443]:
    conn.network.create_security_group_rule(
        security_group_id=sg.id,
        direction="ingress",
        ethertype="IPv4",
        protocol="tcp",
        port_range_min=port,
        port_range_max=port,
        remote_ip_prefix="0.0.0.0/0",
    )

print(f"Rules added to {sg.name}")
```




</Method>
</MethodTabs>

## Verify the result

<MethodTabs>
<Method label="Console">

Open the security group detail page. The **Rules** tab shows all active rules with their protocol, port, direction, and source.

</Method>
<Method label="CLI">

```bash
openstack security group rule list my-security-group
```

</Method>
<Method label="API">

```bash
curl -s "$OS_NETWORK_URL/v2.0/security-group-rules?security_group_id=SECURITY_GROUP_ID" \
  -H "X-Auth-Token: $OS_TOKEN" | python3 -m json.tool
```

</Method>
</MethodTabs>

## See also

- [Create a security group](/docs/network/how-to/create-security-group)
- [Security groups CLI reference](/reference/network/security-groups-cli)
- [Security groups console](/reference/network/console/security-groups)
- [Security groups concepts](/docs/network/concepts/security-groups)
