Configure firewall

When not using Docker

The firewall.sh script closes most ports by default. Its behavior is controlled by variables in the firewall-settings.local file.

Most variables are set by state files:

SSH_IPV4 and SSH_IPV6

IPs from which to allow SSH collections. Set by the firewall state using Pillar data. See Connect to a server (SSH).

PUBLIC_HTTP

Opens port 80. Set by the apache state.

PUBLIC_HTTPS

Opens port 443. Set by the apache state.

PUBLIC_POSTGRESQL

Opens port 5432. Set by the postgres state, if postgres.public_access is True in Pillar.

PRIVATE_POSTGRESQL

Opens port 5432 to the replica servers. Set by the postgres state, if postgres.public_access isn’t True in Pillar.

REPLICA_IPV4 and REPLICA_IPV6

The IPs of replica servers. Set by the postgres state using Pillar data, if postgres.public_access isn’t True in Pillar.

PUBLIC_ELASTICSEARCH

Opens port 9200. Set by the elasticsearch state.

PUBLIC_TINYPROXY

Opens port 8888. Set by the tinyproxy state.

PRIVATE_PROMETHEUS_CLIENT

Opens port 7231 to the Prometheus server. Set by the prometheus.node_exporter state.

PROMETHEUS_IPV4 and PROMETHEUS_IPV6

The IPs of the Prometheus server. Set by the prometheus.node_exporter state using Pillar data.

Other variables are:

PUBLIC_SSH

Opens port 22. Supersedes port knocking.

Open a port

If no variable corresponds to the port you need to open, update the firewall.sh script and firewall-settings.local template.

You might need to set variables if you’re working in a development environment. To set a variable, use the set_firewall macro, for example:

{{ set_firewall('PUBLIC_SSH') }}

This sets PUBLIC_SSH="yes" in the firewall-settings.local file.

Close a port

Use the unset_firewall macro if a set_firewall call is removed from a service’s state, whether directly (by deleting a set_firewall call) or indirectly (by un-including a state file with set_firewall calls).

Troubleshoot

When making changes to firewall settings or port assignments, you might want to:

  • Check if a port is open:

    telnet host port
    
  • List active connections:

    ss -tupln # netstat -tupln
    

When using Docker

The firewall.sh script rewrites all iptables rules. However, Docker needs to add rules to route traffic to and from containers. To address this incompatibility, the firewall.sh script exits if the docker command exists. To implement firewall rules on Docker servers, we implement an external firewall.

  1. Connect to the server

  2. Configure the external firewall:

    Linode provide a stateful Cloud Firewall. Stateful firewalls can store information about connections over time, which is required for HTTP sessions and port knocking, for example.

    1. Log into Linode

    2. Click the Firewalls menu item

    3. Click the Create Firewall button

      1. Enter the server name in Label

      2. Select the server from the Linodes dropdown

      3. Click the Create Firewall button

    4. Click the new firewall’s label

      1. Select “Drop” from the Default inbound policy dropdown

      2. Add an inbound rule. The recommended minimum is:

        Label

        Protocol

        Ports

        Sources

        Action

        Allow-SSH

        TCP

        SSH (22)

        All IPv4, All IPv6

        Accept

        Allow-ICMP

        ICMP

        All IPv4, All IPv6

        Accept

        Allow-Prometheus

        TCP

        7231

        139.162.253.17/32, 2a01:7e00::f03c:93ff:fe13:a12c/128

        Accept

        Most servers will also have:

        Label

        Protocol

        Ports

        Sources

        Action

        Allow-HTTP

        TCP

        HTTP (80), HTTPS (443)

        All IPv4, All IPv6

        Accept

      3. Click the Save Changes button

    1. Log into Hetzner Cloud Console

    2. Click the Default project

    3. Select the server

    4. Click the Firewalls tab, and either:

      1. Click the Apply Firewall button to reuse existing firewalls

        1. Click the default firewall

        2. Click the web firewall, if appropriate

        3. Click the Apply # Firewall(s) button

      2. Click the Create Firewall button to create a new firewall

        1. Click the Add rule button under the Inbound rules heading. The default firewall is:

          IPs

          Protocol

          Port

          Any IPv4, Any IPv6

          TCP

          22

          Any IPv4, Any IPv6

          ICMP

          139.162.253.17/32, 2a01:7e00::f03c:93ff:fe13:a12c/128

          TCP

          7231

          The web firewall is:

          IPs

          Protocol

          Port

          Any IPv4, Any IPv6

          TCP

          80

          Any IPv4, Any IPv6

          TCP

          443

        2. Enter a name in Firewall name (“postgres”, for example)

        3. Click the Create Firewall button

    Hetzner Dedicated provide a free stateless firewall for each dedicated server. “Stateless” means that the firewall does not store information about connections over time, which is required for HTTP sessions and port knocking, for example.

    1. Log into Hetzner Robot

    2. Select the server

    3. Click the Firewall tab

    4. Select “active” from the Status dropdown

    5. Check the Filter IPv6 packets box

    6. Check the Hetzner Services (incoming) box

    7. Select “SSH” from the Firewall template: dropdown and click Apply to fill in:

      Name

      Protocol

      Source port

      Destination port

      TCP flags

      Action

      icmp

      icmp

      0-65535

      accept

      ssh

      tcp

      22

      accept

      tcp established

      tcp

      32768-65535

      ack

      accept

      dns

      udp

      53

      accept

      Or, select “Webserver” from the Firewall template: dropdown and click Apply to also fill in:

      Name

      Protocol

      Destination port

      TCP flags

      Action

      http

      tcp

      80,443

      accept

    8. Add additional firewall rules. The recommended minimum is to also add:

      Name

      Protocol

      Source IP

      Destination port

      TCP flags

      Action

      prometheus

      tcp

      139.162.253.17/32

      7231

      accept

    9. Duplicate each firewall rule, suffixing -v6 to Name and setting Version to ipv6.

      Note

      Rules are duplicated, because Protocol can’t be set if Version is *. Skip the icmp and prometheus rules for ipv6 due to Hetzner limitations.

    10. Click Save and wait for the configuration to be applied.

    Note

    Destination IP and Source port are never set.

  3. Reset the server-side firewall:

    /home/sysadmin-tools/bin/firewall_reset.sh
    
  4. Restart the Docker service, if running:

    systemctl restart docker
    

Troubleshoot

If you configure an external firewall without resetting the server-side firewall, the server becomes inaccessible. Either:

Recovery
Firewall
  • Open port 8255 in the external firewall

  • Connect to the server as the root user

  • Run /home/sysadmin-tools/bin/firewall_reset.sh

  • Close port 8255 in the external firewall

Note

On Azure, instead of the root user, use the ocpadmin user, and run commands with sudo.